Annotation of frontvm/as68k/output_i386.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.