|
|
1.1 ! root 1: ! 2: #include <assert.h> ! 3: #include <stdio.h> ! 4: #include <stdlib.h> ! 5: #include <string.h> ! 6: #include <ctype.h> ! 7: #include <stdarg.h> ! 8: #include "dict.h" ! 9: #include "as68k.h" ! 10: #include "output.h" ! 11: ! 12: static op_t pending; ! 13: static enum M68K_OPS next_op_type; ! 14: static char *pending_labels, *cur_labels; ! 15: static int cur_bitpos; ! 16: /* last instruction was a jsr/bsr, so must create an entry ! 17: * in the computed jump table for return point (this instr) */ ! 18: static int return_target; ! 19: ! 20: #define LABBUF_LEN 32768 ! 21: ! 22: /* enable bounds checking and debug info in the generated turd */ ! 23: #define GEN_DEBUG ! 24: //#define DUMP_LOADS_OF_CRAP ! 25: ! 26: /* which flags an M68K_OP thingy may set */ ! 27: #define fZ (1<<0) ! 28: #define fNVC (1<<1) ! 29: #define fX (1<<2) ! 30: #define fNZVCX (fZ | fNVC | fX) ! 31: #define fNZVC (fZ | fNVC) ! 32: #define fNVCX (fX | fNVC) ! 33: #define _fSafe 0 ! 34: /* _fSafe are ones i haven't got round to doing yet. */ ! 35: ! 36: /* does the flag need to be set? if the next instruction will ! 37: * set the flag then no. */ ! 38: #define ifZ if(!(sets_flags[next_op_type] & fZ)) ! 39: #define ifNVC if(!(sets_flags[next_op_type] & fNVC)) ! 40: #define ifZNVC if((!(sets_flags[next_op_type] & fZ)) || (!(sets_flags[next_op_type] & fNVC))) ! 41: #define ifNVCX if((!(sets_flags[next_op_type] & fNVCX))) ! 42: #define ifX if(!(sets_flags[next_op_type] & fX)) ! 43: ! 44: /* XXX ONLY SET X FLAG FOR INSTRUCTIONS THAT OVERWRITE ! 45: * THE X FLAG __WITHOUT__ USING IT */ ! 46: ! 47: static int sets_flags[OP_MAX+1] = { ! 48: _fSafe, /* OP_NONE */ ! 49: 0, // OP_JMP ! 50: fZ, // OP_BCHG ! 51: fZ, // OP_BCLR ! 52: fZ, // OP_BSET ! 53: fZ, // OP_BTST ! 54: fNZVC, // OP_MULS ! 55: fNZVC, // OP_MULU, ! 56: fNZVC, // OP_AND ! 57: fNZVC, // OP_OR ! 58: fNZVC, // OP_XOR ! 59: fNZVC, // OP_NOT ! 60: fNZVC, // OP_NEGX ! 61: fNZVC, // OP_NEG ! 62: fNZVC, // OP_DIVU ! 63: fNZVC, // OP_DIVS ! 64: fNZVC, // OP_ASL, ! 65: fNZVCX, // OP_LSL ! 66: fNZVC, // OP_ROXR ! 67: fNZVC, // OP_ROXL ! 68: fNZVC, // OP_ROL ! 69: fNZVC, // OP_ROR ! 70: fNZVC, // OP_ASR ! 71: fNZVC, // OP_LSR, ! 72: 0, // OP_MOVEM ! 73: fNZVC, // OP_SUBX ! 74: fNZVC, // OP_ADDX ! 75: fNZVCX, // OP_ADD ! 76: fNZVC, // OP_CMPA ! 77: fNZVC, // OP_CMP ! 78: fNZVCX, // OP_SUB, ! 79: _fSafe, // OP_ADDA ! 80: _fSafe, // OP_SUBA ! 81: fNZVC, // OP_SWAP ! 82: _fSafe, // OP_JSR ! 83: 0, // OP_BCC ! 84: 0, // OP_DBCC ! 85: fNZVC, // OP_CLR, ! 86: 0, // OP_EXG ! 87: fNZVC, // OP_EXT ! 88: 0, // OP_RTE ! 89: 0, // OP_RTS ! 90: 0, // OP_ILLEGAL ! 91: 0, // OP_HCALL ! 92: 0, // OP_LINK, ! 93: 0, // OP_UNLK ! 94: fNZVC, // OP_MOVE ! 95: _fSafe, // OP_MOVEA ! 96: fNZVC, // OP_TST ! 97: 0, // OP_PEA ! 98: 0, // OP_LEA ! 99: 0, // OP_SCC ! 100: _fSafe, // OP_MAX..... ! 101: }; ! 102: ! 103: FILE *asm_out; ! 104: ! 105: static void output_op (op_t *op, op_t *next); ! 106: static void init_regalloc (); ! 107: static void xflush_all (); ! 108: ! 109: /* raw output */ ! 110: static void rout (const char *str) ! 111: { ! 112: fputs (str, asm_out); ! 113: } ! 114: ! 115: /* formatted output */ ! 116: static void xout (const char *format, ...) ! 117: { ! 118: va_list argptr; ! 119: ! 120: va_start (argptr, format); ! 121: vfprintf (asm_out, format, argptr); ! 122: va_end (argptr); ! 123: } ! 124: static void xln (const char *format, ...) ! 125: { ! 126: va_list argptr; ! 127: ! 128: fputc ('\t', asm_out); ! 129: va_start (argptr, format); ! 130: vfprintf (asm_out, format, argptr); ! 131: va_end (argptr); ! 132: fputc ('\n', asm_out); ! 133: } ! 134: ! 135: static int regpos (int num) ! 136: { ! 137: assert ((num >=0) && (num < 16)); ! 138: return -64 + 4*num; ! 139: } ! 140: ! 141: #ifdef GEN_DEBUG ! 142: static void set_line (int num) ! 143: { ! 144: char buf[256]; ! 145: ! 146: snprintf (buf, sizeof (buf), " movl $%d, line_no\n", num); ! 147: strcat (cur_labels, buf); ! 148: } ! 149: #endif ! 150: ! 151: static int pending_flush, cur_flush; ! 152: ! 153: void i386_label (const char *lab) ! 154: { ! 155: char buf[256]; ! 156: ! 157: /* lines that might be jumped to must have a consistent ! 158: * register state, so flush registers to memory before ! 159: * these lines. */ ! 160: cur_flush = 1; ! 161: ! 162: snprintf (buf, sizeof (buf), "__N%s:\n", lab); ! 163: strcat (cur_labels, buf); ! 164: ! 165: add_fixup (0, C_ADDR, lab); ! 166: } ! 167: ! 168: void i386_addr_label (int labelled) ! 169: { ! 170: char buf[256]; ! 171: ! 172: if (labelled) { ! 173: cur_flush = 1; ! 174: } ! 175: ! 176: if (labelled || return_target) { ! 177: snprintf (buf, sizeof (buf), "__l%x", get_bitpos ()); ! 178: add_fixup (get_bitpos (), C_ADDR, buf); ! 179: ! 180: snprintf (buf, sizeof (buf), "__l%x:\n", get_bitpos ()); ! 181: strcat (cur_labels, buf); ! 182: } else { ! 183: #ifdef GEN_DEBUG ! 184: snprintf (buf, sizeof (buf), "/* 0x%x */\n", get_bitpos ()); ! 185: strcat (cur_labels, buf); ! 186: #endif ! 187: } ! 188: ! 189: cur_bitpos = get_bitpos (); ! 190: ! 191: #ifdef GEN_DEBUG ! 192: set_line (line_no); ! 193: ! 194: #ifdef DUMP_LOADS_OF_CRAP ! 195: strcat (cur_labels, " call DumpRegsChanged\n"); ! 196: #endif /* DUMP_LOADS_OF_CRAP */ ! 197: #endif /* GEN_DEBUG */ ! 198: } ! 199: ! 200: #ifdef WIN32 ! 201: void winsym (const char *sym) ! 202: { ! 203: xout ("#define %s _%s\n", sym, sym); ! 204: } ! 205: #endif /* WIN32 */ ! 206: ! 207: void i386_begin (const char *src_filename, const char *bin_filename) ! 208: { ! 209: char buf[128]; ! 210: snprintf (buf, sizeof (buf), ".%s.S", src_filename); ! 211: if ((asm_out = fopen (buf, "w"))==NULL) { ! 212: fprintf (stderr, "Error: Cannot open %s for writing.\n", buf); ! 213: exit (-1); ! 214: } ! 215: ! 216: init_regalloc (); ! 217: ! 218: pending_labels = NULL; ! 219: cur_labels = calloc (LABBUF_LEN, 1); ! 220: ! 221: xout ("#define MEM_SIZE 0x110000\n"); ! 222: xout ("#define PROC_STATE 64\n"); ! 223: xout ("#define MemBase STData+PROC_STATE\n\n"); ! 224: ! 225: xln (".data"); ! 226: /* memory size + registers */ ! 227: xln (".comm STData,MEM_SIZE+PROC_STATE"); ! 228: xln (".comm X,4"); ! 229: xln (".comm N,4"); ! 230: xln (".comm Z,4"); ! 231: xln (".comm V,4"); ! 232: xln (".comm C,4"); ! 233: /* register backing store for during exception handling */ ! 234: xln (".comm bX,4"); ! 235: xln (".comm bN,4"); ! 236: xln (".comm bZ,4"); ! 237: xln (".comm bV,4"); ! 238: xln (".comm bC,4"); ! 239: /* exception return address */ ! 240: xln (".comm rdest,4"); ! 241: xln (".comm exceptions_pending_mask,4"); ! 242: xln (".comm exceptions_pending_nums,32"); ! 243: xln (".comm exception_handlers,4*32"); ! 244: xln (".comm line_no,4"); ! 245: #ifdef GEN_DEBUG ! 246: xout ("debugstr: .string \"$%%x $%%x $%%x $%%x $%%x $%%x $%%x $%%x*$%%x $%%x $%%x $%%x $%%x $%%x $%%x $%%x:%%d\\n\"\n"); ! 247: #endif ! 248: xout (" .global STRam\n"); ! 249: xout ("STRam: .long STData+PROC_STATE\n"); ! 250: ! 251: xout (" .section .rodata\n"); ! 252: xout ("bin_filename: .string \"%s\"\n", bin_filename); ! 253: xout ("open_mode: .string \"r\"\n\n"); ! 254: xout ("dreg_fmt: .string \"D%%d = $%%08x\t\"\n"); ! 255: xout ("areg_fmt: .string \"A%%d = $%%08x\\n\"\n"); ! 256: xout ("cr: .string \"\\n\"\n"); ! 257: xout ("cc_names: .string \"XNZVC\"\n"); ! 258: xout ("hex_fmt: .string \"$%%02x \"\n"); ! 259: xout ("illegal_fmt: .string \"Illegal instruction at line %%d.\\n\"\n"); ! 260: ! 261: xout (" .text\n"); ! 262: ! 263: xout (".globl SetZFlag\n"); ! 264: xout ("SetZFlag:\n"); ! 265: rout ( ! 266: " movl 4(%esp),%eax\n" ! 267: " movb %al,Z\n" ! 268: " ret\n"); ! 269: ! 270: xout (".globl GetXFlag\n"); ! 271: xout ("GetXFlag:\n"); ! 272: rout ( ! 273: " movl X,%eax\n" ! 274: " ret\n"); ! 275: ! 276: xout (".globl GetZFlag\n"); ! 277: xout ("GetZFlag:\n"); ! 278: rout ( ! 279: " movl Z,%eax\n" ! 280: " ret\n"); ! 281: ! 282: xout (".globl GetCFlag\n"); ! 283: xout ("GetCFlag:\n"); ! 284: rout ( ! 285: " movl C,%eax\n" ! 286: " ret\n"); ! 287: ! 288: xout (".globl GetNFlag\n"); ! 289: xout ("GetNFlag:\n"); ! 290: rout ( ! 291: " movl N,%eax\n" ! 292: " ret\n"); ! 293: ! 294: xout (".globl GetVFlag\n"); ! 295: xout ("GetVFlag:\n"); ! 296: rout ( ! 297: " movl V,%eax\n" ! 298: " ret\n"); ! 299: ! 300: xout (".globl DumpRegs\n"); ! 301: xout ("DumpRegs:\n"); ! 302: rout ( ! 303: " pushl %ebp\n" ! 304: " pushl %ebx\n" ! 305: " pushl %ecx\n" ! 306: " pushl %esi\n" ! 307: " movl $STData,%ebx\n" ! 308: " xorl %eax,%eax\n" ! 309: "1: pushl %eax\n" ! 310: " pushl (%ebx,%eax,4)\n" ! 311: " pushl %eax\n" ! 312: " pushl $dreg_fmt\n" ! 313: " call printf\n" ! 314: " addl $12,%esp\n" ! 315: " movl (%esp),%eax\n" ! 316: " pushl 8*4(%ebx,%eax,4)\n" ! 317: " pushl %eax\n" ! 318: " pushl $areg_fmt\n" ! 319: " call printf\n" ! 320: " addl $12,%esp\n" ! 321: " popl %eax\n" ! 322: " inc %eax\n" ! 323: " cmpl $8,%eax\n" ! 324: " jl 1b\n" ! 325: /* print status flags */ ! 326: " movb X,%al\n" ! 327: " movl $0,%ecx\n" ! 328: " call print_scat\n" ! 329: " movb N,%al\n" ! 330: " movl $1,%ecx\n" ! 331: " call print_scat\n" ! 332: " movb Z,%al\n" ! 333: " movl $2,%ecx\n" ! 334: " call print_scat\n" ! 335: " movb V,%al\n" ! 336: " movl $3,%ecx\n" ! 337: " call print_scat\n" ! 338: " movb C,%al\n" ! 339: " movl $4,%ecx\n" ! 340: " call print_scat\n" ! 341: " pushl $cr\n" ! 342: " call printf\n" ! 343: " addl $4,%esp\n" ! 344: /* print memory contents */ ! 345: ! 346: " movl $STData+PROC_STATE,%esi\n" ! 347: " movl $MEM_SIZE,%ebx\n" ! 348: "1: movzbl (%esi),%eax\n" ! 349: " pushl %eax\n" ! 350: " pushl $hex_fmt\n" ! 351: " call printf\n" ! 352: " addl $8,%esp\n" ! 353: " inc %esi\n" ! 354: " dec %ebx\n" ! 355: ! 356: " testl $15,%ebx\n" ! 357: " jz 3f\n" ! 358: ! 359: "2: testl %ebx,%ebx\n" ! 360: " jnz 1b\n" ! 361: ! 362: ! 363: " popl %esi\n" ! 364: " popl %ecx\n" ! 365: " popl %ebx\n" ! 366: " popl %ebp\n" ! 367: " ret\n" ! 368: ! 369: "3: pushl $cr\n" ! 370: " call printf\n" ! 371: " addl $4,%esp\n" ! 372: " jmp 2b\n" ! 373: ! 374: "print_scat:\n" ! 375: " xorl %ebx,%ebx\n" ! 376: " cmpb %al,%bl\n" ! 377: " jz 1f\n" ! 378: " movb cc_names(%ecx),%al\n" ! 379: " pushl %eax\n" ! 380: " call putchar\n" ! 381: " addl $4,%esp\n" ! 382: "1: ret\n" ! 383: ); ! 384: ! 385: xout (".globl FlagException\n"); ! 386: xout ("FlagException:\n"); ! 387: rout ( ! 388: " movl 4(%esp),%eax\n" ! 389: " btsl %eax,exceptions_pending_mask\n" ! 390: " incb exceptions_pending_nums(%eax)\n" ! 391: " ret\n"); ! 392: ! 393: xout (".globl MemReadByte\n"); ! 394: xout ("MemReadByte:\n"); ! 395: rout ( ! 396: " movl 4(%esp),%eax\n" ! 397: " movsbl STData+PROC_STATE(%eax),%eax\n" ! 398: " ret\n"); ! 399: ! 400: xout (".globl MemReadWord\n"); ! 401: xout ("MemReadWord:\n"); ! 402: rout ( ! 403: " movl 4(%esp),%eax\n" ! 404: " movswl STData+PROC_STATE(%eax),%eax\n" ! 405: " xchg %al,%ah\n" ! 406: " ret\n"); ! 407: ! 408: xout (".globl MemReadLong\n"); ! 409: xout ("MemReadLong:\n"); ! 410: rout ( ! 411: " movl 4(%esp),%eax\n" ! 412: " movl STData+PROC_STATE(%eax),%eax\n" ! 413: " bswap %eax\n" ! 414: " ret\n"); ! 415: ! 416: xout (".globl MemWriteByte\n"); ! 417: xout ("MemWriteByte:\n"); ! 418: rout ( ! 419: " movl 4(%esp),%eax\n" ! 420: " movl 8(%esp),%edx\n" ! 421: " movb %dl,STData+PROC_STATE(%eax)\n" ! 422: " ret\n"); ! 423: ! 424: xout (".globl MemWriteWord\n"); ! 425: xout ("MemWriteWord:\n"); ! 426: rout ( ! 427: " movl 8(%esp),%edx\n" ! 428: " movl 4(%esp),%eax\n" ! 429: " xchg %dl,%dh\n" ! 430: " movw %dx,STData+PROC_STATE(%eax)\n" ! 431: " ret\n"); ! 432: ! 433: xout (".globl MemWriteLong\n"); ! 434: xout ("MemWriteLong:\n"); ! 435: rout ( ! 436: " movl 8(%esp),%edx\n" ! 437: " movl 4(%esp),%eax\n" ! 438: " bswap %edx\n" ! 439: " movl %edx,STData+PROC_STATE(%eax)\n" ! 440: " ret\n"); ! 441: ! 442: xout (".globl GetReg\n"); ! 443: xout ("GetReg:\n"); ! 444: rout ( ! 445: " movl 4(%esp),%eax\n" ! 446: " movl STData(,%eax,4),%eax\n" ! 447: " ret\n"); ! 448: ! 449: xout (".globl SetReg\n"); ! 450: xout ("SetReg:\n"); ! 451: rout ( ! 452: " movl 4(%esp),%eax\n" ! 453: " movl 8(%esp),%edx\n" ! 454: " movl %edx,STData(,%eax,4)\n" ! 455: " ret\n"); ! 456: ! 457: xout (".globl Init680x0\n"); ! 458: xout ("Init680x0:\n"); ! 459: rout ( ! 460: " pushl %esi\n" ! 461: " pushl %ebx\n" ! 462: " pushl $open_mode\n" ! 463: " pushl $bin_filename\n" ! 464: " call fopen\n" ! 465: " movl %eax, %ebx\n" ! 466: " popl %eax\n" ! 467: " xorl %eax, %eax\n" ! 468: " testl %ebx, %ebx\n" ! 469: " popl %edx\n" ! 470: " je 1f\n" ! 471: " pushl $2\n" ! 472: " pushl $0\n" ! 473: " pushl %ebx\n" ! 474: " call fseek\n" ! 475: " pushl %ebx\n" ! 476: " call ftell\n" ! 477: " pushl $0\n" ! 478: " movl %eax, %esi\n" ! 479: " pushl $0\n" ! 480: " pushl %ebx\n" ! 481: " call fseek\n" ! 482: " addl $28, %esp\n" ! 483: " xorl %eax, %eax\n" ! 484: " cmpl $MEM_SIZE, %esi\n" ! 485: " jge 1f\n" ! 486: " pushl %ebx\n" ! 487: " pushl %esi\n" ! 488: " pushl $1\n" ! 489: " pushl $STData+PROC_STATE\n" ! 490: " call fread\n" ! 491: " pushl %ebx\n" ! 492: " call fclose\n" ! 493: " movl $1, %eax\n" ! 494: " addl $20, %esp\n" ! 495: "1:\n" ! 496: " popl %ebx\n" ! 497: " popl %esi\n" ! 498: " ret\n"); ! 499: ! 500: xout (".globl Start680x0\n"); ! 501: xout ("Start680x0:\n"); ! 502: xout (" pushl %%ebp\n"); ! 503: xout (" pushl %%esi\n"); ! 504: xout (" pushl %%edi\n"); ! 505: xout (" pushl %%edx\n"); ! 506: xout (" pushl %%ecx\n"); ! 507: xout (" pushl %%ebx\n"); ! 508: xout (" movl $STData+PROC_STATE,%%ebp\n\n"); ! 509: //xout (" movl $0x110000,Regs+15*4"); ! 510: // xout (" movl $0x1c,%%edx"); ! 511: ! 512: // xout (" jmp jumptable"); ! 513: } ! 514: ! 515: static void do_pending (); ! 516: ! 517: void i386_end (const char *src_filename) ! 518: { ! 519: /* some more crap needs to be added to the top */ ! 520: int prev, i; ! 521: char c, buf[128]; ! 522: FILE *f; ! 523: struct Fixup *fix; ! 524: struct Label *lab; ! 525: ! 526: /* output last instruction */ ! 527: next_op_type = OP_NONE; ! 528: do_pending (); ! 529: ! 530: xout ("\n"); ! 531: xflush_all (); ! 532: xln ("popl %%ebx"); ! 533: xln ("popl %%ecx"); ! 534: xln ("popl %%edx"); ! 535: xln ("popl %%edi"); ! 536: xln ("popl %%esi"); ! 537: xln ("popl %%ebp"); ! 538: xln ("ret"); ! 539: ! 540: fclose (asm_out); ! 541: ! 542: snprintf (buf, sizeof (buf), "%s.S", src_filename); ! 543: if ((asm_out = fopen (buf, "w"))==NULL) { ! 544: fprintf (stderr, "Error: Cannot open %s for writing.\n", buf); ! 545: exit (-1); ! 546: } ! 547: ! 548: #ifdef WIN32 ! 549: winsym ("printf"); ! 550: winsym ("hcalls"); ! 551: winsym ("fopen"); ! 552: winsym ("fseek"); ! 553: winsym ("ftell"); ! 554: winsym ("fclose"); ! 555: winsym ("abort"); ! 556: winsym ("putchar"); ! 557: winsym ("fread"); ! 558: winsym ("SetReg"); ! 559: winsym ("GetReg"); ! 560: winsym ("STRam"); ! 561: winsym ("MemReadLong"); ! 562: winsym ("MemReadWord"); ! 563: winsym ("MemReadByte"); ! 564: winsym ("MemWriteLong"); ! 565: winsym ("MemWriteWord"); ! 566: winsym ("MemWriteByte"); ! 567: winsym ("GetZFlag"); ! 568: winsym ("GetNFlag"); ! 569: winsym ("GetVFlag"); ! 570: winsym ("GetCFlag"); ! 571: winsym ("GetXFlag"); ! 572: winsym ("Init680x0"); ! 573: winsym ("Start680x0"); ! 574: winsym ("FlagException"); ! 575: winsym ("line_no"); ! 576: winsym ("exception_handlers"); ! 577: #endif /* WIN32 */ ! 578: ! 579: /* address 'fixups' */ ! 580: fix = fix_first; ! 581: for (; fix != NULL; fix = fix->next) { ! 582: if (fix->size != C_ADDR) continue; ! 583: ! 584: lab = get_label (fix->label); ! 585: if ((fix->adr != 0) || (!lab)) { ! 586: continue; ! 587: } ! 588: xout ("#define __D%s 0x%x\n", lab->name, lab->val+BASE); ! 589: } ! 590: ! 591: /* computed jump table */ ! 592: xln (".align 4"); ! 593: xout ("jtab:\n"); ! 594: ! 595: prev = -2; ! 596: fix = fix_first; ! 597: for (; fix != NULL; fix = fix->next) { ! 598: if (fix->size != C_ADDR) continue; ! 599: ! 600: lab = get_label (fix->label); ! 601: ! 602: if (!fix->adr) { ! 603: /* ignore. let pass2 throw the error. */ ! 604: continue; ! 605: } ! 606: /* add ones since prev */ ! 607: for (i=prev+2; i<fix->adr; i+=2) { ! 608: xln (".long bad_jmp"); ! 609: } ! 610: xln (".long %s", fix->label); ! 611: prev = fix->adr; ! 612: } ! 613: xout ("jumptable:\n"); ! 614: xln ("jmp *jtab(,%%eax,2)"); ! 615: #ifdef GEN_DEBUG ! 616: xout (" .section .rodata\n"); ! 617: xout ("bad_jmp_str: .string \"Error. Bad jump target: $%%x at line %%d.\\n\"\n"); ! 618: xln (".text"); ! 619: xout ("bad_jmp:\n"); ! 620: xln ("shll $1,%%eax"); ! 621: xln ("pushl line_no"); ! 622: xln ("pushl %%eax"); ! 623: xln ("pushl $bad_jmp_str"); ! 624: xln ("call printf"); ! 625: xln ("addl $8,%%esp"); ! 626: xln ("call abort"); ! 627: #else ! 628: xout ("bad_jmp:\n"); ! 629: xout ("bad_jmp2:\n"); ! 630: xln ("call abort"); ! 631: #endif ! 632: ! 633: /* the code we made */ ! 634: snprintf (buf, sizeof (buf), ".%s.S", src_filename); ! 635: if ((f = fopen (buf, "r"))==NULL) { ! 636: fprintf (stderr, "Error: Cannot open %s for writing.\n", buf); ! 637: exit (-1); ! 638: } ! 639: while ((c = fgetc (f)) != EOF) fputc (c, asm_out); ! 640: fclose (f); ! 641: remove (buf); ! 642: ! 643: xout ("handle_exception:\n"); ! 644: ! 645: /* no exceptions while in an exception handler */ ! 646: xln ("movl rdest,%%ebx"); ! 647: xln ("testl %%ebx,%%ebx"); ! 648: xln ("jnz jumptable"); ! 649: ! 650: xln ("movl %%eax,rdest"); ! 651: ! 652: xln ("movl exceptions_pending_mask,%%edx"); ! 653: xln ("xorl %%ecx,%%ecx"); ! 654: xout ("1:\n"); ! 655: xln ("btl %%ecx,%%edx"); ! 656: xln ("jnc 2f"); ! 657: ! 658: /* yay. exception num %ecx pending */ ! 659: xln ("movl $exception_handlers,%%ebx"); ! 660: xln ("movb exceptions_pending_nums(%%ecx),%%al"); ! 661: xln ("decb %%al"); ! 662: xln ("jnz 3f"); ! 663: xln ("btrl %%ecx,exceptions_pending_mask"); ! 664: xln ("3: movb %%al,exceptions_pending_nums(%%ecx)"); ! 665: xln ("movl (%%ebx,%%ecx,4),%%eax"); ! 666: xln ("movb X,%%bh"); ! 667: xln ("movb N,%%bl"); ! 668: xln ("movb Z,%%ch"); ! 669: xln ("movb V,%%cl"); ! 670: xln ("movb C,%%dh"); ! 671: xln ("movb %%bh,bX"); ! 672: xln ("movb %%bl,bN"); ! 673: xln ("movb %%ch,bZ"); ! 674: xln ("movb %%cl,bV"); ! 675: xln ("movb %%dh,bC"); ! 676: xln ("jmp jumptable"); ! 677: ! 678: xout ("2:\n"); ! 679: xln ("inc %%ecx"); ! 680: xln ("cmpl $32,%%ecx"); ! 681: xln ("jl 1b"); ! 682: /* shouldn't get here... */ ! 683: xln ("movl rdest,%%eax"); ! 684: xln ("movl $0,rdest"); ! 685: xln ("jmp jumptable"); ! 686: fclose (asm_out); ! 687: } ! 688: ! 689: static int is_reg (ea_t *ea) ! 690: { ! 691: return ((ea->mode == 0) || (ea->mode == 1)); ! 692: } ! 693: ! 694: static int is_immediate (ea_t *ea) ! 695: { ! 696: return ((ea->mode == 7) && (ea->reg == 4)); ! 697: } ! 698: ! 699: /* only x86 regs used in effective address shit. */ ! 700: enum X86REG { ! 701: EAX, EBX, ECX, EDX, ESI, EDI, X86REG_MAX ! 702: }; ! 703: ! 704: /* m68k -> i386 reg allocation. age goes up with disuse */ ! 705: struct reg_alloc { ! 706: int m68k_reg; ! 707: int age; ! 708: int dirty; ! 709: int locked; ! 710: }; ! 711: ! 712: #define xreg_unlock(reg) i386_regalloc[reg].locked--; ! 713: #define xdirty_reg(reg) {if (reg!=-1) i386_regalloc[reg].dirty = 1; } ! 714: ! 715: /* set m68k_reg to REG_TEMP when allocating a reg as a temporary value, ! 716: * ie not holding a specific m68k reg's value */ ! 717: #define REG_TEMP 16 ! 718: ! 719: static struct reg_alloc i386_regalloc[X86REG_MAX]; ! 720: ! 721: /* x86 asm syntax is a pain in the arse for auto-generated stuff */ ! 722: static const char *reg_turd[3][X86REG_MAX] = { ! 723: { "%al", "%bl", "%cl", "%dl", "%invalid1", "%invalid2" }, ! 724: { "%ax", "%bx", "%cx", "%dx", "%si", "%di" }, ! 725: { "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" } ! 726: }; ! 727: ! 728: static const char *szsconv[] = { "sbl", "swl", "l" }; ! 729: //static const char *szuconv[] = { "zbl", "zwl", "l" }; ! 730: static const char *szmov[] = { "b", "w", "l" }; ! 731: static const char *szfull[] = { "l", "l", "l" }; ! 732: ! 733: static const char *xreg (enum X86REG _reg, int size) ! 734: { ! 735: return reg_turd[size][_reg]; ! 736: } ! 737: ! 738: static void init_regalloc () ! 739: { ! 740: int i; ! 741: for (i=0; i<X86REG_MAX; i++) { ! 742: i386_regalloc[i].m68k_reg = -1; ! 743: i386_regalloc[i].locked = 0; ! 744: } ! 745: } ! 746: ! 747: static void xflush_reg (int x86_reg) ! 748: { ! 749: int m68k_reg = i386_regalloc[x86_reg].m68k_reg; ! 750: ! 751: if (i386_regalloc[x86_reg].locked != 0) { ! 752: bug_error ("Internal compiler error. Attept to flush locked register."); ! 753: } ! 754: if (m68k_reg == -1) return; ! 755: assert (m68k_reg <= REG_TEMP); ! 756: ! 757: /* temps can simply be discarded. */ ! 758: if (m68k_reg == REG_TEMP) { ! 759: i386_regalloc[x86_reg].m68k_reg = -1; ! 760: return; ! 761: } ! 762: /* while real m68k reg values must be flushed to memory */ ! 763: if (i386_regalloc[x86_reg].dirty) ! 764: xln ("movl %s,%d(%%ebp)", xreg (x86_reg, LONG), regpos (m68k_reg)); ! 765: i386_regalloc[x86_reg].m68k_reg = -1; ! 766: i386_regalloc[x86_reg].dirty = 0; ! 767: } ! 768: ! 769: static void xflush_all () ! 770: { ! 771: int i; ! 772: for (i=0; i<X86REG_MAX; i++) { ! 773: if (i386_regalloc[i].m68k_reg != -1) ! 774: xflush_reg (i); ! 775: } ! 776: } ! 777: ! 778: /* return -1 if not cached */ ! 779: static int xfind_reg (int m68k_reg) ! 780: { ! 781: int i; ! 782: for (i=0; i<X86REG_MAX; i++) { ! 783: if (i386_regalloc[i].m68k_reg == m68k_reg) { ! 784: i386_regalloc[i].age = 0; ! 785: return i; ! 786: } ! 787: } ! 788: return -1; ! 789: } ! 790: ! 791: static void xregalloc_age () ! 792: { ! 793: int i; ! 794: for (i=0; i<X86REG_MAX; i++) { ! 795: i386_regalloc[i].age++; ! 796: } ! 797: } ! 798: ! 799: /* set x86reg_preferred = whatever X86REG you MUST HAVE. ! 800: * need_bswap=1 means that */ ! 801: static enum X86REG xalloc_reg (int size, int x86reg_preferred) ! 802: { ! 803: int i, top, oldest, age; ! 804: if (x86reg_preferred != -1) { ! 805: xflush_reg (x86reg_preferred); ! 806: i386_regalloc[x86reg_preferred].m68k_reg = REG_TEMP; ! 807: i386_regalloc[x86reg_preferred].dirty = 0; ! 808: return x86reg_preferred; ! 809: } ! 810: /* look for unused reg */ ! 811: /* if we want BYTE size then regs esi,edi are no use */ ! 812: oldest = -1; ! 813: age = -1; ! 814: top = ((size == BYTE) ? ESI : X86REG_MAX); ! 815: for (i=0; i<top; i++) { ! 816: if (i386_regalloc[i].locked) continue; ! 817: /* unallocated and unlocked temps can always be discarded */ ! 818: if ((i386_regalloc[i].m68k_reg == -1) || ! 819: (i386_regalloc[i].m68k_reg == REG_TEMP)) { ! 820: i386_regalloc[i].m68k_reg = REG_TEMP; ! 821: i386_regalloc[i].dirty = 0; ! 822: i386_regalloc[i].locked = 1; ! 823: return i; ! 824: } ! 825: if (oldest == -1) { ! 826: oldest = i; ! 827: age = i386_regalloc[i].age; ! 828: } else if (i386_regalloc[i].age > age) { ! 829: oldest = i; ! 830: age = i386_regalloc[i].age; ! 831: } ! 832: } ! 833: /* oh well.. we must evict a cached reg */ ! 834: if (oldest == -1) { ! 835: error ("Internal compiler error: Run out of x86 registers (leaked temporaries?)"); ! 836: } ! 837: xflush_reg (oldest); ! 838: i386_regalloc[oldest].m68k_reg = REG_TEMP; ! 839: i386_regalloc[oldest].dirty = 0; ! 840: i386_regalloc[oldest].locked = 1; ! 841: return oldest; ! 842: } ! 843: ! 844: #define XLOADREG_FOR_OVERWRITE (1<<0) ! 845: ! 846: static enum X86REG xmove_reg (int size, enum X86REG src, enum X86REG dest) ! 847: { ! 848: assert (!i386_regalloc[src].locked); ! 849: i386_regalloc[src].locked = 1; ! 850: dest = xalloc_reg (size, dest); ! 851: xln ("movl %s,%s", xreg (src,LONG), xreg (dest,LONG)); ! 852: i386_regalloc[dest] = i386_regalloc[src]; ! 853: i386_regalloc[dest].age = 0; ! 854: i386_regalloc[src].locked = 0; ! 855: i386_regalloc[src].dirty = 0; ! 856: i386_regalloc[src].m68k_reg = -1; ! 857: return dest; ! 858: } ! 859: ! 860: static enum X86REG xload_reg2 (int m68k_reg, int size, int required_x86_reg, int flags, const char **conv) ! 861: { ! 862: int i; ! 863: //static int crap; ! 864: /* is it already loaded? */ ! 865: for (i=0; i<X86REG_MAX; i++) { ! 866: if (i386_regalloc[i].m68k_reg != m68k_reg) { ! 867: continue; ! 868: } else { ! 869: if ((required_x86_reg != -1) && ! 870: (i != required_x86_reg)) { ! 871: /* reg loaded but not in desired place. do it */ ! 872: return xmove_reg (size, i, required_x86_reg); ! 873: } ! 874: } ! 875: ! 876: if ((size == BYTE) && (i >= ESI)) { ! 877: /* can't operate on byte values in the esi/edi regs */ ! 878: //printf ("stupid esi/edi shit (no worries mate (n %d, line %d)\n", crap++, line_no); ! 879: ! 880: xflush_reg (i); ! 881: //return xmove_reg (size, i); ! 882: } else { ! 883: i386_regalloc[i].age = 0; ! 884: i386_regalloc[i].locked++; ! 885: return i; ! 886: } ! 887: } ! 888: /* otherwise allocate.. */ ! 889: i = xalloc_reg (size, required_x86_reg); ! 890: ! 891: /* registers loaded for overwrite size long do not need the original value */ ! 892: if (! ((flags & XLOADREG_FOR_OVERWRITE) && (size == LONG))) ! 893: xln ("mov%s %d(%%ebp),%s", conv[size], regpos (m68k_reg), xreg (i, LONG)); ! 894: ! 895: i386_regalloc[i].m68k_reg = m68k_reg; ! 896: i386_regalloc[i].age = 0; ! 897: i386_regalloc[i].dirty = 0; ! 898: i386_regalloc[i].locked = 1; ! 899: return i; ! 900: } ! 901: static enum X86REG xload_reg (int m68k_reg, int size, int required_x86_reg) ! 902: { ! 903: return xload_reg2 (m68k_reg, size, required_x86_reg, 0, szfull); ! 904: } ! 905: ! 906: enum RegConversion { XCONV_NONE, XCONV_SWL, XCONV_ZWL }; ! 907: /* returns a temporary reg alloc copy of an m68k register, that you can do ! 908: * what the fuck you like with */ ! 909: #define xcopy_reg(m68k_reg,size,required_x86_reg) \ ! 910: xcopy_reg2 (m68k_reg, size, required_x86_reg, 0) ! 911: static enum X86REG xcopy_reg2 (int m68k_reg, int size, int required_x86_reg, enum RegConversion conversion) ! 912: { ! 913: int reg, copy_reg; ! 914: ! 915: /* i wonder if it is an optimisation to load directly to copy reg ! 916: * when the reg is not already cached.. */ ! 917: reg = xload_reg (m68k_reg, size, -1); ! 918: copy_reg = xalloc_reg (size, required_x86_reg); ! 919: ! 920: switch (conversion) { ! 921: case XCONV_NONE: ! 922: xln ("mov%s %s,%s", szmov[size], xreg (reg, size), xreg (copy_reg, size)); ! 923: break; ! 924: case XCONV_SWL: ! 925: assert (size == LONG); ! 926: xln ("movswl %s,%s", szmov[size], xreg (reg, WORD), xreg (copy_reg, LONG)); ! 927: break; ! 928: case XCONV_ZWL: ! 929: assert (size == LONG); ! 930: xln ("movzwl %s,%s", szmov[size], xreg (reg, WORD), xreg (copy_reg, LONG)); ! 931: break; ! 932: } ! 933: xreg_unlock (reg); ! 934: return copy_reg; ! 935: } ! 936: ! 937: static int rset[2] = { EAX, EBX }; ! 938: static int rdirty[2] = { ECX, EDX }; ! 939: ! 940: #define sreg(reg) xreg ((reg), size) ! 941: ! 942: static void x_postea (ea_t *ea) ! 943: { ! 944: int inc, reg; ! 945: ! 946: inc = 1<<ea->op_size; ! 947: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 948: /* deallocate temporary register allocations */ ! 949: if (ea->x86_reg != -1) { ! 950: xreg_unlock (ea->x86_reg); ! 951: } ! 952: if (ea->x86_reg_writeback != -1) { ! 953: xreg_unlock (ea->x86_reg_writeback); ! 954: } ! 955: ! 956: switch (ea->mode) { ! 957: /* areg postinc */ ! 958: case 3: ! 959: reg = xload_reg (ea->reg, LONG, -1); ! 960: xdirty_reg (reg); ! 961: if (inc == 1) ! 962: xln ("incl %s", xreg (reg, LONG)); ! 963: else ! 964: xln ("addl $%d,%s", inc, xreg (reg, LONG)); ! 965: xreg_unlock (reg); ! 966: break; ! 967: /* areg predec */ ! 968: case 4: ! 969: reg = xload_reg (ea->reg, LONG, -1); ! 970: xdirty_reg (reg); ! 971: if (inc == 1) ! 972: xln ("decl %s", xreg (reg, LONG)); ! 973: else ! 974: xln ("subl $%d,%s", inc, xreg (reg, LONG)); ! 975: xreg_unlock (reg); ! 976: break; ! 977: default: break; ! 978: } ! 979: } ! 980: ! 981: #define _S(x) if (stage[arg] == (x)) ! 982: ! 983: /* ! 984: * Note on these multi-stage pipeline turds. The value must be actually ! 985: * set in val_reg on the final stage, final instruction, so that the ! 986: * condition codes are available. ! 987: * ! 988: * Actually used stages should be the final ones, if not all are needed. ! 989: */ ! 990: ! 991: /* ! 992: * Returns zero when done. ! 993: */ ! 994: static void xold_ea_get_address (ea_t *ea, int arg, int advance_stage) ! 995: { ! 996: static int stage[2] = {1,1}; ! 997: int rpos, inc; ! 998: ! 999: if (!advance_stage) { ! 1000: if (stage[arg] != 1) error ("xold_ea_get_address stages missed. (as68k bug)."); ! 1001: ! 1002: stage[arg] = 0; ! 1003: } else { ! 1004: stage[arg]++; ! 1005: } ! 1006: ! 1007: ea->x86_reg = -1; ! 1008: ! 1009: switch (ea->mode) { ! 1010: /* dreg, areg */ ! 1011: case 0: case 1: assert (0); ! 1012: /* areg indirect, postinc */ ! 1013: case 2: case 3: ! 1014: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rset[arg],LONG)); ! 1015: break; ! 1016: /* areg predec */ ! 1017: case 4: ! 1018: inc = 1<<ea->op_size; ! 1019: /* stack pointer always by 2 */ ! 1020: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1021: ! 1022: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rset[arg],LONG)); ! 1023: //XXX ! 1024: _S(1) { ! 1025: if (inc == 1) xln ("dec %s", xreg (rset[arg],LONG)); ! 1026: else xln ("subl $%d,%s", inc, xreg (rset[arg],LONG)); ! 1027: } ! 1028: break; ! 1029: /* areg offset */ ! 1030: case 5: ! 1031: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rset[arg],LONG)); ! 1032: //XXX ! 1033: _S(1) xln ("addl $%d,%s", ea->imm.val, xreg (rset[arg],LONG)); ! 1034: break; ! 1035: /* areg offset + reg */ ! 1036: case 6: ! 1037: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rset[arg],LONG)); ! 1038: if (ea->ext._.size) { ! 1039: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[arg], LONG)); ! 1040: } else { ! 1041: _S(0) xln ("movswl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[arg], LONG)); ! 1042: } ! 1043: _S(0) xln ("addl $%d,%s", ea->ext._.displacement, xreg (rset[arg],LONG)); ! 1044: //XXX ! 1045: _S(1) xln ("addl %s,%s", xreg (rdirty[arg], LONG), xreg (rset[arg],LONG)); ! 1046: break; ! 1047: /* yes */ ! 1048: case 7: ! 1049: /* $xxx.w */ ! 1050: if (ea->reg == 0) { ! 1051: _S(1) xln ("movl $%d,%s", ea->imm.val, xreg (rset[arg],LONG)); ! 1052: } ! 1053: /* $xxx.l */ ! 1054: else if (ea->reg == 1) { ! 1055: if (ea->imm.has_label) { ! 1056: _S(1) xln ("movl $__D%s,%s", ea->imm.label, xreg (rset[arg],LONG)); ! 1057: } else { ! 1058: _S(1) xln ("movl $%d,%s", ea->imm.val, xreg (rset[arg],LONG)); ! 1059: } ! 1060: } ! 1061: /* immediate */ ! 1062: else if (ea->reg == 4) { ! 1063: assert (0); ! 1064: } ! 1065: /* PC + offset */ ! 1066: else if (ea->reg == 2) { ! 1067: if (ea->imm.has_label) { ! 1068: _S(1) xln ("movl $__D%s,%s", ea->imm.label, xreg (rset[arg],LONG)); ! 1069: } else ! 1070: error ("Absolute value not allowed."); ! 1071: } ! 1072: /* PC + INDEX + OFFSET */ ! 1073: else if (ea->reg == 3) { ! 1074: if (!ea->imm.has_label) error ("Absolute value not allowed."); ! 1075: rpos = regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)); ! 1076: if (ea->ext._.size) { ! 1077: _S(0) xln ("movl %d(%%ebp),%s", rpos, xreg (rset[arg],LONG)); ! 1078: } else { ! 1079: _S(0) xln ("movswl %d(%%ebp),%s", rpos, xreg (rset[arg],LONG)); ! 1080: } ! 1081: // XXX ! 1082: _S(1) xln ("addl $__D%s,%s", ea->imm.label, xreg (rset[arg],LONG)); ! 1083: } ! 1084: break; ! 1085: default: ! 1086: assert (0); ! 1087: } ! 1088: } ! 1089: ! 1090: static void do_bswap (enum X86REG val, int size) ! 1091: { ! 1092: switch (size) { ! 1093: case BYTE: return; ! 1094: case WORD: xln ("rorw $8,%s", xreg (val, WORD)); ! 1095: return; ! 1096: case LONG: xln ("bswap %s", xreg (val, LONG)); ! 1097: return; ! 1098: } ! 1099: } ! 1100: ! 1101: /* ! 1102: * To avoid pipeline stalls the function outputs code until ! 1103: * a pipeline stall occurs, and then returns. ! 1104: * First call should be made with advance_stage == 0, subsequent ! 1105: * calls with advance_stage==1. ! 1106: * And then put shit inbetween. ! 1107: * ! 1108: * flag XQUICK_REGS means that for "reading" immediate values, ! 1109: * and XQUICK_REGS values in registers, nothing is done and instead ea->identifier ! 1110: * string is set to (for example) "$1234" or the i386 EA of the reg. ! 1111: * ! 1112: * XCAN_OVERWRITE means that you can modify the returned value because ! 1113: * it is a copy of the cached register (if it is a register, otherwise ! 1114: * this flag has no effect). ! 1115: */ ! 1116: #define XQUICK_REGS (1<<0) ! 1117: #define XQUICK_IMMS (1<<1) ! 1118: #define XQUICK_WRITEBACK (1<<2) ! 1119: #define XCAN_OVERWRITE (1<<3) ! 1120: #define XSIGN_EXTEND_REGS (1<<4) ! 1121: ! 1122: #define xold_readea(ea,arg,adv) xold_readea2(ea,arg,adv,0); ! 1123: static void xold_readea2 (ea_t *ea, int arg, int advance_stage, int flags) ! 1124: { ! 1125: static int stage[2] = {2,2}; ! 1126: int inc, size; ! 1127: size = ea->op_size; ! 1128: ! 1129: if (!advance_stage) { ! 1130: if (stage[arg] != 2) error ("xold_readea stages missed. (as68k bug)."); ! 1131: ! 1132: stage[arg] = 0; ! 1133: } else { ! 1134: stage[arg]++; ! 1135: } ! 1136: ! 1137: ea->do_writeback = 1; ! 1138: ea->x86_reg_writeback = -1; ! 1139: ea->x86_reg = -1; ! 1140: ! 1141: switch (ea->mode) { ! 1142: /* dreg, areg */ ! 1143: case 0: ! 1144: case 1: ! 1145: if (flags & XQUICK_REGS) { ! 1146: /* operate in-place (in memory) */ ! 1147: _S(0) snprintf (ea->identifier, sizeof (ea->identifier), "%d(%%ebp)", regpos (ea->reg)); ! 1148: ea->do_writeback = 0; ! 1149: return; ! 1150: } ! 1151: _S(2) xln ("mov%s %d(%%ebp),%s", szmov[size], regpos (ea->reg), xreg (rset[arg], size)); ! 1152: break; ! 1153: /* areg indirect */ ! 1154: case 2: ! 1155: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[arg], LONG)); ! 1156: _S(1) xln ("mov%s (%%ebp,%s),%s", szmov[size], xreg (rdirty[arg], LONG), xreg (rset[arg], size)); ! 1157: _S(2) do_bswap (rset[arg], size); ! 1158: break; ! 1159: /* areg postinc */ ! 1160: case 3: ! 1161: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[arg], LONG)); ! 1162: _S(1) xln ("mov%s (%%ebp,%s),%s", szmov[size], xreg (rdirty[arg], LONG), xreg (rset[arg], size)); ! 1163: _S(2) do_bswap (rset[arg], size); ! 1164: break; ! 1165: /* areg predec */ ! 1166: case 4: ! 1167: inc = 1<<size; ! 1168: /* stack pointer always by 2 */ ! 1169: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1170: ! 1171: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[arg], LONG)); ! 1172: _S(1) xln ("mov%s -%d(%%ebp,%s),%s", szmov[size], inc, xreg (rdirty[arg], LONG), xreg (rset[arg], size)); ! 1173: _S(2) do_bswap (rset[arg], size); ! 1174: break; ! 1175: /* areg offset */ ! 1176: case 5: ! 1177: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[arg], LONG)); ! 1178: _S(1) xln ("mov%s %d(%%ebp,%s),%s", szmov[size], ea->imm.val, xreg (rdirty[arg], LONG), xreg (rset[arg], size)); ! 1179: _S(2) do_bswap (rset[arg], size); ! 1180: break; ! 1181: /* areg offset + reg */ ! 1182: case 6: ! 1183: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[arg],LONG)); ! 1184: if (ea->ext._.size) { ! 1185: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rset[arg],LONG)); ! 1186: } else { ! 1187: _S(0) xln ("movswl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rset[arg], LONG)); ! 1188: } ! 1189: _S(0) xln ("addl %%ebp,%s", xreg (rdirty[arg],LONG)); ! 1190: _S(1) xln ("mov%s %d(%s,%s),%s", szmov[size], ea->ext._.displacement, xreg (rdirty[arg],LONG), xreg (rset[arg],LONG), xreg (rset[arg], size)); ! 1191: _S(2) do_bswap (rset[arg], size); ! 1192: break; ! 1193: /* yes */ ! 1194: case 7: ! 1195: /* $xxx.w */ ! 1196: if (ea->reg == 0) { ! 1197: _S(1) xln ("mov%s %d(%%ebp),%s", szmov[size], ea->imm.val, xreg (rset[arg], size)); ! 1198: _S(1) do_bswap (rset[arg], size); ! 1199: } ! 1200: /* $xxx.l */ ! 1201: else if (ea->reg == 1) { ! 1202: if (ea->imm.has_label) { ! 1203: _S(1) xln ("mov%s __D%s(%%ebp),%s", szmov[size], ea->imm.label, xreg (rset[arg], size)); ! 1204: _S(2) do_bswap (rset[arg], size); ! 1205: } else { ! 1206: _S(1) xln ("mov%s %d(%%ebp),%s", szmov[size], ea->imm.val, xreg (rset[arg], size)); ! 1207: _S(2) do_bswap (rset[arg], size); ! 1208: } ! 1209: } ! 1210: /* immediate */ ! 1211: else if (ea->reg == 4) { ! 1212: if (flags & XQUICK_IMMS) { ! 1213: if (ea->imm.has_label) { ! 1214: _S(0) snprintf (ea->identifier, sizeof (ea->identifier), ! 1215: "$__D%s", ea->imm.label); ! 1216: } else { ! 1217: _S(0) snprintf (ea->identifier, sizeof (ea->identifier), ! 1218: "$%d", ea->imm.val); ! 1219: } ! 1220: return; ! 1221: } ! 1222: if (ea->imm.has_label) { ! 1223: _S(2) xln ("movl $__D%s,%s", ea->imm.label, xreg (rset [arg], LONG)); ! 1224: } else { ! 1225: _S(2) xln ("movl $%d,%s", ea->imm.val, xreg (rset [arg], LONG)); ! 1226: } ! 1227: } ! 1228: /* PC + offset */ ! 1229: else if (ea->reg == 2) { ! 1230: assert (ea->imm.has_label); ! 1231: ! 1232: _S(1) xln ("mov%s __D%s(%%ebp),%s", szmov[size], ea->imm.label, xreg (rset[arg], size)); ! 1233: _S(2) do_bswap (rset[arg], size); ! 1234: } ! 1235: /* PC + INDEX + OFFSET */ ! 1236: else if (ea->reg == 3) { ! 1237: assert (ea->imm.has_label); ! 1238: if (ea->ext._.size) { ! 1239: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[arg],LONG)); ! 1240: } else { ! 1241: _S(0) xln ("movswl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[arg], LONG)); ! 1242: } ! 1243: _S(1) xln ("mov%s __D%s(%%ebp,%s),%s", szmov[size], ea->imm.label, xreg (rdirty[arg],LONG), xreg (rset[arg], size)); ! 1244: _S(2) do_bswap (rset[arg], size); ! 1245: } ! 1246: break; ! 1247: default: ! 1248: error ("nasty error in c_readea()"); ! 1249: } ! 1250: _S(0) snprintf (ea->identifier, sizeof (ea->identifier), ! 1251: "%s", reg_turd[size][arg]); ! 1252: } ! 1253: ! 1254: /* ! 1255: * Uses dirty regs of arg1 and arg2 (so they can't be pipelined together). ! 1256: */ ! 1257: static void xold_writeea (ea_t *ea, int size, enum X86REG val, int advance_stage) ! 1258: { ! 1259: int inc; ! 1260: const int arg = 1; /* hack. _S macro ;-) */ ! 1261: static int stage[2] = {2,2}; ! 1262: ! 1263: assert ((val == EAX) || (val == EBX)); ! 1264: ! 1265: if (!advance_stage) { ! 1266: if (stage[arg] != 2) error ("xold_writeea stages missed. (as68k bug)."); ! 1267: ! 1268: stage[arg] = 0; ! 1269: } else { ! 1270: stage[arg]++; ! 1271: } ! 1272: ! 1273: if (!ea->do_writeback) return; ! 1274: ea->x86_reg_writeback = -1; ! 1275: ea->x86_reg = -1; ! 1276: ! 1277: switch (ea->mode) { ! 1278: /* dreg, areg */ ! 1279: case 0: case 1: ! 1280: _S(2) xln ("mov%s %s,%d(%%ebp)", szmov[size], xreg (val, size), regpos (ea->reg)); ! 1281: break; ! 1282: /* areg indirect */ ! 1283: case 2: ! 1284: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[0], LONG)); ! 1285: _S(1) do_bswap (val, size); ! 1286: _S(2) xln ("mov%s %s,(%%ebp,%s)", szmov[size], xreg (val, size), xreg (rdirty[0], LONG)); ! 1287: break; ! 1288: /* areg postinc */ ! 1289: case 3: ! 1290: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[0], LONG)); ! 1291: _S(1) do_bswap (val, size); ! 1292: _S(2) xln ("mov%s %s,(%%ebp,%s)", szmov[size], xreg (val, size), xreg (rdirty[0], LONG)); ! 1293: break; ! 1294: /* areg predec */ ! 1295: case 4: ! 1296: inc = 1<<size; ! 1297: /* stack pointer always by 2 */ ! 1298: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1299: ! 1300: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[0], LONG)); ! 1301: _S(1) do_bswap (val, size); ! 1302: _S(2) xln ("mov%s %s,-%d(%%ebp,%s)", szmov[size], xreg (val, size), inc, xreg (rdirty[0], LONG)); ! 1303: break; ! 1304: /* areg offset */ ! 1305: case 5: ! 1306: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[0], LONG)); ! 1307: _S(1) do_bswap (val, size); ! 1308: _S(2) xln ("mov%s %s,%d(%%ebp,%s)", szmov[size], xreg (val, size), ea->imm.val, xreg (rdirty[0], LONG)); ! 1309: break; ! 1310: /* areg offset + reg */ ! 1311: case 6: ! 1312: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->reg), xreg (rdirty[1],LONG)); ! 1313: if (ea->ext._.size) { ! 1314: _S(0) xln ("movl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[0],LONG)); ! 1315: } else { ! 1316: _S(0) xln ("movswl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[0], LONG)); ! 1317: } ! 1318: _S(0) xln ("addl %%ebp,%s", xreg (rdirty[1],LONG)); ! 1319: _S(0) do_bswap (val, size); ! 1320: _S(1) xln ("mov%s %s,%d(%s,%s)", szmov[size], xreg (val, size), ea->ext._.displacement, xreg (rdirty[1],LONG), xreg (rdirty[0],LONG)); ! 1321: break; ! 1322: /* yes */ ! 1323: case 7: ! 1324: /* $xxx.w */ ! 1325: if (ea->reg == 0) { ! 1326: _S(1) do_bswap (val, size); ! 1327: _S(2) xln ("mov%s %s,%d(%%ebp)", szmov[size], xreg (val, size), ea->imm.val); ! 1328: } ! 1329: /* $xxx.l */ ! 1330: else if (ea->reg == 1) { ! 1331: if (ea->imm.has_label) { ! 1332: _S(1) do_bswap (val, size); ! 1333: _S(2) xln ("mov%s %s,__D%s(%%ebp)", szmov[size], xreg (val, size), ea->imm.label); ! 1334: } else { ! 1335: _S(1) do_bswap (val, size); ! 1336: _S(2) xln ("mov%s %s,%d(%%ebp)", szmov[size], xreg (val, size), ea->imm.val); ! 1337: } ! 1338: } ! 1339: /* immediate */ ! 1340: else if (ea->reg == 4) { ! 1341: assert (0); ! 1342: } ! 1343: /* PC + offset */ ! 1344: else if (ea->reg == 2) { ! 1345: assert (ea->imm.has_label); ! 1346: ! 1347: _S(1) do_bswap (val, size); ! 1348: _S(2) xln ("mov%s %s,__D%s(%%ebp)", szmov[size], xreg (val, size), ea->imm.label); ! 1349: } ! 1350: /* PC + INDEX + OFFSET */ ! 1351: else if (ea->reg == 3) { ! 1352: assert (ea->imm.has_label); ! 1353: if (ea->ext._.size) { ! 1354: _S(1) xln ("movl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[0],LONG)); ! 1355: } else { ! 1356: _S(1) xln ("movswl %d(%%ebp),%s", regpos (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0)), xreg (rdirty[0], LONG)); ! 1357: } ! 1358: _S(1) do_bswap (val, size); ! 1359: _S(2) xln ("mov%s %s,__D%s(%%ebp,%s)", szmov[size], xreg (val,size), ea->imm.label, xreg (rdirty[0],LONG)); ! 1360: } ! 1361: else { ! 1362: error ("wtf in c_writeea ()"); ! 1363: } ! 1364: break; ! 1365: default: ! 1366: error ("nasty error in c_writeea()"); ! 1367: } ! 1368: } ! 1369: ! 1370: /* loads effective address, not value pointed to */ ! 1371: static void x_loadea (ea_t *ea) ! 1372: { ! 1373: int reg2, reg3, inc, out_reg; ! 1374: ! 1375: ea->do_writeback = 1; ! 1376: ea->x86_reg_writeback = -1; ! 1377: ! 1378: switch (ea->mode) { ! 1379: /* dreg, areg */ ! 1380: case 0: case 1: assert (0); ! 1381: /* areg indirect, postinc */ ! 1382: case 2: case 3: ! 1383: out_reg = xcopy_reg (ea->reg, LONG, -1); ! 1384: break; ! 1385: /* areg predec */ ! 1386: case 4: ! 1387: inc = 1<<ea->op_size; ! 1388: /* stack pointer always by 2 */ ! 1389: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1390: ! 1391: out_reg = xcopy_reg (ea->reg, LONG, -1); ! 1392: if (inc == 1) xln ("dec %s", xreg (out_reg,LONG)); ! 1393: else xln ("subl $%d,%s", inc, xreg (out_reg,LONG)); ! 1394: break; ! 1395: /* areg offset */ ! 1396: case 5: ! 1397: out_reg = xcopy_reg (ea->reg, LONG, -1); ! 1398: xln ("addl $%d,%s", ea->imm.val, xreg (out_reg,LONG)); ! 1399: break; ! 1400: /* areg offset + reg */ ! 1401: case 6: ! 1402: out_reg = xcopy_reg (ea->reg, LONG, -1); ! 1403: if (ea->ext._.size) { ! 1404: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1405: } else { ! 1406: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1407: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1408: reg2 = xalloc_reg (LONG, -1); ! 1409: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1410: xreg_unlock (reg3); ! 1411: ! 1412: } ! 1413: xln ("leal %d(%s,%s),%s", ea->ext._.displacement, xreg (reg2, LONG), xreg(out_reg, LONG), xreg (out_reg, LONG)); ! 1414: xreg_unlock (reg2); ! 1415: break; ! 1416: /* yes */ ! 1417: case 7: ! 1418: /* $xxx.w */ ! 1419: if (ea->reg == 0) { ! 1420: out_reg = xalloc_reg (LONG, -1); ! 1421: xln ("movl $%d,%s", ea->imm.val, out_reg, LONG); ! 1422: } ! 1423: /* $xxx.l */ ! 1424: else if (ea->reg == 1) { ! 1425: out_reg = xalloc_reg (LONG, -1); ! 1426: if (ea->imm.has_label) { ! 1427: xln ("movl $__D%s,%s", ea->imm.label, xreg (out_reg,LONG)); ! 1428: } else { ! 1429: xln ("movl $%d,%s", ea->imm.val, xreg (out_reg,LONG)); ! 1430: } ! 1431: } ! 1432: /* immediate */ ! 1433: else if (ea->reg == 4) { ! 1434: assert (0); ! 1435: } ! 1436: /* PC + offset */ ! 1437: else if (ea->reg == 2) { ! 1438: if (ea->imm.has_label) { ! 1439: out_reg = xalloc_reg (LONG, -1); ! 1440: xln ("movl $__D%s,%s", ea->imm.label, xreg (out_reg,LONG)); ! 1441: } else ! 1442: error ("Absolute value not allowed."); ! 1443: } ! 1444: /* PC + INDEX + OFFSET */ ! 1445: else if (ea->reg == 3) { ! 1446: if (!ea->imm.has_label) error ("Absolute value not allowed."); ! 1447: out_reg = xalloc_reg (LONG, -1); ! 1448: if (ea->ext._.size) { ! 1449: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1450: } else { ! 1451: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1452: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1453: reg2 = xalloc_reg (LONG, -1); ! 1454: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1455: xreg_unlock (reg3); ! 1456: } ! 1457: // XXX ! 1458: xln ("leal __D%s(%s),%s", ea->imm.label, xreg (reg2, LONG), xreg (out_reg, LONG)); ! 1459: xreg_unlock (reg2); ! 1460: } ! 1461: break; ! 1462: default: ! 1463: assert (0); ! 1464: } ! 1465: ea->x86_reg = out_reg; ! 1466: snprintf (ea->identifier, sizeof (ea->identifier), ! 1467: "%s", xreg (out_reg, LONG)); ! 1468: } ! 1469: ! 1470: /* that is, preferred x86 reg. ! 1471: * XXX nothing preferred about it. it is a fucking demand. */ ! 1472: static void x_loadval (ea_t *ea, int preferred_reg, int flags) ! 1473: { ! 1474: int inc, size, reg1, reg2, reg3, out_reg; ! 1475: size = ea->op_size; ! 1476: ! 1477: ea->do_writeback = 1; ! 1478: ea->x86_reg_writeback = -1; ! 1479: ! 1480: switch (ea->mode) { ! 1481: /* dreg, areg */ ! 1482: case 0: ! 1483: case 1: ! 1484: if (flags & XCAN_OVERWRITE) { ! 1485: out_reg = xcopy_reg (ea->reg, LONG, preferred_reg); ! 1486: } else ! 1487: if ((flags & XQUICK_REGS) && (xfind_reg (ea->reg)==-1)) { ! 1488: /* operate in-place (in memory) */ ! 1489: snprintf (ea->identifier, sizeof (ea->identifier), "%d(%%ebp)", regpos (ea->reg)); ! 1490: ea->do_writeback = 0; ! 1491: return; ! 1492: } else { ! 1493: out_reg = xload_reg2 (ea->reg, size, preferred_reg, ! 1494: 0, (flags & XSIGN_EXTEND_REGS ? szsconv : szfull)); ! 1495: } ! 1496: break; ! 1497: /* areg indirect */ ! 1498: case 2: ! 1499: reg1 = xload_reg (ea->reg, LONG, -1); ! 1500: out_reg = xalloc_reg (size, preferred_reg); ! 1501: ! 1502: xln ("mov%s (%%ebp,%s),%s", szmov[size], xreg (reg1, LONG), xreg (out_reg, size)); ! 1503: xreg_unlock (reg1); ! 1504: do_bswap (out_reg, size); ! 1505: break; ! 1506: /* areg postinc */ ! 1507: case 3: ! 1508: reg1 = xload_reg (ea->reg, LONG, -1); ! 1509: out_reg = xalloc_reg (size, preferred_reg); ! 1510: ! 1511: xln ("mov%s (%%ebp,%s),%s", szmov[size], xreg (reg1, LONG), xreg (out_reg, size)); ! 1512: xreg_unlock (reg1); ! 1513: do_bswap (out_reg, size); ! 1514: break; ! 1515: /* areg predec */ ! 1516: case 4: ! 1517: inc = 1<<size; ! 1518: /* stack pointer always by 2 */ ! 1519: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1520: ! 1521: reg1 = xload_reg (ea->reg, LONG, -1); ! 1522: out_reg = xalloc_reg (size, preferred_reg); ! 1523: xln ("mov%s -%d(%%ebp,%s),%s", szmov[size], inc, xreg (reg1, LONG), xreg (out_reg, size)); ! 1524: xreg_unlock (reg1); ! 1525: do_bswap (out_reg, size); ! 1526: break; ! 1527: /* areg offset */ ! 1528: case 5: ! 1529: reg1 = xload_reg (ea->reg, LONG, -1); ! 1530: out_reg = xalloc_reg (size, preferred_reg); ! 1531: ! 1532: xln ("mov%s %d(%%ebp,%s),%s", szmov[size], ea->imm.val, xreg (reg1, LONG), xreg (out_reg, size)); ! 1533: xreg_unlock (reg1); ! 1534: do_bswap (out_reg, size); ! 1535: break; ! 1536: /* areg offset + reg */ ! 1537: case 6: ! 1538: reg1 = xload_reg (ea->reg, LONG, -1); ! 1539: out_reg = xalloc_reg (size, preferred_reg); ! 1540: if (ea->ext._.size) { ! 1541: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1542: } else { ! 1543: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1544: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1545: reg2 = xalloc_reg (LONG, -1); ! 1546: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1547: } ! 1548: if (flags & XQUICK_WRITEBACK) { ! 1549: xln ("lea (MemBase+%d)(%s,%s),%s", ea->ext._.displacement, xreg (reg1,LONG), xreg (reg2,LONG), xreg (reg2, LONG)); ! 1550: xln ("mov%s (%s),%s", szmov[size], xreg (reg2,LONG), xreg (out_reg, size)); ! 1551: ea->x86_reg_writeback = reg2; ! 1552: ! 1553: xreg_unlock (reg1); ! 1554: xreg_unlock (reg3); ! 1555: } else { ! 1556: xln ("mov%s (MemBase+%d)(%s,%s),%s", szmov[size], ea->ext._.displacement, xreg (reg1,LONG), xreg (reg2,LONG), xreg (out_reg, size)); ! 1557: if (!ea->ext._.size) xreg_unlock (reg3); ! 1558: xreg_unlock (reg1); ! 1559: xreg_unlock (reg2); ! 1560: } ! 1561: do_bswap (out_reg, size); ! 1562: break; ! 1563: /* yes */ ! 1564: case 7: ! 1565: /* $xxx.w */ ! 1566: if (ea->reg == 0) { ! 1567: out_reg = xalloc_reg (size, preferred_reg); ! 1568: xln ("mov%s %d(%%ebp),%s", szmov[size], ea->imm.val, xreg (out_reg, size)); ! 1569: do_bswap (out_reg, size); ! 1570: } ! 1571: /* $xxx.l */ ! 1572: else if (ea->reg == 1) { ! 1573: out_reg = xalloc_reg (size, preferred_reg); ! 1574: if (ea->imm.has_label) { ! 1575: xln ("mov%s __D%s(%%ebp),%s", szmov[size], ea->imm.label, xreg (out_reg, size)); ! 1576: } else { ! 1577: xln ("mov%s %d(%%ebp),%s", szmov[size], ea->imm.val, xreg (out_reg, size)); ! 1578: } ! 1579: do_bswap (out_reg, size); ! 1580: } ! 1581: /* immediate */ ! 1582: else if (ea->reg == 4) { ! 1583: if (flags & XQUICK_IMMS) { ! 1584: if (ea->imm.has_label) { ! 1585: snprintf (ea->identifier, sizeof (ea->identifier), ! 1586: "$__D%s", ea->imm.label); ! 1587: } else { ! 1588: snprintf (ea->identifier, sizeof (ea->identifier), ! 1589: "$%d", ea->imm.val); ! 1590: } ! 1591: ea->x86_reg = -1; ! 1592: return; ! 1593: } ! 1594: out_reg = xalloc_reg (size, preferred_reg); ! 1595: if (ea->imm.has_label) { ! 1596: xln ("movl $__D%s,%s", ea->imm.label, xreg (out_reg, LONG)); ! 1597: } else { ! 1598: xln ("movl $%d,%s", ea->imm.val, xreg (out_reg, LONG)); ! 1599: } ! 1600: } ! 1601: /* PC + offset */ ! 1602: else if (ea->reg == 2) { ! 1603: assert (ea->imm.has_label); ! 1604: ! 1605: out_reg = xalloc_reg (size, preferred_reg); ! 1606: xln ("mov%s __D%s(%%ebp),%s", szmov[size], ea->imm.label, xreg (out_reg, size)); ! 1607: do_bswap (out_reg, size); ! 1608: } ! 1609: /* PC + INDEX + OFFSET */ ! 1610: else if (ea->reg == 3) { ! 1611: assert (ea->imm.has_label); ! 1612: ! 1613: out_reg = xalloc_reg (size, preferred_reg); ! 1614: if (ea->ext._.size) { ! 1615: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1616: } else { ! 1617: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1618: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1619: reg2 = xalloc_reg (LONG, -1); ! 1620: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1621: xreg_unlock (reg3); ! 1622: } ! 1623: xln ("mov%s __D%s(%%ebp,%s),%s", szmov[size], ea->imm.label, xreg (reg2,LONG), xreg (out_reg, size)); ! 1624: do_bswap (out_reg, size); ! 1625: xreg_unlock (reg2); ! 1626: } ! 1627: break; ! 1628: default: ! 1629: error ("nasty error in c_readea()"); ! 1630: } ! 1631: ! 1632: ea->x86_reg = out_reg; ! 1633: snprintf (ea->identifier, sizeof (ea->identifier), ! 1634: "%s", xreg (out_reg, size)); ! 1635: } ! 1636: ! 1637: static void x_saveval (ea_t *ea, int size) ! 1638: { ! 1639: int inc, reg1, reg2, reg3; ! 1640: ! 1641: if (!ea->do_writeback) return; ! 1642: ! 1643: if (ea->x86_reg_writeback != -1) { ! 1644: do_bswap (ea->x86_reg, size); ! 1645: xln ("mov%s %s,(%s)", szmov[size], xreg (ea->x86_reg, size), xreg (ea->x86_reg_writeback, LONG)); ! 1646: return; ! 1647: } ! 1648: ! 1649: switch (ea->mode) { ! 1650: /* dreg, areg */ ! 1651: case 0: case 1: ! 1652: /* don't need to act until xflush_reg... */ ! 1653: break; ! 1654: /* areg indirect */ ! 1655: case 2: ! 1656: reg1 = xload_reg (ea->reg, LONG, -1); ! 1657: do_bswap (ea->x86_reg, size); ! 1658: xln ("mov%s %s,(%%ebp,%s)", szmov[size], xreg (ea->x86_reg, size), xreg (reg1, LONG)); ! 1659: xreg_unlock (reg1); ! 1660: break; ! 1661: /* areg postinc */ ! 1662: case 3: ! 1663: reg1 = xload_reg (ea->reg, LONG, -1); ! 1664: do_bswap (ea->x86_reg, size); ! 1665: xln ("mov%s %s,(%%ebp,%s)", szmov[size], xreg (ea->x86_reg, size), xreg (reg1, LONG)); ! 1666: xreg_unlock (reg1); ! 1667: break; ! 1668: /* areg predec */ ! 1669: case 4: ! 1670: inc = 1<<size; ! 1671: /* stack pointer always by 2 */ ! 1672: if ((ea->reg == 15) && (inc == 1)) inc = 2; ! 1673: ! 1674: reg1 = xload_reg (ea->reg, LONG, -1); ! 1675: do_bswap (ea->x86_reg, size); ! 1676: xln ("mov%s %s,-%d(%%ebp,%s)", szmov[size], xreg (ea->x86_reg, size), inc, xreg (reg1, LONG)); ! 1677: xreg_unlock (reg1); ! 1678: break; ! 1679: /* areg offset */ ! 1680: case 5: ! 1681: reg1 = xload_reg (ea->reg, LONG, -1); ! 1682: do_bswap (ea->x86_reg, size); ! 1683: xln ("mov%s %s,%d(%%ebp,%s)", szmov[size], xreg (ea->x86_reg, size), ea->imm.val, xreg (reg1, LONG)); ! 1684: xreg_unlock (reg1); ! 1685: break; ! 1686: /* areg offset + reg */ ! 1687: case 6: ! 1688: reg1 = xload_reg (ea->reg, LONG, -1); ! 1689: if (ea->ext._.size) { ! 1690: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1691: } else { ! 1692: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1693: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1694: reg2 = xalloc_reg (LONG, -1); ! 1695: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1696: xreg_unlock (reg3); ! 1697: } ! 1698: do_bswap (ea->x86_reg, size); ! 1699: xln ("mov%s %s,(MemBase+%d)(%s,%s)", szmov[size], xreg (ea->x86_reg, size), ea->ext._.displacement, xreg (reg1,LONG), xreg (reg2,LONG)); ! 1700: xreg_unlock (reg1); ! 1701: xreg_unlock (reg2); ! 1702: break; ! 1703: /* yes */ ! 1704: case 7: ! 1705: /* XXX TO DO */ ! 1706: /* $xxx.w */ ! 1707: if (ea->reg == 0) { ! 1708: do_bswap (ea->x86_reg, size); ! 1709: xln ("mov%s %s,%d(%%ebp)", szmov[size], xreg (ea->x86_reg, size), ea->imm.val); ! 1710: } ! 1711: /* $xxx.l */ ! 1712: else if (ea->reg == 1) { ! 1713: if (ea->imm.has_label) { ! 1714: do_bswap (ea->x86_reg, size); ! 1715: xln ("mov%s %s,__D%s(%%ebp)", szmov[size], xreg (ea->x86_reg, size), ea->imm.label); ! 1716: } else { ! 1717: do_bswap (ea->x86_reg, size); ! 1718: xln ("mov%s %s,%d(%%ebp)", szmov[size], xreg (ea->x86_reg, size), ea->imm.val); ! 1719: } ! 1720: } ! 1721: /* immediate */ ! 1722: else if (ea->reg == 4) { ! 1723: assert (0); ! 1724: } ! 1725: /* PC + offset */ ! 1726: else if (ea->reg == 2) { ! 1727: assert (ea->imm.has_label); ! 1728: ! 1729: do_bswap (ea->x86_reg, size); ! 1730: xln ("mov%s %s,__D%s(%%ebp)", szmov[size], xreg (ea->x86_reg, size), ea->imm.label); ! 1731: } ! 1732: /* PC + INDEX + OFFSET */ ! 1733: else if (ea->reg == 3) { ! 1734: assert (ea->imm.has_label); ! 1735: if (ea->ext._.size) { ! 1736: reg2 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1737: } else { ! 1738: /* need fucking 16-bit chunk of variable sign extended to 32... */ ! 1739: reg3 = xload_reg (ea->ext._.reg + (ea->ext._.d_or_a ? 8 : 0), LONG, -1); ! 1740: reg2 = xalloc_reg (LONG, -1); ! 1741: xln ("movswl %s,%s", xreg (reg3, WORD), xreg (reg2, LONG)); ! 1742: xreg_unlock (reg3); ! 1743: } ! 1744: do_bswap (ea->x86_reg, size); ! 1745: xln ("mov%s %s,__D%s(%%ebp,%s)", szmov[size], xreg (ea->x86_reg,size), ea->imm.label, xreg (reg2,LONG)); ! 1746: xreg_unlock (reg2); ! 1747: } ! 1748: else { ! 1749: error ("wtf in c_writeea ()"); ! 1750: } ! 1751: break; ! 1752: default: ! 1753: error ("nasty error in c_writeea()"); ! 1754: } ! 1755: } ! 1756: ! 1757: static void x_ea_set_val_2_reg (ea_t *ea, int size, int x86_reg) ! 1758: { ! 1759: int i; ! 1760: assert (size == LONG); ! 1761: ! 1762: ea->do_writeback = 1; ! 1763: ea->x86_reg_writeback = -1; ! 1764: ! 1765: if ((ea->mode == 0) || (ea->mode == 1)) { ! 1766: i = xfind_reg (ea->reg); ! 1767: ! 1768: if (i != -1) { ! 1769: /* reg already loaded, but we are wiping ! 1770: * the bastard with a full LONG write so drop ! 1771: * the existing regalloc */ ! 1772: assert (i386_regalloc[i].locked == 0); ! 1773: i386_regalloc[i].m68k_reg = -1; ! 1774: i386_regalloc[i].dirty = 0; ! 1775: } ! 1776: i386_regalloc[x86_reg].m68k_reg = ea->reg; ! 1777: i386_regalloc[x86_reg].dirty = 1; ! 1778: ! 1779: ea->x86_reg = x86_reg; ! 1780: } else { ! 1781: i386_regalloc[x86_reg].m68k_reg = REG_TEMP; ! 1782: ea->x86_reg = x86_reg; ! 1783: } ! 1784: i386_regalloc[x86_reg].locked++; ! 1785: i386_regalloc[x86_reg].age = 0; ! 1786: } ! 1787: ! 1788: static void x_cond_end () ! 1789: { ! 1790: xout ("2:\n"); ! 1791: } ! 1792: ! 1793: static void x_cond_begin (int cond) ! 1794: { ! 1795: switch (cond) { ! 1796: /* t */ ! 1797: case 0: break; ! 1798: /* f */ ! 1799: case 1: xln ("jmp 2f"); break; ! 1800: /* hi */ ! 1801: case 2: ! 1802: xln ("movb C,%%al"); ! 1803: xln ("orb Z,%%al"); ! 1804: xln ("jnz 2f"); ! 1805: break; ! 1806: //cout ("((!C) && !Z)"); break; ! 1807: /* ls */ ! 1808: case 3: ! 1809: xln ("movb C,%%al"); ! 1810: xln ("orb Z,%%al"); ! 1811: xln ("jz 2f"); ! 1812: break; ! 1813: //cout ("(C || Z)"); break; ! 1814: /* cc */ ! 1815: case 4: ! 1816: xln ("testb $1,C"); ! 1817: xln ("jnz 2f"); ! 1818: break; ! 1819: //cout ("(!C)"); break; ! 1820: /* cs */ ! 1821: case 5: ! 1822: xln ("testb $1,C"); ! 1823: xln ("jz 2f"); ! 1824: break; ! 1825: //cout ("C"); break; ! 1826: /* ne */ ! 1827: case 6: ! 1828: xln ("testb $1,Z"); ! 1829: xln ("jnz 2f"); ! 1830: break; ! 1831: //cout ("!Z"); break; ! 1832: /* eq */ ! 1833: case 7: ! 1834: xln ("testb $1,Z"); ! 1835: xln ("jz 2f"); ! 1836: break; ! 1837: //cout ("(Z)"); break; ! 1838: /* vc */ ! 1839: case 8: ! 1840: xln ("testb $1,V"); ! 1841: xln ("jnz 2f"); ! 1842: break; ! 1843: //cout ("(!V)"); break; ! 1844: /* vs */ ! 1845: case 9: ! 1846: xln ("testb $1,V"); ! 1847: xln ("jz 2f"); ! 1848: break; ! 1849: //cout ("V"); break; ! 1850: /* pl */ ! 1851: case 10: ! 1852: xln ("testb $1,N"); ! 1853: xln ("jnz 2f"); ! 1854: break; ! 1855: //cout ("(!N)"); break; ! 1856: /* mi */ ! 1857: case 11: ! 1858: xln ("testb $1,N"); ! 1859: xln ("jz 2f"); ! 1860: break; ! 1861: //cout ("N"); break; ! 1862: /* ge */ ! 1863: case 12: ! 1864: xln ("movb N,%%al"); ! 1865: xln ("xorb V,%%al"); ! 1866: xln ("jnz 2f"); ! 1867: break; ! 1868: //cout ("((N && V) || ((!N) && (!V)))"); break; ! 1869: /* lt */ ! 1870: case 13: ! 1871: xln ("movb V,%%al"); ! 1872: xln ("xorb $1,%%al"); ! 1873: xln ("xorb N,%%al"); ! 1874: xln ("jnz 2f"); ! 1875: break; ! 1876: //cout ("((N && (!V)) || ((!N) && V))"); break; ! 1877: /* gt */ ! 1878: case 14: ! 1879: xln ("movb N,%%al"); ! 1880: xln ("xorb V,%%al"); ! 1881: xln ("orb Z,%%al"); ! 1882: xln ("jnz 2f"); ! 1883: break; ! 1884: //cout ("((N && V && (!Z)) || ((!N) && (!V) && (!Z)))"); break; ! 1885: /* le */ ! 1886: case 15: ! 1887: xln ("movb Z,%%ah"); ! 1888: xln ("movb V,%%al"); ! 1889: xln ("xorb $1,%%ah"); ! 1890: xln ("xorb $1,%%al"); ! 1891: xln ("xorb N,%%al"); ! 1892: xln ("andb %%ah,%%al"); ! 1893: xln ("jnz 2f"); ! 1894: break; ! 1895: //cout ("((Z) || (N && (!V)) || ((!N) && V))"); break; ! 1896: } ! 1897: } ! 1898: ! 1899: void i386_jump (ea_t *ea) ! 1900: { ! 1901: xflush_all (); ! 1902: if (((ea->mode == 7) && (ea->reg == 1)) || ! 1903: ((ea->mode == 7) && (ea->reg == 2))) { ! 1904: xln ("jmp __N%s", ea->imm.label); ! 1905: } else { ! 1906: xold_ea_get_address (ea, 0, 0); ! 1907: xold_ea_get_address (ea, 0, 1); ! 1908: x_postea (ea); ! 1909: //xln ("jmp jumptable"); ! 1910: xln ("jmp *jtab(,%%eax,2)"); ! 1911: } ! 1912: } ! 1913: ! 1914: /* Check for pending exceptions also */ ! 1915: void i386_jump_e (ea_t *ea) ! 1916: { ! 1917: xflush_all (); ! 1918: xln ("cmpl $0,exceptions_pending_mask"); ! 1919: ! 1920: /* yay! exception */ ! 1921: if (((ea->mode == 7) && (ea->reg == 1)) || ! 1922: ((ea->mode == 7) && (ea->reg == 2))) { ! 1923: xln ("movl $__D%s,%%eax", ea->imm.label); ! 1924: } else { ! 1925: xold_ea_get_address (ea, 0, 0); ! 1926: xold_ea_get_address (ea, 0, 1); ! 1927: x_postea (ea); ! 1928: } ! 1929: xln ("jnz handle_exception"); ! 1930: i386_jump (ea); ! 1931: } ! 1932: ! 1933: static void i386_func_bitop (ea_t *src, ea_t *dest, int size, const char *op) ! 1934: { ! 1935: int len = size2len [size]; ! 1936: ! 1937: xflush_all (); ! 1938: ! 1939: if (is_immediate (src)) { ! 1940: xold_readea (dest, 1, 0); ! 1941: xold_readea (dest, 1, 1); ! 1942: xold_readea (dest, 1, 1); ! 1943: ! 1944: xln ("%sl $%d,%%ebx", op, src->imm.val & (len-1)); ! 1945: ifZ xln ("setnc Z"); ! 1946: ! 1947: xold_writeea (dest, size, EBX, 0); ! 1948: xold_writeea (dest, size, EBX, 1); ! 1949: xold_writeea (dest, size, EBX, 1); ! 1950: ! 1951: x_postea (dest); ! 1952: return; ! 1953: } ! 1954: ! 1955: xold_readea (src, 0, 0); ! 1956: xold_readea (dest, 1, 0); ! 1957: xold_readea (src, 0, 1); ! 1958: xold_readea (dest, 1, 1); ! 1959: xold_readea (src, 0, 1); ! 1960: xold_readea (dest, 1, 1); ! 1961: ! 1962: if (size == BYTE) xln ("andl $7,%%eax"); ! 1963: xln ("%sl %%eax,%%ebx", op, src->imm.val); ! 1964: ifZ xln ("setnc Z"); ! 1965: ! 1966: xold_writeea (dest, size, EBX, 0); ! 1967: xold_writeea (dest, size, EBX, 1); ! 1968: xold_writeea (dest, size, EBX, 1); ! 1969: ! 1970: x_postea (src); ! 1971: x_postea (dest); ! 1972: } ! 1973: ! 1974: void i386_func_bchg (ea_t *src, ea_t *dest, int size) ! 1975: { ! 1976: i386_func_bitop (src, dest, size, "btc"); ! 1977: } ! 1978: ! 1979: void i386_func_bclr (ea_t *src, ea_t *dest, int size) ! 1980: { ! 1981: i386_func_bitop (src, dest, size, "btr"); ! 1982: } ! 1983: ! 1984: void i386_func_bset (ea_t *src, ea_t *dest, int size) ! 1985: { ! 1986: i386_func_bitop (src, dest, size, "bts"); ! 1987: } ! 1988: ! 1989: void i386_func_btst (ea_t *src, ea_t *dest, int size) ! 1990: { ! 1991: int len = size2len [size]; ! 1992: ! 1993: xflush_all (); ! 1994: ! 1995: if (is_immediate (src)) { ! 1996: xold_readea (dest, 1, 0); ! 1997: xold_readea (dest, 1, 1); ! 1998: xold_readea (dest, 1, 1); ! 1999: ! 2000: xln ("btl $%d,%%ebx", src->imm.val & (len-1)); ! 2001: xln ("setnc Z"); ! 2002: ! 2003: x_postea (dest); ! 2004: return; ! 2005: } ! 2006: ! 2007: xold_readea (src, 0, 0); ! 2008: xold_readea (dest, 1, 0); ! 2009: xold_readea (src, 0, 1); ! 2010: xold_readea (dest, 1, 1); ! 2011: xold_readea (src, 0, 1); ! 2012: xold_readea (dest, 1, 1); ! 2013: ! 2014: if (size == BYTE) xln ("andl $7,%%eax"); ! 2015: xln ("btl %%eax,%%ebx", src->imm.val); ! 2016: xln ("setnc Z"); ! 2017: ! 2018: x_postea (src); ! 2019: x_postea (dest); ! 2020: } ! 2021: ! 2022: void i386_func_muls (ea_t *src, ea_t *dest) ! 2023: { ! 2024: assert (dest->mode == 0); ! 2025: src->op_size = WORD; ! 2026: x_loadval (src, -1, XCAN_OVERWRITE); ! 2027: dest->op_size = WORD; ! 2028: x_loadval (dest, -1, 0);//XSIGN_EXTEND_REGS); ! 2029: ! 2030: xln ("movswl %s,%s", src->identifier, xreg (src->x86_reg, LONG)); ! 2031: xln ("movswl %s,%s", dest->identifier, xreg (dest->x86_reg, LONG)); ! 2032: ! 2033: xln ("imull %s,%s", xreg (src->x86_reg, LONG), xreg (dest->x86_reg, LONG)); ! 2034: ifNVC xln ("movb $0,C"); ! 2035: ifNVC xln ("movb $0,V"); ! 2036: ifZNVC xln ("testl %s,%s", xreg (dest->x86_reg, LONG), xreg (dest->x86_reg, LONG)); ! 2037: ifNVC xln ("sets N"); ! 2038: ifZ xln ("setz Z"); ! 2039: ! 2040: xdirty_reg (dest->x86_reg); ! 2041: x_saveval (dest, WORD); ! 2042: x_postea (src); ! 2043: x_postea (dest); ! 2044: } ! 2045: void i386_func_mulu (ea_t *src, ea_t *dest) ! 2046: { ! 2047: xflush_all (); ! 2048: xold_readea2 (src, 1, 0, XQUICK_REGS); ! 2049: xold_readea2 (dest, 0, 0, XQUICK_REGS); ! 2050: xold_readea2 (src, 1, 1, XQUICK_REGS); ! 2051: xold_readea2 (dest, 0, 1, XQUICK_REGS); ! 2052: xold_readea2 (src, 1, 1, XQUICK_REGS); ! 2053: xold_readea2 (dest, 0, 1, XQUICK_REGS); ! 2054: ! 2055: xln ("movzwl %s,%%ebx", src->identifier); ! 2056: xln ("movzwl %s,%%eax", dest->identifier); ! 2057: ! 2058: xln ("mull %%ebx"); ! 2059: ifNVC xln ("movb $0,C"); ! 2060: ifNVC xln ("movb $0,V"); ! 2061: ifZNVC xln ("testl %%eax,%%eax"); ! 2062: ifNVC xln ("sets N"); ! 2063: ifZ xln ("setz Z"); ! 2064: ! 2065: /* hack - force writeback, because we didn't operate in-place */ ! 2066: dest->do_writeback = 1; ! 2067: ! 2068: xold_writeea (dest, LONG, EAX, 0); ! 2069: xold_writeea (dest, LONG, EAX, 1); ! 2070: xold_writeea (dest, LONG, EAX, 1); ! 2071: x_postea (src); ! 2072: x_postea (dest); ! 2073: } ! 2074: ! 2075: void i386_func_logop (ea_t *src, ea_t *dest, int size, char op) ! 2076: { ! 2077: x_loadval (src, -1, XQUICK_REGS | XQUICK_IMMS); ! 2078: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2079: ! 2080: switch (op) { ! 2081: case '&': xln ("and%s %s,%s", szmov [size], src->identifier, dest->identifier); break; ! 2082: case '|': xln ("or%s %s,%s", szmov [size], src->identifier, dest->identifier); break; ! 2083: case '^': xln ("xor%s %s,%s", szmov [size], src->identifier, dest->identifier); break; ! 2084: default: assert (0); ! 2085: } ! 2086: ! 2087: ifNVC xln ("sets N"); ! 2088: ifZ xln ("setz Z"); ! 2089: ifNVC xln ("movb $0,V"); ! 2090: ifNVC xln ("movb $0,C"); ! 2091: ! 2092: xdirty_reg (dest->x86_reg); ! 2093: x_saveval (dest, size); ! 2094: x_postea (src); ! 2095: x_postea (dest); ! 2096: } ! 2097: ! 2098: void i386_func_not (ea_t *ea, int size) ! 2099: { ! 2100: int flags = XQUICK_WRITEBACK; ! 2101: /* mem to mem operations are crap */ ! 2102: //ifZNVC {} else flags |= XQUICK_REGS; ! 2103: ! 2104: x_loadval (ea, -1, flags); ! 2105: ! 2106: xln ("not%s %s", szmov [size], ea->identifier); ! 2107: ! 2108: ifZNVC xln ("test%s %s,%s", szmov [size], ea->identifier, ea->identifier); ! 2109: ifNVC xln ("sets N"); ! 2110: ifZ xln ("setz Z"); ! 2111: ifNVC xln ("movb $0,V"); ! 2112: ifNVC xln ("movb $0,C"); ! 2113: ! 2114: xdirty_reg (ea->x86_reg); ! 2115: x_saveval (ea, size); ! 2116: x_postea (ea); ! 2117: } ! 2118: ! 2119: void i386_func_negx (ea_t *ea, int size) ! 2120: { ! 2121: xflush_all (); ! 2122: xold_readea (ea, 0, 0); ! 2123: xold_readea (ea, 0, 1); ! 2124: xold_readea (ea, 0, 1); ! 2125: ! 2126: // XXX this is crap. do without jumps (negx) ! 2127: // then again, negx and subx caused so many problems ! 2128: // and took so long to get right that who cares.. ! 2129: xln ("xorl %%ebx,%%ebx"); ! 2130: xln ("movb X,%%cl"); ! 2131: xln ("testb %%cl,%%cl"); ! 2132: xln ("jz 1f"); ! 2133: xln ("stc"); ! 2134: xln ("jmp 2f"); ! 2135: ! 2136: xout ("1:\n"); ! 2137: xln ("clc"); ! 2138: ! 2139: xout ("2:\n"); ! 2140: xln ("sbb%s %s,%s", szmov [size], sreg (EAX), sreg (EBX)); ! 2141: ifNVC { ! 2142: xln ("sets N"); ! 2143: xln ("seto V"); ! 2144: xln ("setc C"); ! 2145: } ! 2146: xln ("setc X"); ! 2147: ifZ { ! 2148: xln ("test%s %s,%s", szmov[size], sreg (EBX), sreg (EBX)); ! 2149: xln ("jz 1f"); ! 2150: xln ("movb $0,Z"); ! 2151: xout ("1:\n"); ! 2152: } ! 2153: ! 2154: xold_writeea (ea, size, EBX, 0); ! 2155: xold_writeea (ea, size, EBX, 1); ! 2156: xold_writeea (ea, size, EBX, 1); ! 2157: x_postea (ea); ! 2158: } ! 2159: void i386_func_neg (ea_t *ea, int size) ! 2160: { ! 2161: x_loadval (ea, -1, XQUICK_WRITEBACK); ! 2162: ! 2163: xln ("neg%s %s", szmov [size], ea->identifier); ! 2164: ifNVC { ! 2165: xln ("sets N"); ! 2166: xln ("seto V"); ! 2167: xln ("setc C"); ! 2168: } ! 2169: ifZ xln ("setz Z"); ! 2170: xln ("setc X"); ! 2171: ! 2172: xdirty_reg (ea->x86_reg); ! 2173: x_saveval (ea, size); ! 2174: x_postea (ea); ! 2175: } ! 2176: ! 2177: void i386_func_divu (ea_t *ea, int reg) ! 2178: { ! 2179: xflush_all (); ! 2180: ea->op_size = WORD; ! 2181: xold_readea (ea, 1, 0); ! 2182: xold_readea (ea, 1, 1); ! 2183: xold_readea (ea, 1, 1); ! 2184: ! 2185: xln ("movl %d(%%ebp),%%eax", regpos (reg)); ! 2186: xln ("movzwl %%bx,%%ebx"); ! 2187: xln ("xorl %%edx,%%edx"); ! 2188: xln ("divl %%ebx"); ! 2189: ! 2190: xln ("testl $0xffff0000,%%eax"); ! 2191: /* overflow */ ! 2192: xln ("jnz 1f"); ! 2193: ! 2194: ifZNVC xln ("testl %%eax,%%eax"); ! 2195: ifNVC xln ("sets N"); ! 2196: ifZ xln ("setz Z"); ! 2197: ifNVC xln ("movb $0,V"); ! 2198: ifNVC xln ("movb $0,C"); ! 2199: ! 2200: xln ("shll $16,%%edx"); ! 2201: xln ("movw %%ax,%%dx"); ! 2202: ! 2203: xln ("movl %%edx,%d(%%ebp)", regpos (reg)); ! 2204: xln ("jmp 2f"); ! 2205: xout ("1:\n"); ! 2206: ifZNVC { ! 2207: xln ("movb $0,C"); ! 2208: xln ("movb $1,N"); ! 2209: xln ("movb $0,Z"); ! 2210: xln ("movb $1,V"); ! 2211: } ! 2212: xout ("2:\n"); ! 2213: x_postea (ea); ! 2214: } ! 2215: ! 2216: void i386_func_divs (ea_t *ea, int reg) ! 2217: { ! 2218: xflush_all (); ! 2219: ea->op_size = WORD; ! 2220: xold_readea (ea, 1, 0); ! 2221: xold_readea (ea, 1, 1); ! 2222: xold_readea (ea, 1, 1); ! 2223: ! 2224: xln ("movl %d(%%ebp),%%eax", regpos (reg)); ! 2225: xln ("movswl %%bx,%%ebx"); ! 2226: /* sign-extend eax into edx */ ! 2227: xln ("cltd"); ! 2228: xln ("idivl %%ebx"); ! 2229: xln ("jmp 3f"); ! 2230: /* success */ ! 2231: xout ("1:\n"); ! 2232: ! 2233: ifZNVC xln ("testl %%eax,%%eax"); ! 2234: ifNVC xln ("sets N"); ! 2235: ifZ xln ("setz Z"); ! 2236: ! 2237: xln ("shll $16,%%edx"); ! 2238: ifNVC xln ("movb $0,V"); ! 2239: xln ("movw %%ax,%%dx"); ! 2240: ifNVC xln ("movb $0,C"); ! 2241: xln ("movl %%edx,%d(%%ebp)", regpos (reg)); ! 2242: xln ("jmp 2f"); ! 2243: /* overflow */ ! 2244: xout ("3:\n"); ! 2245: xln ("movl %%eax,%%ecx"); ! 2246: xln ("andl $0xffff8000,%%ecx"); ! 2247: xln ("jz 1b"); ! 2248: xln ("cmpl $0xffff8000,%%ecx"); ! 2249: xln ("jz 1b"); ! 2250: ifNVC { ! 2251: xln ("movb $0,C"); ! 2252: xln ("movb $1,N"); ! 2253: xln ("movb $1,V"); ! 2254: } ifZ xln ("movb $0,Z"); ! 2255: xout ("2:\n"); ! 2256: x_postea (ea); ! 2257: } ! 2258: ! 2259: /* src is the shift */ ! 2260: /* these are such cunts */ ! 2261: void i386_func_asl (ea_t *src, ea_t *dest, int size) ! 2262: { ! 2263: /* special case we can optimise happily. no flags except X || Z needed, and ! 2264: * immediate src, reg dest. */ ! 2265: ifNVC { } else if (is_immediate (src) && is_reg (dest)) { ! 2266: x_loadval (src, -1, XQUICK_IMMS); ! 2267: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2268: ! 2269: xln ("shl%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2270: xln ("setc X"); ! 2271: ifZ xln ("setz Z"); ! 2272: ! 2273: xdirty_reg (dest->x86_reg); ! 2274: x_saveval (dest, size); ! 2275: x_postea (src); ! 2276: x_postea (dest); ! 2277: return; ! 2278: } ! 2279: xflush_all (); ! 2280: xold_readea (src, 0, 0); ! 2281: xold_readea (dest, 1, 0); ! 2282: xold_readea (src, 0, 1); ! 2283: xold_readea (dest, 1, 1); ! 2284: xold_readea (src, 0, 1); ! 2285: xold_readea (dest, 1, 1); ! 2286: ! 2287: /* sets flags wrong. can use with flag optimisations one day */ ! 2288: ! 2289: /* V flag not set by sal on x86 :( */ ! 2290: ! 2291: xln ("and%s $63,%s", szmov[size], sreg (EAX)); ! 2292: xln ("cmp%s $%d,%s", szmov[size], size2len[size], sreg (EAX)); ! 2293: xln ("jl 2f"); ! 2294: ! 2295: xln ("test%s %s,%s", szmov[size], sreg (EBX), sreg (EBX)); ! 2296: xln ("setnz V"); ! 2297: xln ("movb $1,Z"); ! 2298: xln ("movb $0,N"); ! 2299: /* XXX what should be done about C and X... */ ! 2300: xln ("xor%s %s,%s", szmov[size], sreg (EBX), sreg (EBX)); ! 2301: xln ("jmp 4f"); ! 2302: ! 2303: /* mask in edx */ ! 2304: xout ("2:\n"); ! 2305: ifNVC { ! 2306: xln ("movb $%d,%%cl", size2len[size]-1); ! 2307: xln ("mov%s $0x%s,%s", szmov[size], ! 2308: (size == BYTE ? "ff" : ! 2309: (size == WORD ? "ffff" : "ffffffff")), sreg (EDX)); ! 2310: xln ("subb %%al,%%cl"); ! 2311: xln ("movb $0,V"); ! 2312: xln ("shl%s %%cl,%s", szmov[size], sreg (EDX)); ! 2313: xln ("mov%s %s,%s", szmov[size], sreg (EDX), sreg (ECX)); ! 2314: ! 2315: /* V = ((val & mask) != mask &&) ! 2316: * ((val & mask != 0) */ ! 2317: xln ("test%s %s,%s", szmov[size], sreg (EBX), sreg (EDX)); ! 2318: xln ("jz 3f"); ! 2319: xln ("and%s %s,%s", szmov[size], sreg (EBX), sreg (EDX)); ! 2320: xln ("cmp%s %s,%s", szmov[size], sreg (ECX), sreg (EDX)); ! 2321: xln ("setnz V"); ! 2322: /* ^^ huge amount of code for one fucking flag... */ ! 2323: ! 2324: xout ("3:\n"); ! 2325: } ! 2326: xln ("movb %%al,%%cl"); ! 2327: xln ("shl%s %%cl,%s", szmov [size], sreg (EBX)); ! 2328: ! 2329: ifNVC { ! 2330: xln ("sets N"); ! 2331: xln ("setc C"); ! 2332: } ! 2333: xln ("setc X"); ! 2334: ! 2335: if (!is_immediate (src)) { ! 2336: /* shifts of zero bits set the Z flag on x86, apparently */ ! 2337: /* (immediate shifts can't be zero) */ ! 2338: ifZ xln ("test%s %s,%s", szmov[size], sreg (EBX), sreg (EBX)); ! 2339: } ! 2340: ifZ xln ("setz Z"); ! 2341: ! 2342: xout ("4:\n"); ! 2343: ! 2344: xold_writeea (dest, size, EBX, 0); ! 2345: xold_writeea (dest, size, EBX, 1); ! 2346: xold_writeea (dest, size, EBX, 1); ! 2347: x_postea (src); ! 2348: x_postea (dest); ! 2349: } ! 2350: ! 2351: void i386_func_lsl (ea_t *src, ea_t *dest, int size) ! 2352: { ! 2353: x_loadval (src, ECX, XQUICK_IMMS); ! 2354: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2355: ! 2356: if (is_immediate (src)) { ! 2357: xln ("shl%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2358: } else { ! 2359: xln ("shl%s %%cl,%s", szmov [size], dest->identifier); ! 2360: } ! 2361: ! 2362: ifZ xln ("setz Z"); ! 2363: ifNVC { ! 2364: xln ("sets N"); ! 2365: xln ("setc C"); ! 2366: xln ("movb $0,V"); ! 2367: } ! 2368: ifX xln ("setc X"); ! 2369: ! 2370: xdirty_reg (dest->x86_reg); ! 2371: x_saveval (dest, size); ! 2372: x_postea (src); ! 2373: x_postea (dest); ! 2374: #if 0 ! 2375: xflush_all (); ! 2376: xold_readea2 (src, 0, 0, XQUICK_REGS | XQUICK_IMMS); ! 2377: xold_readea2 (dest, 1, 0, XQUICK_REGS); ! 2378: xold_readea2 (src, 0, 1, XQUICK_REGS | XQUICK_IMMS); ! 2379: xold_readea2 (dest, 1, 1, XQUICK_REGS); ! 2380: xold_readea2 (src, 0, 1, XQUICK_REGS | XQUICK_IMMS); ! 2381: xold_readea2 (dest, 1, 1, XQUICK_REGS); ! 2382: ! 2383: if (is_immediate (src)) { ! 2384: xln ("shl%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2385: } else { ! 2386: xln ("movl %s,%%ecx", src->identifier); ! 2387: xln ("shl%s %%cl,%s", szmov [size], dest->identifier); ! 2388: } ! 2389: ! 2390: ifZ xln ("setz Z"); ! 2391: ifNVC { ! 2392: xln ("sets N"); ! 2393: xln ("setc C"); ! 2394: xln ("movb $0,V"); ! 2395: } ! 2396: xln ("setc X"); ! 2397: ! 2398: xold_writeea (dest, size, EBX, 0); ! 2399: xold_writeea (dest, size, EBX, 1); ! 2400: xold_writeea (dest, size, EBX, 1); ! 2401: x_postea (src); ! 2402: x_postea (dest); ! 2403: #endif ! 2404: } ! 2405: ! 2406: void i386_func_roxr (ea_t *src, ea_t *dest, int size) ! 2407: { ! 2408: xflush_all (); ! 2409: if ((src->mode != F_IMM) && (src->imm.val != 1)) { ! 2410: error ("X86 output of roxr unfinished. Only supports 1 bit immediate shifts."); ! 2411: } ! 2412: ! 2413: xold_readea (dest, 1, 0); ! 2414: xold_readea (dest, 1, 1); ! 2415: xold_readea (dest, 1, 1); ! 2416: ! 2417: xln ("movb X,%%al"); ! 2418: xln ("shr%s $1,%s", szmov [size], sreg (EBX)); ! 2419: ifNVC xln ("setc C"); ! 2420: xln ("setc X"); ! 2421: xln ("shl%s $%d,%s", szmov[size], size2len [size]-1, sreg (EAX)); ! 2422: ifNVC xln ("movb $0,V"); ! 2423: xln ("or%s %s,%s", szmov [size], sreg (EAX), sreg (EBX)); ! 2424: ifZNVC xln ("test%s %s,%s", szmov [size], sreg (EBX), sreg (EBX)); ! 2425: ifNVC xln ("sets N"); ! 2426: ifZ xln ("setz Z"); ! 2427: ! 2428: xold_writeea (dest, size, EBX, 0); ! 2429: xold_writeea (dest, size, EBX, 1); ! 2430: xold_writeea (dest, size, EBX, 1); ! 2431: x_postea (dest); ! 2432: } ! 2433: void i386_func_roxl (ea_t *src, ea_t *dest, int size) ! 2434: { ! 2435: xflush_all (); ! 2436: if ((src->mode != F_IMM) && (src->imm.val != 1)) { ! 2437: error ("X86 output of roxr unfinished. Only supports 1 bit immediate shifts."); ! 2438: } ! 2439: ! 2440: xold_readea (dest, 1, 0); ! 2441: xold_readea (dest, 1, 1); ! 2442: xold_readea (dest, 1, 1); ! 2443: ! 2444: xln ("movzbl X,%%eax"); ! 2445: xln ("shl%s $1,%s", szmov [size], sreg (EBX)); ! 2446: ifNVC xln ("setc C"); ! 2447: xln ("setc X"); ! 2448: xln ("or%s %s,%s", szmov [size], sreg (EAX), sreg (EBX)); ! 2449: ifNVC xln ("movb $0,V"); ! 2450: ifZNVC xln ("test%s %s,%s", szmov [size], sreg (EBX), sreg (EBX)); ! 2451: ifNVC xln ("sets N"); ! 2452: ifZ xln ("setz Z"); ! 2453: ! 2454: xold_writeea (dest, size, EBX, 0); ! 2455: xold_writeea (dest, size, EBX, 1); ! 2456: xold_writeea (dest, size, EBX, 1); ! 2457: x_postea (dest); ! 2458: } ! 2459: void i386_func_rol (ea_t *src, ea_t *dest, int size) ! 2460: { ! 2461: int len; ! 2462: len = size2len[size]; ! 2463: /* fast case */ ! 2464: ifZNVC {} else if (is_immediate (src)) { ! 2465: x_loadval (src, -1, XQUICK_IMMS); ! 2466: x_loadval (dest, -1, XQUICK_REGS); ! 2467: ! 2468: xln ("rol%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2469: ! 2470: xdirty_reg (dest->x86_reg); ! 2471: x_saveval (dest, size); ! 2472: x_postea (src); ! 2473: x_postea (dest); ! 2474: return; ! 2475: } ! 2476: xflush_all (); ! 2477: src->op_size = BYTE; ! 2478: xold_readea (src, 0, 0); ! 2479: xold_readea (dest, 1, 0); ! 2480: xold_readea (src, 0, 1); ! 2481: xold_readea (dest, 1, 1); ! 2482: xold_readea (src, 0, 1); ! 2483: xold_readea (dest, 1, 1); ! 2484: ! 2485: xln ("movb %%al,%%cl"); ! 2486: xln ("decb %%cl"); ! 2487: xln ("rol%s %%cl,%s", szmov [size], sreg (EBX)); ! 2488: xln ("btl $%d,%%ebx", len-1); ! 2489: ifNVC xln ("setc C"); ! 2490: xln ("rol%s $1,%s", szmov [size], sreg (EBX)); ! 2491: ifNVC xln ("movb $0,V"); ! 2492: ifZNVC xln ("test%s %s,%s", szmov [size], sreg (EBX), sreg (EBX)); ! 2493: ifNVC xln ("sets N"); ! 2494: ifZ xln ("setz Z"); ! 2495: ! 2496: xold_writeea (dest, size, EBX, 0); ! 2497: xold_writeea (dest, size, EBX, 1); ! 2498: xold_writeea (dest, size, EBX, 1); ! 2499: x_postea (src); ! 2500: x_postea (dest); ! 2501: } ! 2502: ! 2503: void i386_func_ror (ea_t *src, ea_t *dest, int size) ! 2504: { ! 2505: /* fast case */ ! 2506: ifZNVC {} else if (is_immediate (src)) { ! 2507: x_loadval (src, -1, XQUICK_IMMS); ! 2508: x_loadval (dest, -1, 0); ! 2509: ! 2510: xln ("ror%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2511: ! 2512: xdirty_reg (dest->x86_reg); ! 2513: x_saveval (dest, size); ! 2514: x_postea (src); ! 2515: x_postea (dest); ! 2516: return; ! 2517: } ! 2518: xflush_all (); ! 2519: xold_readea (src, 0, 0); ! 2520: xold_readea (dest, 1, 0); ! 2521: xold_readea (src, 0, 1); ! 2522: xold_readea (dest, 1, 1); ! 2523: xold_readea (src, 0, 1); ! 2524: xold_readea (dest, 1, 1); ! 2525: ! 2526: /* x86 ror doesn't set flags... */ ! 2527: xln ("movb %%al,%%cl"); ! 2528: xln ("decb %%cl"); ! 2529: xln ("ror%s %%cl,%s", szmov [size], sreg (EBX)); ! 2530: xln ("btl $0,%%ebx"); ! 2531: ifNVC xln ("setc C"); ! 2532: xln ("ror%s $1,%s", szmov [size], sreg (EBX)); ! 2533: ifNVC xln ("movb $0,V"); ! 2534: ifZNVC xln ("test%s %s,%s", szmov [size], sreg (EBX), sreg (EBX)); ! 2535: ifNVC xln ("sets N"); ! 2536: ifZ xln ("setz Z"); ! 2537: ! 2538: xold_writeea (dest, size, EBX, 0); ! 2539: xold_writeea (dest, size, EBX, 1); ! 2540: xold_writeea (dest, size, EBX, 1); ! 2541: x_postea (src); ! 2542: x_postea (dest); ! 2543: } ! 2544: ! 2545: void i386_func_asr (ea_t *src, ea_t *dest, int size) ! 2546: { ! 2547: /* special case we can optimise happily. immediate src. */ ! 2548: if (is_immediate (src) && is_reg (dest)) { ! 2549: x_loadval (src, -1, XQUICK_IMMS); ! 2550: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2551: ! 2552: xln ("sar%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2553: ifNVC { ! 2554: xln ("seto V"); ! 2555: xln ("setc C"); ! 2556: } ! 2557: ifX xln ("setc X"); ! 2558: ifZ xln ("setz Z"); ! 2559: ifNVC xln ("sets N"); ! 2560: ! 2561: xdirty_reg (dest->x86_reg); ! 2562: x_saveval (dest, size); ! 2563: x_postea (src); ! 2564: x_postea (dest); ! 2565: return; ! 2566: } ! 2567: xflush_all (); ! 2568: xold_readea (src, 0, 0); ! 2569: xold_readea (dest, 1, 0); ! 2570: xold_readea (src, 0, 1); ! 2571: xold_readea (dest, 1, 1); ! 2572: xold_readea (src, 0, 1); ! 2573: xold_readea (dest, 1, 1); ! 2574: ! 2575: /* XXX warning if correct shift count zero behaviour matters then uncomment these */ ! 2576: // xln ("movb X,%%ch"); ! 2577: xln ("movb %%al,%%cl"); ! 2578: xln ("cmpb $%d,%%al", size2len[size]); ! 2579: xln ("jns 2f"); ! 2580: xln ("sar%s %%cl,%s", szmov [size], sreg (EBX)); ! 2581: ! 2582: ifNVC { ! 2583: xln ("seto V"); ! 2584: xln ("setc C"); ! 2585: } ! 2586: ifX xln ("setc X"); ! 2587: ifZ xln ("setz Z"); ! 2588: ifNVC xln ("sets N"); ! 2589: ! 2590: /* shift count zero do not set X... */ ! 2591: // xln ("testb %%al,%%al"); ! 2592: // xln ("jnz 1f"); ! 2593: ! 2594: // xln ("movb %%ch,X"); ! 2595: ! 2596: xout ("1:\n"); ! 2597: /* shift count > thingy. smeg */ ! 2598: // xln ("cmpb $%d,%%al", size2len[size]); ! 2599: // xln ("jns 2f"); ! 2600: ! 2601: //ifZNVC xln ("test%s %s,%s", szmov[size], sreg (EBX), sreg (EBX)); ! 2602: //ifZ xln ("setz Z"); ! 2603: ! 2604: /* Sign flag is crap with val=0 */ ! 2605: //ifNVC xln ("sets N"); ! 2606: ! 2607: xln ("jmp 3f"); ! 2608: xout ("2:\n"); ! 2609: xln ("mov%s $0,%s", szmov[size], sreg (EBX)); ! 2610: xln ("movb $0,Z"); ! 2611: xout ("3:\n"); ! 2612: ! 2613: xold_writeea (dest, size, EBX, 0); ! 2614: xold_writeea (dest, size, EBX, 1); ! 2615: xold_writeea (dest, size, EBX, 1); ! 2616: x_postea (src); ! 2617: x_postea (dest); ! 2618: } ! 2619: void i386_func_lsr (ea_t *src, ea_t *dest, int size) ! 2620: { ! 2621: /* special case we can optimise happily. no flags except X || Z needed, and ! 2622: * immediate src, reg dest. */ ! 2623: if (is_immediate (src) && is_reg (dest)) { ! 2624: x_loadval (src, -1, XQUICK_IMMS); ! 2625: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2626: ! 2627: xln ("shr%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2628: ifZ xln ("setz Z"); ! 2629: ifX xln ("setc X"); ! 2630: ifNVC { ! 2631: xln ("sets N"); ! 2632: xln ("setc C"); ! 2633: xln ("movb $0,V"); ! 2634: } ! 2635: ! 2636: xdirty_reg (dest->x86_reg); ! 2637: x_saveval (dest, size); ! 2638: x_postea (src); ! 2639: x_postea (dest); ! 2640: return; ! 2641: } ! 2642: xflush_all (); ! 2643: xold_readea2 (src, 0, 0, XQUICK_REGS); ! 2644: xold_readea2 (dest, 1, 0, XQUICK_REGS); ! 2645: xold_readea2 (src, 0, 1, XQUICK_REGS); ! 2646: xold_readea2 (dest, 1, 1, XQUICK_REGS); ! 2647: xold_readea2 (src, 0, 1, XQUICK_REGS); ! 2648: xold_readea2 (dest, 1, 1, XQUICK_REGS); ! 2649: ! 2650: xln ("movl %s,%%ecx", src->identifier); ! 2651: xln ("movb X,%%ah"); ! 2652: xln ("shr%s %%cl,%s", szmov [size], dest->identifier); ! 2653: ! 2654: ifZ xln ("setz Z"); ! 2655: xln ("setc X"); ! 2656: ifNVC { ! 2657: xln ("sets N"); ! 2658: xln ("setc C"); ! 2659: xln ("movb $0,V"); ! 2660: } ! 2661: ! 2662: /* shift count of zero is special.. (and never in immediate case) */ ! 2663: if (!is_immediate (src)) { ! 2664: xln ("testb %%al,%%al"); ! 2665: xln ("jnz 1f"); ! 2666: xln ("movb $0,C"); ! 2667: xln ("movb %%ah,X"); ! 2668: } ! 2669: ! 2670: xout ("1:\n"); ! 2671: xold_writeea (dest, size, EBX, 0); ! 2672: xold_writeea (dest, size, EBX, 1); ! 2673: xold_writeea (dest, size, EBX, 1); ! 2674: x_postea (src); ! 2675: x_postea (dest); ! 2676: } ! 2677: ! 2678: void i386_func_movem (ea_t *ea, int sz, int dr, int reg_mask) ! 2679: { ! 2680: int i, offset, reg; ! 2681: sz++; ! 2682: ea_t dummy; ! 2683: ! 2684: x_loadea (ea); ! 2685: ! 2686: if (dr == 0) { ! 2687: /* reg to memory */ ! 2688: if (ea->mode == 4) { ! 2689: /* pre-decrement mode */ ! 2690: offset = 0; ! 2691: for (i=0; i<16; i++) { ! 2692: if (reg_mask & (1<<i)) { ! 2693: reg = xcopy_reg (15-i, sz, -1); ! 2694: do_bswap (reg, sz); ! 2695: xln ("mov%s %s,-%d(%%ebp,%s)", szmov[sz], xreg (reg, sz), offset, ea->identifier); ! 2696: xreg_unlock (reg); ! 2697: offset += 1<<sz; ! 2698: } ! 2699: } ! 2700: reg = xload_reg (ea->reg, LONG, -1); ! 2701: xln ("subl $%d,%s", offset, xreg (reg, LONG)); ! 2702: xdirty_reg (reg); ! 2703: xreg_unlock (reg); ! 2704: } else { ! 2705: offset = 0; ! 2706: for (i=0; i<16; i++) { ! 2707: if (reg_mask & (1<<i)) { ! 2708: reg = xcopy_reg (i, sz, -1); ! 2709: do_bswap (reg, sz); ! 2710: xln ("mov%s %s,%d(%%ebp,%s)", szmov[sz], xreg (reg, sz), offset, ea->identifier); ! 2711: xreg_unlock (reg); ! 2712: offset += 1<<sz; ! 2713: } ! 2714: } ! 2715: } ! 2716: } else { ! 2717: ! 2718: /* mem to reg */ ! 2719: offset = 0; ! 2720: for (i=0; i<16; i++) { ! 2721: if (reg_mask & (1<<i)) { ! 2722: dummy.mode = 0; ! 2723: dummy.op_size = LONG; ! 2724: dummy.x86_reg = -1; ! 2725: dummy.x86_reg_writeback = -1; ! 2726: dummy.reg = i; ! 2727: reg = xalloc_reg (sz, -1); ! 2728: x_ea_set_val_2_reg (&dummy, LONG, reg); ! 2729: ! 2730: xln ("mov%s %d(%%ebp,%s),%s", szmov[sz], offset, ea->identifier, xreg (reg, sz)); ! 2731: do_bswap (reg, sz); ! 2732: if (sz == WORD) xln ("movswl %s,%s", xreg (reg, WORD), xreg (reg, LONG)); ! 2733: offset += 1<<sz; ! 2734: ! 2735: /* once for xalloc_reg and once for x_ea_set_val_2_reg */ ! 2736: xreg_unlock (reg); ! 2737: xreg_unlock (reg); ! 2738: } ! 2739: } ! 2740: /* post-inc mode */ ! 2741: if (ea->mode == 3) { ! 2742: reg = xload_reg (ea->reg, LONG, -1); ! 2743: xln ("addl $%d,%s", offset, xreg (reg, LONG)); ! 2744: xdirty_reg (reg); ! 2745: xreg_unlock (reg); ! 2746: } ! 2747: } ! 2748: /* deallocate temporary register allocations */ ! 2749: if (ea->x86_reg != -1) { ! 2750: xreg_unlock (ea->x86_reg); ! 2751: } ! 2752: } ! 2753: ! 2754: void i386_func_subx (ea_t *src, ea_t *dest, int size) ! 2755: { ! 2756: xflush_all (); ! 2757: xold_readea (src, 0, 0); ! 2758: xold_readea (dest, 1, 0); ! 2759: xold_readea (src, 0, 1); ! 2760: xold_readea (dest, 1, 1); ! 2761: xold_readea (src, 0, 1); ! 2762: xold_readea (dest, 1, 1); ! 2763: ! 2764: /* fucking X flag */ ! 2765: ifNVCX { ! 2766: xln ("mov%s %s,%s", szmov[size], sreg (EAX), sreg (ECX)); ! 2767: xln ("mov%s %s,%s", szmov[size], sreg (EBX), sreg (EDX)); ! 2768: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (ECX)); ! 2769: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (EDX)); ! 2770: } ! 2771: xln ("add%s X,%s", szmov [size], sreg (EAX)); ! 2772: xln ("sub%s %s,%s", szmov [size], sreg (EAX), sreg (EBX)); ! 2773: ! 2774: ifNVC { ! 2775: xln ("sets N"); ! 2776: xln ("seto V"); ! 2777: } ! 2778: ! 2779: ifZ { ! 2780: xln ("jz 1f"); ! 2781: xln ("movb $0,Z"); ! 2782: xout ("1:\n"); ! 2783: } ! 2784: ! 2785: ifNVCX { ! 2786: /* fucking X flag */ ! 2787: xln ("mov%s %s,%s", szmov[size], sreg (EBX), sreg (EAX)); ! 2788: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (EAX)); ! 2789: /* ecx=flgs, edx=flgo, eax=flgn */ ! 2790: xln ("xor%s %s,%s", szmov[size], sreg (EAX), sreg (EDX)); ! 2791: xln ("xor%s %s,%s", szmov[size], sreg (ECX), sreg (EAX)); ! 2792: xln ("and%s %s,%s", szmov[size], sreg (EDX), sreg (EAX)); ! 2793: xln ("xor%s %s,%s", szmov[size], sreg (EAX), sreg (ECX)); ! 2794: ifX xln ("movb %%cl,X"); ! 2795: ifNVC xln ("movb %%cl,C"); ! 2796: } ! 2797: ! 2798: xold_writeea (dest, size, EBX, 0); ! 2799: xold_writeea (dest, size, EBX, 1); ! 2800: xold_writeea (dest, size, EBX, 1); ! 2801: x_postea (src); ! 2802: x_postea (dest); ! 2803: } ! 2804: ! 2805: void i386_func_addx (ea_t *src, ea_t *dest, int size) ! 2806: { ! 2807: xflush_all (); ! 2808: xold_readea (src, 0, 0); ! 2809: xold_readea (dest, 1, 0); ! 2810: xold_readea (src, 0, 1); ! 2811: xold_readea (dest, 1, 1); ! 2812: xold_readea (src, 0, 1); ! 2813: xold_readea (dest, 1, 1); ! 2814: ! 2815: /* fucking X flag */ ! 2816: ifNVCX { ! 2817: xln ("mov%s %s,%s", szmov[size], sreg (EAX), sreg (ECX)); ! 2818: xln ("mov%s %s,%s", szmov[size], sreg (EBX), sreg (EDX)); ! 2819: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (ECX)); ! 2820: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (EDX)); ! 2821: } ! 2822: xln ("add%s X,%s", szmov [size], sreg (EAX)); ! 2823: xln ("add%s %s,%s", szmov [size], sreg (EAX), sreg (EBX)); ! 2824: ! 2825: ifNVC { ! 2826: xln ("sets N"); ! 2827: xln ("seto V"); ! 2828: } ! 2829: ! 2830: ifZ { ! 2831: xln ("jz 1f"); ! 2832: xln ("movb $0,Z"); ! 2833: xout ("1:\n"); ! 2834: } ! 2835: ! 2836: ifNVCX { ! 2837: /* fucking X flag */ ! 2838: xln ("mov%s %s,%s", szmov[size], sreg (EBX), sreg (EAX)); ! 2839: xln ("shr%s $%d,%s", szmov[size], size2len[size]-1, sreg (EAX)); ! 2840: /* ecx=flgs, edx=flgo, eax=flgn */ ! 2841: xln ("xor%s %s,%s", szmov[size], sreg (EDX), sreg (EAX)); ! 2842: xln ("xor%s %s,%s", szmov[size], sreg (ECX), sreg (EDX)); ! 2843: xln ("and%s %s,%s", szmov[size], sreg (EDX), sreg (EAX)); ! 2844: xln ("xor%s %s,%s", szmov[size], sreg (EAX), sreg (ECX)); ! 2845: ifX xln ("movb %%cl,X"); ! 2846: ifNVC xln ("movb %%cl,C"); ! 2847: } ! 2848: xold_writeea (dest, size, EBX, 0); ! 2849: xold_writeea (dest, size, EBX, 1); ! 2850: xold_writeea (dest, size, EBX, 1); ! 2851: x_postea (src); ! 2852: x_postea (dest); ! 2853: } ! 2854: ! 2855: void i386_func_add (ea_t *src, ea_t *dest, int size) ! 2856: { ! 2857: x_loadval (src, -1, XQUICK_REGS | XQUICK_IMMS); ! 2858: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2859: ! 2860: xln ("add%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2861: ! 2862: ifNVC { ! 2863: xln ("sets N"); ! 2864: xln ("seto V"); ! 2865: xln ("setc C"); ! 2866: } ! 2867: ifZ xln ("setz Z"); ! 2868: ifX xln ("setc X"); ! 2869: ! 2870: xdirty_reg (dest->x86_reg); ! 2871: x_saveval (dest, size); ! 2872: x_postea (src); ! 2873: x_postea (dest); ! 2874: } ! 2875: ! 2876: void i386_func_cmpa (ea_t *src, ea_t *dest, int size) ! 2877: { ! 2878: src->op_size = size; ! 2879: dest->op_size = LONG; ! 2880: x_loadval (src, -1, (size != WORD ? 0 : XCAN_OVERWRITE)); ! 2881: x_loadval (dest, -1, 0); ! 2882: ! 2883: if (size == WORD) xln ("movswl %s,%s", xreg (src->x86_reg, WORD), xreg (src->x86_reg, LONG)); ! 2884: ! 2885: xln ("cmpl %s,%s", xreg (src->x86_reg, LONG), dest->identifier); ! 2886: ! 2887: ifNVC { ! 2888: xln ("sets N"); ! 2889: xln ("seto V"); ! 2890: xln ("setc C"); ! 2891: } ! 2892: ifZ xln ("setz Z"); ! 2893: ! 2894: x_postea (src); ! 2895: x_postea (dest); ! 2896: } ! 2897: ! 2898: void i386_func_cmp (ea_t *src, ea_t *dest, int size) ! 2899: { ! 2900: x_loadval (src, -1, XQUICK_IMMS); ! 2901: x_loadval (dest, -1, 0); ! 2902: ! 2903: xln ("cmp%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2904: ! 2905: ifNVC { ! 2906: xln ("sets N"); ! 2907: xln ("seto V"); ! 2908: xln ("setc C"); ! 2909: } ! 2910: ifZ xln ("setz Z"); ! 2911: ! 2912: x_postea (src); ! 2913: x_postea (dest); ! 2914: } ! 2915: ! 2916: void i386_func_sub (ea_t *src, ea_t *dest, int size) ! 2917: { ! 2918: x_loadval (src, -1, XQUICK_REGS | XQUICK_IMMS); ! 2919: x_loadval (dest, -1, XQUICK_WRITEBACK); ! 2920: ! 2921: xln ("sub%s %s,%s", szmov [size], src->identifier, dest->identifier); ! 2922: ! 2923: ifNVC { ! 2924: xln ("sets N"); ! 2925: xln ("seto V"); ! 2926: xln ("setc C"); ! 2927: } ! 2928: ifZ xln ("setz Z"); ! 2929: ifX xln ("setc X"); ! 2930: ! 2931: xdirty_reg (dest->x86_reg); ! 2932: x_saveval (dest, size); ! 2933: x_postea (src); ! 2934: x_postea (dest); ! 2935: } ! 2936: ! 2937: void i386_func_adda (ea_t *src, ea_t *dest, int size) ! 2938: { ! 2939: src->op_size = size; ! 2940: dest->op_size = LONG; ! 2941: x_loadval (src, -1, (size != WORD ? 0 : XCAN_OVERWRITE)); ! 2942: x_loadval (dest, -1, 0); ! 2943: ! 2944: if (size == WORD) xln ("movswl %s,%s", xreg (src->x86_reg, WORD), xreg (src->x86_reg, LONG)); ! 2945: ! 2946: xln ("addl %s,%s", xreg (src->x86_reg, LONG), dest->identifier); ! 2947: ! 2948: xdirty_reg (dest->x86_reg); ! 2949: x_saveval (dest, LONG); ! 2950: x_postea (src); ! 2951: x_postea (dest); ! 2952: } ! 2953: ! 2954: void i386_func_suba (ea_t *src, ea_t *dest, int size) ! 2955: { ! 2956: src->op_size = size; ! 2957: dest->op_size = LONG; ! 2958: x_loadval (src, -1, (size != WORD ? 0 : XCAN_OVERWRITE)); ! 2959: x_loadval (dest, -1, 0); ! 2960: ! 2961: if (size == WORD) xln ("movswl %s,%s", xreg (src->x86_reg, WORD), xreg (src->x86_reg, LONG)); ! 2962: ! 2963: xln ("subl %s,%s", xreg (src->x86_reg, LONG), dest->identifier); ! 2964: ! 2965: xdirty_reg (dest->x86_reg); ! 2966: x_saveval (dest, LONG); ! 2967: x_postea (src); ! 2968: x_postea (dest); ! 2969: } ! 2970: ! 2971: void i386_func_swap (int reg) ! 2972: { ! 2973: struct ea_t ea; ! 2974: ! 2975: ea.mode = 0; ! 2976: ea.reg = reg; ! 2977: ea.op_size = LONG; ! 2978: ea.x86_reg = -1; ! 2979: ea.x86_reg_writeback = -1; ! 2980: ! 2981: ifZNVC { ! 2982: x_loadval (&ea, -1, 0); ! 2983: ifNVC xln ("movb $0,V"); ! 2984: xln ("rorl $16,%s", ea.identifier); ! 2985: ifNVC xln ("movb $0,C"); ! 2986: ifZNVC xln ("testl %s,%s", ea.identifier, ea.identifier); ! 2987: ifNVC xln ("sets N"); ! 2988: ifZ xln ("setz Z"); ! 2989: } else { ! 2990: x_loadval (&ea, -1, 0); ! 2991: xln ("rorl $16,%s", ea.identifier); ! 2992: } ! 2993: xdirty_reg (ea.x86_reg); ! 2994: x_saveval (&ea, LONG); ! 2995: x_postea (&ea); ! 2996: } ! 2997: ! 2998: void i386_func_jsr (ea_t *dest) ! 2999: { ! 3000: char buf[256]; ! 3001: xflush_all (); ! 3002: snprintf (buf, sizeof (buf), "%x", cur_bitpos); ! 3003: add_label (buf, C_ADDR, cur_bitpos - BASE); ! 3004: add_fixup (0, C_ADDR, buf); ! 3005: ! 3006: /* XXX this is a bit inefficient, since the label is a ! 3007: * constant and could be bswapped at compile-time ! 3008: * -- but the scheduling makes this irrelevant */ ! 3009: xln ("movl %d(%%ebp),%%ebx", regpos (15)); ! 3010: xln ("movl $__D%x,%%eax", cur_bitpos); ! 3011: xln ("subl $4,%%ebx"); ! 3012: xln ("bswap %%eax"); ! 3013: xln ("movl %%ebx,%d(%%ebp)", regpos (15)); ! 3014: xln ("movl %%eax,(%%ebp,%%ebx)"); ! 3015: ! 3016: i386_jump (dest); ! 3017: } ! 3018: ! 3019: void i386_func_bcc (ea_t *dest, int cond) ! 3020: { ! 3021: xflush_all (); ! 3022: if (cond == 0) { ! 3023: i386_jump (dest); ! 3024: } else { ! 3025: x_cond_begin (cond); ! 3026: i386_jump_e (dest); ! 3027: x_cond_end (cond); ! 3028: } ! 3029: } ! 3030: ! 3031: /* XXX note: this does not call i386_jump and therefore does not ! 3032: * check for pending exceptions. an infinite DBcc loop will not ! 3033: * allow exceptions to occur. ! 3034: * does it matter? */ ! 3035: void i386_func_dbcc (const char *label, int cond, int reg) ! 3036: { ! 3037: xflush_all (); ! 3038: if (cond == 1) { ! 3039: xln ("decw %d(%%ebp)", regpos (reg)); ! 3040: xln ("cmpw $-1,%d(%%ebp)", regpos (reg)); ! 3041: xln ("jne __N%s", label); ! 3042: } else { ! 3043: /* relies on naming of x_cond_begin labels */ ! 3044: x_cond_begin (cond); ! 3045: xln ("jmp 10f"); ! 3046: x_cond_end (); ! 3047: xln ("decw %d(%%ebp)", regpos (reg)); ! 3048: xln ("cmpw $-1,%d(%%ebp)", regpos (reg)); ! 3049: xln ("jne __N%s", label); ! 3050: xout ("10:\n"); ! 3051: } ! 3052: } ! 3053: ! 3054: void i386_func_clr (ea_t *dest) ! 3055: { ! 3056: xflush_all (); ! 3057: xln ("xorl %%eax,%%eax"); ! 3058: ifZ xln ("movb $1,Z"); ! 3059: ifNVC xln ("movb %%al,N"); ! 3060: ifNVC xln ("movb %%al,V"); ! 3061: ifNVC xln ("movb %%al,C"); ! 3062: ! 3063: xold_writeea (dest, dest->op_size, EAX, 0); ! 3064: xold_writeea (dest, dest->op_size, EAX, 1); ! 3065: xold_writeea (dest, dest->op_size, EAX, 1); ! 3066: x_postea (dest); ! 3067: } ! 3068: ! 3069: void i386_func_exg (int reg1, int reg2) ! 3070: { ! 3071: xflush_all (); ! 3072: xln ("movl %d(%%ebp),%%eax", regpos (reg1)); ! 3073: xln ("movl %d(%%ebp),%%ebx", regpos (reg2)); ! 3074: xln ("movl %%eax,%d(%%ebp)", regpos (reg2)); ! 3075: xln ("movl %%ebx,%d(%%ebp)", regpos (reg1)); ! 3076: } ! 3077: ! 3078: void i386_func_ext (int reg, int size) ! 3079: { ! 3080: int x86reg = xload_reg (reg, size-1, -1); ! 3081: ! 3082: if (size == WORD) { ! 3083: xln ("movsbw %s,%s", xreg (x86reg, BYTE), xreg (x86reg, WORD)); ! 3084: } else { ! 3085: xln ("movswl %s,%s", xreg (x86reg, WORD), xreg (x86reg, LONG)); ! 3086: } ! 3087: ! 3088: ifNVC xln ("movb $0,V"); ! 3089: ifNVC xln ("movb $0,C"); ! 3090: ifZNVC xln ("test%s %s,%s", szmov[size], xreg (x86reg,size), xreg (x86reg,size)); ! 3091: ifZ xln ("setz Z"); ! 3092: ifNVC xln ("sets N"); ! 3093: xdirty_reg (x86reg); ! 3094: xreg_unlock (x86reg); ! 3095: } ! 3096: ! 3097: void i386_func_rte () ! 3098: { ! 3099: xflush_all (); ! 3100: xln ("movb bX,%%bh"); ! 3101: xln ("movb bN,%%bl"); ! 3102: xln ("movb bZ,%%ch"); ! 3103: xln ("movb bV,%%cl"); ! 3104: xln ("movb bC,%%dh"); ! 3105: xln ("movb %%bh,X"); ! 3106: xln ("movb %%bl,N"); ! 3107: xln ("movb %%ch,Z"); ! 3108: xln ("movb %%cl,V"); ! 3109: xln ("movb %%dh,C"); ! 3110: xln ("movl rdest,%%eax"); ! 3111: xln ("movl $0,rdest"); ! 3112: //xln ("jmp jumptable"); ! 3113: xln ("jmp *jtab(,%%eax,2)"); ! 3114: } ! 3115: ! 3116: void i386_func_rts () ! 3117: { ! 3118: xflush_all (); ! 3119: xln ("movl %d(%%ebp),%%ebx", regpos (15)); ! 3120: xln ("movl (%%ebx,%%ebp),%%eax"); ! 3121: xln ("addl $4,%%ebx"); ! 3122: xln ("bswap %%eax"); ! 3123: xln ("movl %%ebx,%d(%%ebp)", regpos (15)); ! 3124: //xln ("jmp jumptable"); ! 3125: xln ("jmp *jtab(,%%eax,2)"); ! 3126: } ! 3127: ! 3128: void i386_func_illegal () ! 3129: { ! 3130: xflush_all (); ! 3131: xln ("pushl line_no"); ! 3132: xln ("pushl $illegal_fmt"); ! 3133: xln ("call printf"); ! 3134: xln ("addl $8,%%esp"); ! 3135: xln ("call abort"); ! 3136: } ! 3137: ! 3138: void i386_func_hcall (int val) ! 3139: { ! 3140: xflush_all (); ! 3141: xln ("call *hcalls+%d", val*4); ! 3142: } ! 3143: ! 3144: void i386_func_link (int reg, int val) ! 3145: { ! 3146: xflush_all (); ! 3147: xln ("movl %d(%%ebp),%%ebx", regpos (15)); ! 3148: xln ("subl $4,%%ebx"); ! 3149: ! 3150: xln ("movl %d(%%ebp),%%eax", regpos (reg)); ! 3151: xln ("bswap %%eax"); ! 3152: ! 3153: xln ("movl %%eax,(%%ebp,%%ebx)"); ! 3154: xln ("addl $%d,%d(%%ebp)", val-4, regpos (15)); ! 3155: xln ("movl %%ebx,%d(%%ebp)", regpos (reg)); ! 3156: } ! 3157: ! 3158: void i386_func_unlk (int reg) ! 3159: { ! 3160: xflush_all (); ! 3161: xln ("movl %d(%%ebp),%%eax", regpos (reg)); ! 3162: xln ("movl (%%ebp,%%eax),%%ebx"); ! 3163: xln ("addl $4,%%eax"); ! 3164: xln ("bswap %%ebx"); ! 3165: xln ("movl %%ebx,%d(%%ebp)", regpos (reg)); ! 3166: xln ("movl %%eax,%d(%%ebp)", regpos (15)); ! 3167: } ! 3168: ! 3169: void i386_func_move (ea_t *src, ea_t *dest, int size) ! 3170: { ! 3171: x_loadval (src, -1, XQUICK_IMMS); ! 3172: ! 3173: ifNVC xln ("movb $0,V"); ! 3174: ifNVC xln ("movb $0,C"); ! 3175: ! 3176: if (is_immediate (src)) { ! 3177: ifZ xln ("movb $%d,Z", src->imm.val == 0); ! 3178: ifNVC xln ("movb $%d,N", src->imm.val < 0); ! 3179: } else { ! 3180: ifZNVC xln ("test%s %s,%s", szmov [size], src->identifier, src->identifier); ! 3181: ifZ xln ("setz Z"); ! 3182: ifNVC xln ("sets N"); ! 3183: } ! 3184: ! 3185: if (is_reg (dest)) { ! 3186: dest->x86_reg = xload_reg2 (dest->reg, size, -1, XLOADREG_FOR_OVERWRITE, szfull); ! 3187: } else { ! 3188: dest->x86_reg = xalloc_reg (size, -1); ! 3189: } ! 3190: xln ("mov%s %s,%s", szmov[size], src->identifier, ! 3191: xreg (dest->x86_reg, size)); ! 3192: xdirty_reg (dest->x86_reg); ! 3193: ! 3194: x_saveval (dest, size); ! 3195: x_postea (src); ! 3196: x_postea (dest); ! 3197: } ! 3198: ! 3199: void i386_func_movea (ea_t *src, int reg_dest) ! 3200: { ! 3201: #if 0 ! 3202: xflush_all (); ! 3203: xold_readea (src, 0, 0); ! 3204: xold_readea (src, 0, 1); ! 3205: xold_readea (src, 0, 1); ! 3206: if (src->op_size == WORD) xln ("movswl %%ax,%%eax"); ! 3207: xln ("movl %%eax,%d(%%ebp)", regpos (reg_dest)); ! 3208: x_postea (src); ! 3209: #endif ! 3210: int reg; ! 3211: struct ea_t dest; ! 3212: ! 3213: dest.mode = 1; ! 3214: dest.reg = reg_dest; ! 3215: dest.op_size = LONG; ! 3216: dest.x86_reg = -1; ! 3217: dest.x86_reg_writeback = -1; ! 3218: ! 3219: x_loadval (src, -1, 0); ! 3220: ! 3221: reg = xalloc_reg (LONG, -1); ! 3222: ! 3223: if (src->op_size == WORD) ! 3224: xln ("movswl %s,%s", xreg (src->x86_reg, WORD), xreg (reg, LONG)); ! 3225: else ! 3226: xln ("movl %s,%s", xreg (src->x86_reg, LONG), xreg (reg, LONG)); ! 3227: ! 3228: x_ea_set_val_2_reg (&dest, LONG, reg); ! 3229: ! 3230: xreg_unlock (reg); ! 3231: xdirty_reg (reg); ! 3232: ! 3233: x_saveval (&dest, LONG); ! 3234: x_postea (src); ! 3235: x_postea (&dest); ! 3236: } ! 3237: ! 3238: void i386_func_tst (ea_t *ea) ! 3239: { ! 3240: x_loadval (ea, -1, 0); ! 3241: ifNVC xln ("movb $0,C"); ! 3242: ifNVC xln ("movb $0,V"); ! 3243: xln ("test%s %s,%s", szmov[ea->op_size], ea->identifier, ea->identifier); ! 3244: ifZ xln ("setz Z"); ! 3245: ifNVC xln ("sets N"); ! 3246: x_postea (ea); ! 3247: } ! 3248: ! 3249: void i386_func_pea (ea_t *ea) ! 3250: { ! 3251: int a7; ! 3252: ! 3253: x_loadea (ea); ! 3254: a7 = xload_reg (15, LONG, -1); ! 3255: ! 3256: xln ("subl $4,%s", xreg (a7, LONG)); ! 3257: xln ("bswap %s", ea->identifier); ! 3258: xln ("movl %s,(%%ebp,%s)", ea->identifier, xreg (a7, LONG)); ! 3259: ! 3260: xdirty_reg (a7); ! 3261: xreg_unlock (a7); ! 3262: x_postea (ea); ! 3263: } ! 3264: ! 3265: void i386_func_lea (ea_t *ea, int reg) ! 3266: { ! 3267: struct ea_t dest; ! 3268: ! 3269: dest.mode = 1; ! 3270: dest.reg = reg; ! 3271: dest.op_size = LONG; ! 3272: dest.x86_reg = -1; ! 3273: dest.x86_reg_writeback = -1; ! 3274: ! 3275: x_loadea (ea); ! 3276: ! 3277: x_ea_set_val_2_reg (&dest, LONG, ea->x86_reg); ! 3278: x_saveval (&dest, LONG); ! 3279: x_postea (ea); ! 3280: x_postea (&dest); ! 3281: } ! 3282: ! 3283: void i386_func_scc (ea_t *dest, int cond) ! 3284: { ! 3285: xflush_all (); ! 3286: x_cond_begin (cond); ! 3287: ! 3288: xln ("movb $0xff,%%al"); ! 3289: xold_writeea (dest, BYTE, EAX, 0); ! 3290: xold_writeea (dest, BYTE, EAX, 1); ! 3291: xold_writeea (dest, BYTE, EAX, 1); ! 3292: x_postea (dest); ! 3293: xln ("jmp 10f"); ! 3294: ! 3295: x_cond_end (); ! 3296: ! 3297: xln ("xorb %%al,%%al"); ! 3298: xold_writeea (dest, BYTE, EAX, 0); ! 3299: xold_writeea (dest, BYTE, EAX, 1); ! 3300: xold_writeea (dest, BYTE, EAX, 1); ! 3301: x_postea (dest); ! 3302: ! 3303: xout ("10:\n"); ! 3304: } ! 3305: ! 3306: static void output_op (op_t *op, op_t *next) ! 3307: { ! 3308: xregalloc_age (); ! 3309: ! 3310: op->src.x86_reg = -1; ! 3311: op->src.x86_reg_writeback = -1; ! 3312: op->dest.x86_reg = -1; ! 3313: op->dest.x86_reg_writeback = -1; ! 3314: ! 3315: switch (op->optype) { ! 3316: case OP_MULS: i386_func_muls (&op->src, &op->dest); break; ! 3317: case OP_MULU: i386_func_mulu (&op->src, &op->dest); break; ! 3318: case OP_ADDA: i386_func_adda (&op->src, &op->dest, op->size); break; ! 3319: case OP_SUBA: i386_func_suba (&op->src, &op->dest, op->size); break; ! 3320: case OP_ADD: i386_func_add (&op->src, &op->dest, op->size); break; ! 3321: case OP_SUB: i386_func_sub (&op->src, &op->dest, op->size); break; ! 3322: case OP_NOT: i386_func_not (&op->src, op->size); break; ! 3323: case OP_NEGX: i386_func_negx (&op->src, op->size); break; ! 3324: case OP_NEG: i386_func_neg (&op->src, op->size); break; ! 3325: case OP_DIVS: i386_func_divs (&op->src, op->dest.reg); break; ! 3326: case OP_DIVU: i386_func_divu (&op->src, op->dest.reg); break; ! 3327: case OP_ADDX: i386_func_addx (&op->src, &op->dest, op->size); break; ! 3328: case OP_SUBX: i386_func_subx (&op->src, &op->dest, op->size); break; ! 3329: case OP_BCHG: i386_func_bchg (&op->src, &op->dest, op->size); break; ! 3330: case OP_BCLR: i386_func_bclr (&op->src, &op->dest, op->size); break; ! 3331: case OP_BSET: i386_func_bset (&op->src, &op->dest, op->size); break; ! 3332: case OP_BTST: i386_func_btst (&op->src, &op->dest, op->size); break; ! 3333: case OP_ASL: i386_func_asl (&op->src, &op->dest, op->size); break; ! 3334: case OP_ASR: i386_func_asr (&op->src, &op->dest, op->size); break; ! 3335: case OP_LSL: i386_func_lsl (&op->src, &op->dest, op->size); break; ! 3336: case OP_LSR: i386_func_lsr (&op->src, &op->dest, op->size); break; ! 3337: case OP_ROL: i386_func_rol (&op->src, &op->dest, op->size); break; ! 3338: case OP_ROR: i386_func_ror (&op->src, &op->dest, op->size); break; ! 3339: case OP_ROXL: i386_func_roxl (&op->src, &op->dest, op->size); break; ! 3340: case OP_ROXR: i386_func_roxr (&op->src, &op->dest, op->size); break; ! 3341: case OP_OR: i386_func_logop (&op->src, &op->dest, op->size, '|'); break; ! 3342: case OP_AND: i386_func_logop (&op->src, &op->dest, op->size, '&'); break; ! 3343: case OP_XOR: i386_func_logop (&op->src, &op->dest, op->size, '^'); break; ! 3344: case OP_SWAP: i386_func_swap (op->src.reg); break; ! 3345: case OP_JSR: i386_func_jsr (&op->src); break; ! 3346: case OP_BCC: i386_func_bcc (&op->src, op->opcode.Bcc.cond); break; ! 3347: case OP_DBCC: i386_func_dbcc (op->dest.imm.label, op->opcode.Bcc.cond, op->src.reg); break; ! 3348: case OP_CLR: i386_func_clr (&op->src); break; ! 3349: case OP_CMP: i386_func_cmp (&op->src, &op->dest, op->size); break; ! 3350: case OP_CMPA: i386_func_cmpa (&op->src, &op->dest, op->size); break; ! 3351: case OP_EXG: i386_func_exg (op->src.reg, op->dest.reg); break; ! 3352: case OP_EXT: i386_func_ext (op->src.reg, op->size); break; ! 3353: case OP_MOVEM: i386_func_movem (&op->src, op->opcode.movem.sz, op->opcode.movem.dr, op->dest.reg); break; ! 3354: case OP_RTE: i386_func_rte (); break; ! 3355: case OP_RTS: i386_func_rts (); break; ! 3356: case OP_ILLEGAL: i386_func_illegal (); break; ! 3357: case OP_HCALL: i386_func_hcall (op->src.imm.val); break; ! 3358: case OP_LINK: i386_func_link (op->src.reg, op->dest.imm.val); break; ! 3359: case OP_UNLK: i386_func_unlk (op->src.reg); break; ! 3360: case OP_MOVE: i386_func_move (&op->src, &op->dest, op->size); break; ! 3361: case OP_MOVEA: i386_func_movea (&op->src, op->dest.reg); break; ! 3362: case OP_TST: i386_func_tst (&op->src); break; ! 3363: case OP_PEA: i386_func_pea (&op->src); break; ! 3364: case OP_LEA: i386_func_lea (&op->src, op->dest.reg); break; ! 3365: case OP_JMP: i386_jump (&op->src); break; ! 3366: case OP_SCC: i386_func_scc (&op->src, op->opcode.DBcc.cond); break; ! 3367: ! 3368: default: ! 3369: printf ("type %d\n", op->optype); ! 3370: assert (0); ! 3371: } ! 3372: ! 3373: /* int i; ! 3374: int fucked = 0; ! 3375: for (i=0; i<X86REG_MAX; i++) { ! 3376: printf ("l%d X86-reg %d: contained 68k reg %d, age %d, dirty %d, locked %d\n", ! 3377: line_no, ! 3378: i, i386_regalloc[i].m68k_reg, ! 3379: i386_regalloc[i].age, ! 3380: i386_regalloc[i].dirty, ! 3381: i386_regalloc[i].locked); ! 3382: if (i386_regalloc[i].locked) fucked = 1; ! 3383: } ! 3384: printf ("\n"); ! 3385: assert (fucked == 0);*/ ! 3386: } ! 3387: ! 3388: static void do_pending () ! 3389: { ! 3390: if (pending_flush) { ! 3391: xflush_all (); ! 3392: } ! 3393: pending_flush = cur_flush; ! 3394: cur_flush = 0; ! 3395: ! 3396: #ifdef DUMP_LOADS_OF_CRAP ! 3397: /* state must be consistent to print reg contents */ ! 3398: xflush_all (); ! 3399: #endif /* DUMP_LOADS_OF_CRAP */ ! 3400: ! 3401: if (pending_labels) { ! 3402: rout (pending_labels); ! 3403: free (pending_labels); ! 3404: } ! 3405: pending_labels = cur_labels; ! 3406: cur_labels = calloc (LABBUF_LEN, 1); ! 3407: strcat (cur_labels, "\n"); ! 3408: ! 3409: if (pending.optype) output_op (&pending, NULL); ! 3410: } ! 3411: ! 3412: void i386_push_op (enum M68K_OPS type, ea_t *src, ea_t *dest, int size) ! 3413: { ! 3414: i386_push_op2 (type, src, dest, size, 0); ! 3415: } ! 3416: void i386_push_op2 (enum M68K_OPS type, ea_t *src, ea_t *dest, int size, int opcode) ! 3417: { ! 3418: op_t op; ! 3419: ! 3420: op.size = size; ! 3421: op.opcode.code = opcode; ! 3422: op.optype = type; ! 3423: if (type == OP_JSR) ! 3424: return_target = 1; ! 3425: else ! 3426: return_target = 0; ! 3427: if (src) { ! 3428: op.src = *src; ! 3429: } ! 3430: if (dest) { ! 3431: op.dest = *dest; ! 3432: } ! 3433: next_op_type = op.optype; ! 3434: ! 3435: do_pending (); ! 3436: pending = op; ! 3437: } ! 3438: void i386_push_op_basic (enum M68K_OPS type) ! 3439: { ! 3440: i386_push_op2 (type, NULL, NULL, 0, 0); ! 3441: } ! 3442:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.