Annotation of qemu/target-m68k/translate.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  m68k translation
                      3:  * 
                      4:  *  Copyright (c) 2005-2006 CodeSourcery
                      5:  *  Written by Paul Brook
                      6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
                     18:  * License along with this library; if not, write to the Free Software
                     19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     20:  */
                     21: #include <stdarg.h>
                     22: #include <stdlib.h>
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <inttypes.h>
                     26: 
                     27: #include "config.h"
                     28: #include "cpu.h"
                     29: #include "exec-all.h"
                     30: #include "disas.h"
                     31: #include "m68k-qreg.h"
                     32: 
                     33: static inline void qemu_assert(int cond, const char *msg)
                     34: {
                     35:     if (!cond) {
                     36:         fprintf (stderr, "badness: %s\n", msg);
                     37:         abort();
                     38:     }
                     39: }
                     40: 
                     41: /* internal defines */
                     42: typedef struct DisasContext {
                     43:     target_ulong pc;
                     44:     int is_jmp;
                     45:     int cc_op;
                     46:     uint32_t fpcr;
                     47:     struct TranslationBlock *tb;
                     48:     int singlestep_enabled;
                     49: } DisasContext;
                     50: 
                     51: #define DISAS_JUMP_NEXT 4
                     52: 
                     53: /* XXX: move that elsewhere */
                     54: /* ??? Fix exceptions.  */
                     55: static void *gen_throws_exception;
                     56: #define gen_last_qop NULL
                     57: 
                     58: static uint16_t *gen_opc_ptr;
                     59: static uint32_t *gen_opparam_ptr;
                     60: extern FILE *logfile;
                     61: extern int loglevel;
                     62: 
                     63: enum {
                     64: #define DEF(s, n, copy_size) INDEX_op_ ## s,
                     65: #include "opc.h"
                     66: #undef DEF
                     67:     NB_OPS,
                     68: };
                     69: 
                     70: #include "gen-op.h"
                     71: #include "op-hacks.h"
                     72: 
                     73: #define OS_BYTE 0
                     74: #define OS_WORD 1
                     75: #define OS_LONG 2
                     76: #define OS_SINGLE 4
                     77: #define OS_DOUBLE 5
                     78: 
                     79: #define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
                     80: #define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
                     81: #define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
                     82: 
                     83: #define M68K_INSN_CF_A    (1 << 0)
                     84: #define M68K_INSN_CF_B    (1 << 1)
                     85: #define M68K_INSN_CF_C    (1 << 2)
                     86: #define M68K_INSN_CF_MAC  (1 << 3)
                     87: #define M68K_INSN_CF_EMAC (1 << 4)
                     88: #define M68K_INSN_CF_FPU  (1 << 5)
                     89: 
                     90: struct m68k_def_t {
                     91:     const char * name;
                     92:     uint32_t insns;
                     93: };
                     94: 
                     95: static m68k_def_t m68k_cpu_defs[] = {
                     96:     {"m5206", M68K_INSN_CF_A},
                     97:     {"cfv4e", M68K_INSN_CF_A | M68K_INSN_CF_B | M68K_INSN_CF_C
                     98:             | M68K_INSN_CF_MAC | M68K_INSN_CF_EMAC | M68K_INSN_CF_FPU},
                     99:     {NULL, 0}, 
                    100: };
                    101: 
                    102: typedef void (*disas_proc)(DisasContext *, uint16_t);
                    103: 
                    104: #define DISAS_INSN(name) \
                    105:   static void disas_##name (DisasContext *s, uint16_t insn)
                    106: 
                    107: /* Generate a load from the specified address.  Narrow values are
                    108:    sign extended to full register width.  */
                    109: static inline int gen_load(int opsize, int addr, int sign)
                    110: {
                    111:     int tmp;
                    112:     switch(opsize) {
                    113:     case OS_BYTE:
                    114:         tmp = gen_new_qreg(QMODE_I32);
                    115:         if (sign)
                    116:             gen_op_ld8s32(tmp, addr);
                    117:         else
                    118:             gen_op_ld8u32(tmp, addr);
                    119:         break;
                    120:     case OS_WORD:
                    121:         tmp = gen_new_qreg(QMODE_I32);
                    122:         if (sign)
                    123:             gen_op_ld16s32(tmp, addr);
                    124:         else
                    125:             gen_op_ld16u32(tmp, addr);
                    126:         break;
                    127:     case OS_LONG:
                    128:         tmp = gen_new_qreg(QMODE_I32);
                    129:         gen_op_ld32(tmp, addr);
                    130:         break;
                    131:     case OS_SINGLE:
                    132:         tmp = gen_new_qreg(QMODE_F32);
                    133:         gen_op_ldf32(tmp, addr);
                    134:         break;
                    135:     case OS_DOUBLE:
                    136:         tmp  = gen_new_qreg(QMODE_F64);
                    137:         gen_op_ldf64(tmp, addr);
                    138:         break;
                    139:     default:
                    140:         qemu_assert(0, "bad load size");
                    141:     }
                    142:     gen_throws_exception = gen_last_qop;
                    143:     return tmp;
                    144: }
                    145: 
                    146: /* Generate a store.  */
                    147: static inline void gen_store(int opsize, int addr, int val)
                    148: {
                    149:     switch(opsize) {
                    150:     case OS_BYTE:
                    151:         gen_op_st8(addr, val);
                    152:         break;
                    153:     case OS_WORD:
                    154:         gen_op_st16(addr, val);
                    155:         break;
                    156:     case OS_LONG:
                    157:         gen_op_st32(addr, val);
                    158:         break;
                    159:     case OS_SINGLE:
                    160:         gen_op_stf32(addr, val);
                    161:         break;
                    162:     case OS_DOUBLE:
                    163:         gen_op_stf64(addr, val);
                    164:         break;
                    165:     default:
                    166:         qemu_assert(0, "bad store size");
                    167:     }
                    168:     gen_throws_exception = gen_last_qop;
                    169: }
                    170: 
                    171: /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
                    172:    otherwise generate a store.  */
                    173: static int gen_ldst(int opsize, int addr, int val)
                    174: {
                    175:     if (val > 0) {
                    176:         gen_store(opsize, addr, val);
                    177:         return 0;
                    178:     } else {
                    179:         return gen_load(opsize, addr, val != 0);
                    180:     }
                    181: }
                    182: 
                    183: /* Handle a base + index + displacement effective addresss.  A base of
                    184:    -1 means pc-relative.  */
                    185: static int gen_lea_indexed(DisasContext *s, int opsize, int base)
                    186: {
                    187:     int scale;
                    188:     uint32_t offset;
                    189:     uint16_t ext;
                    190:     int add;
                    191:     int tmp;
                    192: 
                    193:     offset = s->pc;
                    194:     ext = lduw(s->pc);
                    195:     s->pc += 2;
                    196:     tmp = ((ext >> 12) & 7) + ((ext & 0x8000) ? QREG_A0 : QREG_D0);
                    197:     /* ??? Check W/L bit.  */
                    198:     scale = (ext >> 9) & 3;
                    199:     if (scale == 0) {
                    200:         add = tmp;
                    201:     } else {
                    202:         add = gen_new_qreg(QMODE_I32);
                    203:         gen_op_shl32(add, tmp, gen_im32(scale));
                    204:     }
                    205:     tmp = gen_new_qreg(QMODE_I32);
                    206:     if (base != -1) {
                    207:         gen_op_add32(tmp, base, gen_im32((int8_t)ext));
                    208:         gen_op_add32(tmp, tmp, add);
                    209:     } else {
                    210:         gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
                    211:     }
                    212:     return tmp;
                    213: }
                    214: 
                    215: /* Read a 32-bit immediate constant.  */
                    216: static inline uint32_t read_im32(DisasContext *s)
                    217: {
                    218:     uint32_t im;
                    219:     im = ((uint32_t)lduw(s->pc)) << 16;
                    220:     s->pc += 2;
                    221:     im |= lduw(s->pc);
                    222:     s->pc += 2;
                    223:     return im;
                    224: }
                    225: 
                    226: 
                    227: /* Update the CPU env CC_OP state.  */
                    228: static inline void gen_flush_cc_op(DisasContext *s)
                    229: {
                    230:     if (s->cc_op != CC_OP_DYNAMIC)
                    231:         gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
                    232: }
                    233: 
                    234: /* Evaluate all the CC flags.  */
                    235: static inline void gen_flush_flags(DisasContext *s)
                    236: {
                    237:     if (s->cc_op == CC_OP_FLAGS)
                    238:         return;
                    239:     gen_op_flush_flags(s->cc_op);
                    240:     s->cc_op = CC_OP_FLAGS;
                    241: }
                    242: 
                    243: static inline int opsize_bytes(int opsize)
                    244: {
                    245:     switch (opsize) {
                    246:     case OS_BYTE: return 1;
                    247:     case OS_WORD: return 2;
                    248:     case OS_LONG: return 4;
                    249:     case OS_SINGLE: return 4;
                    250:     case OS_DOUBLE: return 8;
                    251:     default:
                    252:         qemu_assert(0, "bad operand size");
                    253:     }
                    254: }
                    255: 
                    256: /* Assign value to a register.  If the width is less than the register width
                    257:    only the low part of the register is set.  */
                    258: static void gen_partset_reg(int opsize, int reg, int val)
                    259: {
                    260:     int tmp;
                    261:     switch (opsize) {
                    262:     case OS_BYTE:
                    263:         gen_op_and32(reg, reg, gen_im32(0xffffff00));
                    264:         tmp = gen_new_qreg(QMODE_I32);
                    265:         gen_op_and32(tmp, val, gen_im32(0xff));
                    266:         gen_op_or32(reg, reg, tmp);
                    267:         break;
                    268:     case OS_WORD:
                    269:         gen_op_and32(reg, reg, gen_im32(0xffff0000));
                    270:         tmp = gen_new_qreg(QMODE_I32);
                    271:         gen_op_and32(tmp, val, gen_im32(0xffff));
                    272:         gen_op_or32(reg, reg, tmp);
                    273:         break;
                    274:     case OS_LONG:
                    275:         gen_op_mov32(reg, val);
                    276:         break;
                    277:     case OS_SINGLE:
                    278:         gen_op_pack_32_f32(reg, val);
                    279:         break;
                    280:     default:
                    281:         qemu_assert(0, "Bad operand size");
                    282:         break;
                    283:     }
                    284: }
                    285: 
                    286: /* Sign or zero extend a value.  */
                    287: static inline int gen_extend(int val, int opsize, int sign)
                    288: {
                    289:     int tmp;
                    290: 
                    291:     switch (opsize) {
                    292:     case OS_BYTE:
                    293:         tmp = gen_new_qreg(QMODE_I32);
                    294:         if (sign)
                    295:             gen_op_ext8s32(tmp, val);
                    296:         else
                    297:             gen_op_ext8u32(tmp, val);
                    298:         break;
                    299:     case OS_WORD:
                    300:         tmp = gen_new_qreg(QMODE_I32);
                    301:         if (sign)
                    302:             gen_op_ext16s32(tmp, val);
                    303:         else
                    304:             gen_op_ext16u32(tmp, val);
                    305:         break;
                    306:     case OS_LONG:
                    307:         tmp = val;
                    308:         break;
                    309:     case OS_SINGLE:
                    310:         tmp = gen_new_qreg(QMODE_F32);
                    311:         gen_op_pack_f32_32(tmp, val);
                    312:         break;
                    313:     default:
                    314:         qemu_assert(0, "Bad operand size");
                    315:     }
                    316:     return tmp;
                    317: }
                    318: 
                    319: /* Generate code for an "effective address".  Does not adjust the base
                    320:    register for autoincrememnt addressing modes.  */
                    321: static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
                    322: {
                    323:     int reg;
                    324:     int tmp;
                    325:     uint16_t ext;
                    326:     uint32_t offset;
                    327: 
                    328:     reg = insn & 7;
                    329:     switch ((insn >> 3) & 7) {
                    330:     case 0: /* Data register direct.  */
                    331:     case 1: /* Address register direct.  */
                    332:         /* ??? generate bad addressing mode fault.  */
                    333:         qemu_assert(0, "invalid addressing mode");
                    334:     case 2: /* Indirect register */
                    335:     case 3: /* Indirect postincrement.  */
                    336:         reg += QREG_A0;
                    337:         return reg;
                    338:     case 4: /* Indirect predecrememnt.  */
                    339:         reg += QREG_A0;
                    340:         tmp = gen_new_qreg(QMODE_I32);
                    341:         gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
                    342:         return tmp;
                    343:     case 5: /* Indirect displacement.  */
                    344:         reg += QREG_A0;
                    345:         tmp = gen_new_qreg(QMODE_I32);
                    346:         ext = lduw(s->pc);
                    347:         s->pc += 2;
                    348:         gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
                    349:         return tmp;
                    350:     case 6: /* Indirect index + displacement.  */
                    351:         reg += QREG_A0;
                    352:         return gen_lea_indexed(s, opsize, reg);
                    353:     case 7: /* Other */
                    354:         switch (reg) {
                    355:         case 0: /* Absolute short.  */
                    356:             offset = ldsw(s->pc);
                    357:             s->pc += 2;
                    358:             return gen_im32(offset);
                    359:         case 1: /* Absolute long.  */
                    360:             offset = read_im32(s);
                    361:             return gen_im32(offset);
                    362:         case 2: /* pc displacement  */
                    363:             tmp = gen_new_qreg(QMODE_I32);
                    364:             offset = s->pc;
                    365:             offset += ldsw(s->pc);
                    366:             s->pc += 2;
                    367:             return gen_im32(offset);
                    368:         case 3: /* pc index+displacement.  */
                    369:             return gen_lea_indexed(s, opsize, -1);
                    370:         case 4: /* Immediate.  */
                    371:         default:
                    372:             /* ??? generate bad addressing mode fault.  */
                    373:             qemu_assert(0, "invalid addressing mode");
                    374:         }
                    375:     }
                    376:     /* Should never happen.  */
                    377:     return -1;
                    378: }
                    379: 
                    380: /* Helper function for gen_ea. Reuse the computed address between the
                    381:    for read/write operands.  */
                    382: static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
                    383:                               int val, int *addrp)
                    384: {
                    385:     int tmp;
                    386: 
                    387:     if (addrp && val > 0) {
                    388:         tmp = *addrp;
                    389:     } else {
                    390:         tmp = gen_lea(s, insn, opsize);
                    391:         if (addrp)
                    392:             *addrp = tmp;
                    393:     }
                    394:     return gen_ldst(opsize, tmp, val);
                    395: }
                    396: 
                    397: /* Generate code to load/store a value ito/from an EA.  If VAL > 0 this is
                    398:    a write otherwise it is a read (0 == sign extend, -1 == zero extend).
                    399:    ADDRP is non-null for readwrite operands.  */
                    400: static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
                    401:                   int *addrp)
                    402: {
                    403:     int reg;
                    404:     int result;
                    405:     uint32_t offset;
                    406: 
                    407:     reg = insn & 7;
                    408:     switch ((insn >> 3) & 7) {
                    409:     case 0: /* Data register direct.  */
                    410:         reg += QREG_D0;
                    411:         if (val > 0) {
                    412:             gen_partset_reg(opsize, reg, val);
                    413:             return 0;
                    414:         } else {
                    415:             return gen_extend(reg, opsize, val);
                    416:         }
                    417:     case 1: /* Address register direct.  */
                    418:         reg += QREG_A0;
                    419:         if (val > 0) {
                    420:             gen_op_mov32(reg, val);
                    421:             return 0;
                    422:         } else {
                    423:             return gen_extend(reg, opsize, val);
                    424:         }
                    425:     case 2: /* Indirect register */
                    426:         reg += QREG_A0;
                    427:         return gen_ldst(opsize, reg, val);
                    428:     case 3: /* Indirect postincrement.  */
                    429:         reg += QREG_A0;
                    430:         result = gen_ldst(opsize, reg, val);
                    431:         /* ??? This is not exception safe.  The instruction may still
                    432:            fault after this point.  */
                    433:         if (val > 0 || !addrp)
                    434:             gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
                    435:         return result;
                    436:     case 4: /* Indirect predecrememnt.  */
                    437:         {
                    438:             int tmp;
                    439:             if (addrp && val > 0) {
                    440:                 tmp = *addrp;
                    441:             } else {
                    442:                 tmp = gen_lea(s, insn, opsize);
                    443:                 if (addrp)
                    444:                     *addrp = tmp;
                    445:             }
                    446:             result = gen_ldst(opsize, tmp, val);
                    447:             /* ??? This is not exception safe.  The instruction may still
                    448:                fault after this point.  */
                    449:             if (val > 0 || !addrp) {
                    450:                 reg += QREG_A0;
                    451:                 gen_op_mov32(reg, tmp);
                    452:             }
                    453:         }
                    454:         return result;
                    455:     case 5: /* Indirect displacement.  */
                    456:     case 6: /* Indirect index + displacement.  */
                    457:         return gen_ea_once(s, insn, opsize, val, addrp);
                    458:     case 7: /* Other */
                    459:         switch (reg) {
                    460:         case 0: /* Absolute short.  */
                    461:         case 1: /* Absolute long.  */
                    462:         case 2: /* pc displacement  */
                    463:         case 3: /* pc index+displacement.  */
                    464:             return gen_ea_once(s, insn, opsize, val, addrp);
                    465:         case 4: /* Immediate.  */
                    466:             /* Sign extend values for consistency.  */
                    467:             switch (opsize) {
                    468:             case OS_BYTE:
                    469:                 if (val)
                    470:                     offset = ldsb(s->pc + 1);
                    471:                 else
                    472:                     offset = ldub(s->pc + 1);
                    473:                 s->pc += 2;
                    474:                 break;
                    475:             case OS_WORD:
                    476:                 if (val)
                    477:                     offset = ldsw(s->pc);
                    478:                 else
                    479:                     offset = lduw(s->pc);
                    480:                 s->pc += 2;
                    481:                 break;
                    482:             case OS_LONG:
                    483:                 offset = read_im32(s);
                    484:                 break;
                    485:             default:
                    486:                 qemu_assert(0, "Bad immediate operand");
                    487:             }
                    488:             return gen_im32(offset);
                    489:         default:
                    490:             qemu_assert(0, "invalid addressing mode");
                    491:         }
                    492:     }
                    493:     /* Should never happen.  */
                    494:     return -1;
                    495: }
                    496: 
                    497: static void gen_logic_cc(DisasContext *s, int val)
                    498: {
                    499:     gen_op_logic_cc(val);
                    500:     s->cc_op = CC_OP_LOGIC;
                    501: }
                    502: 
                    503: static void gen_jmpcc(DisasContext *s, int cond, int l1)
                    504: {
                    505:     int tmp;
                    506: 
                    507:     gen_flush_flags(s);
                    508:     switch (cond) {
                    509:     case 0: /* T */
                    510:         gen_op_jmp(l1);
                    511:         break;
                    512:     case 1: /* F */
                    513:         break;
                    514:     case 2: /* HI (!C && !Z) */
                    515:         tmp = gen_new_qreg(QMODE_I32);
                    516:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
                    517:         gen_op_jmp_z32(tmp, l1);
                    518:         break;
                    519:     case 3: /* LS (C || Z) */
                    520:         tmp = gen_new_qreg(QMODE_I32);
                    521:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
                    522:         gen_op_jmp_nz32(tmp, l1);
                    523:         break;
                    524:     case 4: /* CC (!C) */
                    525:         tmp = gen_new_qreg(QMODE_I32);
                    526:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
                    527:         gen_op_jmp_z32(tmp, l1);
                    528:         break;
                    529:     case 5: /* CS (C) */
                    530:         tmp = gen_new_qreg(QMODE_I32);
                    531:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
                    532:         gen_op_jmp_nz32(tmp, l1);
                    533:         break;
                    534:     case 6: /* NE (!Z) */
                    535:         tmp = gen_new_qreg(QMODE_I32);
                    536:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
                    537:         gen_op_jmp_z32(tmp, l1);
                    538:         break;
                    539:     case 7: /* EQ (Z) */
                    540:         tmp = gen_new_qreg(QMODE_I32);
                    541:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
                    542:         gen_op_jmp_nz32(tmp, l1);
                    543:         break;
                    544:     case 8: /* VC (!V) */
                    545:         tmp = gen_new_qreg(QMODE_I32);
                    546:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
                    547:         gen_op_jmp_z32(tmp, l1);
                    548:         break;
                    549:     case 9: /* VS (V) */
                    550:         tmp = gen_new_qreg(QMODE_I32);
                    551:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
                    552:         gen_op_jmp_nz32(tmp, l1);
                    553:         break;
                    554:     case 10: /* PL (!N) */
                    555:         tmp = gen_new_qreg(QMODE_I32);
                    556:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
                    557:         gen_op_jmp_z32(tmp, l1);
                    558:         break;
                    559:     case 11: /* MI (N) */
                    560:         tmp = gen_new_qreg(QMODE_I32);
                    561:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
                    562:         gen_op_jmp_nz32(tmp, l1);
                    563:         break;
                    564:     case 12: /* GE (!(N ^ V)) */
                    565:         tmp = gen_new_qreg(QMODE_I32);
                    566:         gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
                    567:         gen_op_xor32(tmp, tmp, QREG_CC_DEST);
                    568:         gen_op_and32(tmp, tmp, gen_im32(CCF_V));
                    569:         gen_op_jmp_z32(tmp, l1);
                    570:         break;
                    571:     case 13: /* LT (N ^ V) */
                    572:         tmp = gen_new_qreg(QMODE_I32);
                    573:         gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
                    574:         gen_op_xor32(tmp, tmp, QREG_CC_DEST);
                    575:         gen_op_and32(tmp, tmp, gen_im32(CCF_V));
                    576:         gen_op_jmp_nz32(tmp, l1);
                    577:         break;
                    578:     case 14: /* GT (!(Z || (N ^ V))) */
                    579:         {
                    580:             int l2;
                    581:             l2 = gen_new_label();
                    582:             tmp = gen_new_qreg(QMODE_I32);
                    583:             gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
                    584:             gen_op_jmp_nz32(tmp, l2);
                    585:             tmp = gen_new_qreg(QMODE_I32);
                    586:             gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
                    587:             gen_op_xor32(tmp, tmp, QREG_CC_DEST);
                    588:             gen_op_and32(tmp, tmp, gen_im32(CCF_V));
                    589:             gen_op_jmp_nz32(tmp, l2);
                    590:             gen_op_jmp(l1);
                    591:             gen_set_label(l2);
                    592:         }
                    593:         break;
                    594:     case 15: /* LE (Z || (N ^ V)) */
                    595:         tmp = gen_new_qreg(QMODE_I32);
                    596:         gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
                    597:         gen_op_jmp_nz32(tmp, l1);
                    598:         tmp = gen_new_qreg(QMODE_I32);
                    599:         gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
                    600:         gen_op_xor32(tmp, tmp, QREG_CC_DEST);
                    601:         gen_op_and32(tmp, tmp, gen_im32(CCF_V));
                    602:         gen_op_jmp_nz32(tmp, l1);
                    603:         break;
                    604:     default:
                    605:         /* Should ever happen.  */
                    606:         abort();
                    607:     }
                    608: }
                    609: 
                    610: DISAS_INSN(scc)
                    611: {
                    612:     int l1;
                    613:     int cond;
                    614:     int reg;
                    615: 
                    616:     l1 = gen_new_label();
                    617:     cond = (insn >> 8) & 0xf;
                    618:     reg = DREG(insn, 0);
                    619:     gen_op_and32(reg, reg, gen_im32(0xffffff00));
                    620:     gen_jmpcc(s, cond ^ 1, l1);
                    621:     gen_op_or32(reg, reg, gen_im32(0xff));
                    622:     gen_set_label(l1);
                    623: }
                    624: 
                    625: /* Generate a jump to to the address in qreg DEST.  */
                    626: static void gen_jmp(DisasContext *s, int dest)
                    627: {
                    628:     gen_flush_cc_op(s);
                    629:     gen_op_mov32(QREG_PC, dest);
                    630:     s->is_jmp = DISAS_JUMP;
                    631: }
                    632: 
                    633: static void gen_exception(DisasContext *s, uint32_t where, int nr)
                    634: {
                    635:     gen_flush_cc_op(s);
                    636:     gen_jmp(s, gen_im32(where));
                    637:     gen_op_raise_exception(nr);
                    638: }
                    639: 
                    640: /* Generate a jump to an immediate address.  */
                    641: static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
                    642: {
                    643:     TranslationBlock *tb;
                    644: 
                    645:     tb = s->tb;
                    646:     if (__builtin_expect (s->singlestep_enabled, 0)) {
                    647:         gen_exception(s, dest, EXCP_DEBUG);
                    648:     } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
                    649:                (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
                    650:         gen_op_goto_tb(0, n, (long)tb);
                    651:         gen_op_mov32(QREG_PC, gen_im32(dest));
                    652:         gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
                    653:         gen_op_exit_tb();
                    654:     } else {
                    655:         gen_jmp(s, gen_im32(dest));
                    656:         gen_op_mov32(QREG_T0, gen_im32(0));
                    657:         gen_op_exit_tb();
                    658:     }
                    659:     s->is_jmp = DISAS_TB_JUMP;
                    660: }
                    661: 
                    662: DISAS_INSN(undef_mac)
                    663: {
                    664:     gen_exception(s, s->pc - 2, EXCP_LINEA);
                    665: }
                    666: 
                    667: DISAS_INSN(undef_fpu)
                    668: {
                    669:     gen_exception(s, s->pc - 2, EXCP_LINEF);
                    670: }
                    671: 
                    672: DISAS_INSN(undef)
                    673: {
                    674:     gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
                    675:     cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
                    676:               insn, s->pc - 2);
                    677: }
                    678: 
                    679: DISAS_INSN(mulw)
                    680: {
                    681:     int reg;
                    682:     int tmp;
                    683:     int src;
                    684:     int sign;
                    685: 
                    686:     sign = (insn & 0x100) != 0;
                    687:     reg = DREG(insn, 9);
                    688:     tmp = gen_new_qreg(QMODE_I32);
                    689:     if (sign)
                    690:         gen_op_ext16s32(tmp, reg);
                    691:     else
                    692:         gen_op_ext16u32(tmp, reg);
                    693:     src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
                    694:     gen_op_mul32(tmp, tmp, src);
                    695:     gen_op_mov32(reg, tmp);
                    696:     /* Unlike m68k, coldfire always clears the overflow bit.  */
                    697:     gen_logic_cc(s, tmp);
                    698: }
                    699: 
                    700: DISAS_INSN(divw)
                    701: {
                    702:     int reg;
                    703:     int tmp;
                    704:     int src;
                    705:     int sign;
                    706: 
                    707:     sign = (insn & 0x100) != 0;
                    708:     reg = DREG(insn, 9);
                    709:     if (sign) {
                    710:         gen_op_ext16s32(QREG_DIV1, reg);
                    711:     } else {
                    712:         gen_op_ext16u32(QREG_DIV1, reg);
                    713:     }
                    714:     src = gen_ea(s, insn, OS_WORD, sign ? -1 : 0, NULL);
                    715:     gen_op_mov32(QREG_DIV2, src);
                    716:     if (sign) {
                    717:         gen_op_divs(1);
                    718:     } else {
                    719:         gen_op_divu(1);
                    720:     }
                    721: 
                    722:     tmp = gen_new_qreg(QMODE_I32);
                    723:     src = gen_new_qreg(QMODE_I32);
                    724:     gen_op_ext16u32(tmp, QREG_DIV1);
                    725:     gen_op_shl32(src, QREG_DIV2, gen_im32(16));
                    726:     gen_op_or32(reg, tmp, src);
                    727:     gen_op_flags_set();
                    728:     s->cc_op = CC_OP_FLAGS;
                    729: }
                    730: 
                    731: DISAS_INSN(divl)
                    732: {
                    733:     int num;
                    734:     int den;
                    735:     int reg;
                    736:     uint16_t ext;
                    737: 
                    738:     ext = lduw(s->pc);
                    739:     s->pc += 2;
                    740:     if (ext & 0x87f8) {
                    741:         gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
                    742:         return;
                    743:     }
                    744:     num = DREG(ext, 12);
                    745:     reg = DREG(ext, 0);
                    746:     gen_op_mov32(QREG_DIV1, num);
                    747:     den = gen_ea(s, insn, OS_LONG, 0, NULL);
                    748:     gen_op_mov32(QREG_DIV2, den);
                    749:     if (ext & 0x0800) {
                    750:         gen_op_divs(2);
                    751:     } else {
                    752:         gen_op_divu(2);
                    753:     }
                    754:     if (num == reg) {
                    755:         /* div */
                    756:         gen_op_mov32 (reg, QREG_DIV1);
                    757:     } else {
                    758:         /* rem */
                    759:         gen_op_mov32 (reg, QREG_DIV2);
                    760:     }
                    761:     gen_op_flags_set();
                    762:     s->cc_op = CC_OP_FLAGS;
                    763: }
                    764: 
                    765: DISAS_INSN(addsub)
                    766: {
                    767:     int reg;
                    768:     int dest;
                    769:     int src;
                    770:     int tmp;
                    771:     int addr;
                    772:     int add;
                    773: 
                    774:     add = (insn & 0x4000) != 0;
                    775:     reg = DREG(insn, 9);
                    776:     dest = gen_new_qreg(QMODE_I32);
                    777:     if (insn & 0x100) {
                    778:         tmp = gen_ea(s, insn, OS_LONG, 0, &addr);
                    779:         src = reg;
                    780:     } else {
                    781:         tmp = reg;
                    782:         src = gen_ea(s, insn, OS_LONG, 0, NULL);
                    783:     }
                    784:     if (add) {
                    785:         gen_op_add32(dest, tmp, src);
                    786:         gen_op_update_xflag_lt(dest, src);
                    787:         s->cc_op = CC_OP_ADD;
                    788:     } else {
                    789:         gen_op_update_xflag_lt(tmp, src);
                    790:         gen_op_sub32(dest, tmp, src);
                    791:         s->cc_op = CC_OP_SUB;
                    792:     }
                    793:     gen_op_update_cc_add(dest, src);
                    794:     if (insn & 0x100) {
                    795:         gen_ea(s, insn, OS_LONG, dest, &addr);
                    796:     } else {
                    797:         gen_op_mov32(reg, dest);
                    798:     }
                    799: }
                    800: 
                    801: 
                    802: /* Reverse the order of the bits in REG.  */
                    803: DISAS_INSN(bitrev)
                    804: {
                    805:     int val;
                    806:     int tmp1;
                    807:     int tmp2;
                    808:     int reg;
                    809: 
                    810:     val = gen_new_qreg(QMODE_I32);
                    811:     tmp1 = gen_new_qreg(QMODE_I32);
                    812:     tmp2 = gen_new_qreg(QMODE_I32);
                    813:     reg = DREG(insn, 0);
                    814:     gen_op_mov32(val, reg);
                    815:     /* Reverse bits within each nibble.  */
                    816:     gen_op_shl32(tmp1, val, gen_im32(3));
                    817:     gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
                    818:     gen_op_shl32(tmp2, val, gen_im32(1));
                    819:     gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
                    820:     gen_op_or32(tmp1, tmp1, tmp2);
                    821:     gen_op_shr32(tmp2, val, gen_im32(1));
                    822:     gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
                    823:     gen_op_or32(tmp1, tmp1, tmp2);
                    824:     gen_op_shr32(tmp2, val, gen_im32(3));
                    825:     gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
                    826:     gen_op_or32(tmp1, tmp1, tmp2);
                    827:     /* Reverse nibbles withing bytes.  */
                    828:     gen_op_shl32(val, tmp1, gen_im32(4));
                    829:     gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
                    830:     gen_op_shr32(tmp2, tmp1, gen_im32(4));
                    831:     gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
                    832:     gen_op_or32(val, val, tmp2);
                    833:     /* Reverse bytes.  */
                    834:     gen_op_bswap32(reg, val);
                    835:     gen_op_mov32(reg, val);
                    836: }
                    837: 
                    838: DISAS_INSN(bitop_reg)
                    839: {
                    840:     int opsize;
                    841:     int op;
                    842:     int src1;
                    843:     int src2;
                    844:     int tmp;
                    845:     int addr;
                    846:     int dest;
                    847: 
                    848:     if ((insn & 0x38) != 0)
                    849:         opsize = OS_BYTE;
                    850:     else
                    851:         opsize = OS_LONG;
                    852:     op = (insn >> 6) & 3;
                    853:     src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
                    854:     src2 = DREG(insn, 9);
                    855:     dest = gen_new_qreg(QMODE_I32);
                    856: 
                    857:     gen_flush_flags(s);
                    858:     tmp = gen_new_qreg(QMODE_I32);
                    859:     if (opsize == OS_BYTE)
                    860:         gen_op_and32(tmp, src2, gen_im32(7));
                    861:     else
                    862:         gen_op_and32(tmp, src2, gen_im32(31));
                    863:     src2 = tmp;
                    864:     tmp = gen_new_qreg(QMODE_I32);
                    865:     gen_op_shl32(tmp, gen_im32(1), src2);
                    866: 
                    867:     gen_op_btest(src1, tmp);
                    868:     switch (op) {
                    869:     case 1: /* bchg */
                    870:         gen_op_xor32(dest, src1, tmp);
                    871:         break;
                    872:     case 2: /* bclr */
                    873:         gen_op_not32(tmp, tmp);
                    874:         gen_op_and32(dest, src1, tmp);
                    875:         break;
                    876:     case 3: /* bset */
                    877:         gen_op_or32(dest, src1, tmp);
                    878:         break;
                    879:     default: /* btst */
                    880:         break;
                    881:     }
                    882:     if (op)
                    883:         gen_ea(s, insn, opsize, dest, &addr);
                    884: }
                    885: 
                    886: DISAS_INSN(sats)
                    887: {
                    888:     int reg;
                    889:     int tmp;
                    890:     int l1;
                    891: 
                    892:     reg = DREG(insn, 0);
                    893:     tmp = gen_new_qreg(QMODE_I32);
                    894:     gen_flush_flags(s);
                    895:     gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
                    896:     l1 = gen_new_label();
                    897:     gen_op_jmp_z32(tmp, l1);
                    898:     tmp = gen_new_qreg(QMODE_I32);
                    899:     gen_op_shr32(tmp, reg, gen_im32(31));
                    900:     gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
                    901:     gen_op_mov32(reg, tmp);
                    902:     gen_set_label(l1);
                    903:     gen_logic_cc(s, tmp);
                    904: }
                    905: 
                    906: static void gen_push(int val)
                    907: {
                    908:     int tmp;
                    909: 
                    910:     tmp = gen_new_qreg(QMODE_I32);
                    911:     gen_op_sub32(tmp, QREG_SP, gen_im32(4));
                    912:     gen_store(OS_LONG, tmp, val);
                    913:     gen_op_mov32(QREG_SP, tmp);
                    914: }
                    915: 
                    916: DISAS_INSN(movem)
                    917: {
                    918:     int addr;
                    919:     int i;
                    920:     uint16_t mask;
                    921:     int reg;
                    922:     int tmp;
                    923:     int is_load;
                    924: 
                    925:     mask = lduw(s->pc);
                    926:     s->pc += 2;
                    927:     tmp = gen_lea(s, insn, OS_LONG);
                    928:     addr = gen_new_qreg(QMODE_I32);
                    929:     gen_op_mov32(addr, tmp);
                    930:     is_load = ((insn & 0x0400) != 0);
                    931:     for (i = 0; i < 16; i++, mask >>= 1) {
                    932:         if (mask & 1) {
                    933:             if (i < 8)
                    934:                 reg = DREG(i, 0);
                    935:             else
                    936:                 reg = AREG(i, 0);
                    937:             if (is_load) {
                    938:                 tmp = gen_load(OS_LONG, addr, 0);
                    939:                 gen_op_mov32(reg, tmp);
                    940:             } else {
                    941:                 gen_store(OS_LONG, addr, reg);
                    942:             }
                    943:             if (mask != 1)
                    944:                 gen_op_add32(addr, addr, gen_im32(4));
                    945:         }
                    946:     }
                    947: }
                    948: 
                    949: DISAS_INSN(bitop_im)
                    950: {
                    951:     int opsize;
                    952:     int op;
                    953:     int src1;
                    954:     uint32_t mask;
                    955:     int bitnum;
                    956:     int tmp;
                    957:     int addr;
                    958:     int dest;
                    959: 
                    960:     if ((insn & 0x38) != 0)
                    961:         opsize = OS_BYTE;
                    962:     else
                    963:         opsize = OS_LONG;
                    964:     op = (insn >> 6) & 3;
                    965: 
                    966:     bitnum = lduw(s->pc);
                    967:     s->pc += 2;
                    968:     if (bitnum & 0xff00) {
                    969:         disas_undef(s, insn);
                    970:         return;
                    971:     }
                    972: 
                    973:     src1 = gen_ea(s, insn, opsize, 0, op ? &addr: NULL);
                    974: 
                    975:     gen_flush_flags(s);
                    976:     tmp = gen_new_qreg(QMODE_I32);
                    977:     if (opsize == OS_BYTE)
                    978:         bitnum &= 7;
                    979:     else
                    980:         bitnum &= 31;
                    981:     mask = 1 << bitnum;
                    982: 
                    983:     gen_op_btest(src1, gen_im32(mask));
                    984:     if (op)
                    985:         dest = gen_new_qreg(QMODE_I32);
                    986:     else
                    987:         dest = -1;
                    988: 
                    989:     switch (op) {
                    990:     case 1: /* bchg */
                    991:         gen_op_xor32(dest, src1, gen_im32(mask));
                    992:         break;
                    993:     case 2: /* bclr */
                    994:         gen_op_and32(dest, src1, gen_im32(~mask));
                    995:         break;
                    996:     case 3: /* bset */
                    997:         gen_op_or32(dest, src1, gen_im32(mask));
                    998:         break;
                    999:     default: /* btst */
                   1000:         break;
                   1001:     }
                   1002:     if (op)
                   1003:         gen_ea(s, insn, opsize, dest, &addr);
                   1004: }
                   1005: 
                   1006: DISAS_INSN(arith_im)
                   1007: {
                   1008:     int op;
                   1009:     int src1;
                   1010:     int dest;
                   1011:     int src2;
                   1012:     int addr;
                   1013: 
                   1014:     op = (insn >> 9) & 7;
                   1015:     src1 = gen_ea(s, insn, OS_LONG, 0, (op == 6) ? NULL : &addr);
                   1016:     src2 = gen_im32(read_im32(s));
                   1017:     dest = gen_new_qreg(QMODE_I32);
                   1018:     switch (op) {
                   1019:     case 0: /* ori */
                   1020:         gen_op_or32(dest, src1, src2);
                   1021:         gen_logic_cc(s, dest);
                   1022:         break;
                   1023:     case 1: /* andi */
                   1024:         gen_op_and32(dest, src1, src2);
                   1025:         gen_logic_cc(s, dest);
                   1026:         break;
                   1027:     case 2: /* subi */
                   1028:         gen_op_mov32(dest, src1);
                   1029:         gen_op_update_xflag_lt(dest, src2);
                   1030:         gen_op_sub32(dest, dest, src2);
                   1031:         gen_op_update_cc_add(dest, src2);
                   1032:         s->cc_op = CC_OP_SUB;
                   1033:         break;
                   1034:     case 3: /* addi */
                   1035:         gen_op_mov32(dest, src1);
                   1036:         gen_op_add32(dest, dest, src2);
                   1037:         gen_op_update_cc_add(dest, src2);
                   1038:         gen_op_update_xflag_lt(dest, src2);
                   1039:         s->cc_op = CC_OP_ADD;
                   1040:         break;
                   1041:     case 5: /* eori */
                   1042:         gen_op_xor32(dest, src1, src2);
                   1043:         gen_logic_cc(s, dest);
                   1044:         break;
                   1045:     case 6: /* cmpi */
                   1046:         gen_op_mov32(dest, src1);
                   1047:         gen_op_sub32(dest, dest, src2);
                   1048:         gen_op_update_cc_add(dest, src2);
                   1049:         s->cc_op = CC_OP_SUB;
                   1050:         break;
                   1051:     default:
                   1052:         abort();
                   1053:     }
                   1054:     if (op != 6) {
                   1055:         gen_ea(s, insn, OS_LONG, dest, &addr);
                   1056:     }
                   1057: }
                   1058: 
                   1059: DISAS_INSN(byterev)
                   1060: {
                   1061:     int reg;
                   1062: 
                   1063:     reg = DREG(insn, 0);
                   1064:     gen_op_bswap32(reg, reg);
                   1065: }
                   1066: 
                   1067: DISAS_INSN(move)
                   1068: {
                   1069:     int src;
                   1070:     int dest;
                   1071:     int op;
                   1072:     int opsize;
                   1073: 
                   1074:     switch (insn >> 12) {
                   1075:     case 1: /* move.b */
                   1076:         opsize = OS_BYTE;
                   1077:         break;
                   1078:     case 2: /* move.l */
                   1079:         opsize = OS_LONG;
                   1080:         break;
                   1081:     case 3: /* move.w */
                   1082:         opsize = OS_WORD;
                   1083:         break;
                   1084:     default:
                   1085:         abort();
                   1086:     }
                   1087:     src = gen_ea(s, insn, opsize, -1, NULL);
                   1088:     op = (insn >> 6) & 7;
                   1089:     if (op == 1) {
                   1090:         /* movea */
                   1091:         /* The value will already have been sign extended.  */
                   1092:         dest = AREG(insn, 9);
                   1093:         gen_op_mov32(dest, src);
                   1094:     } else {
                   1095:         /* normal move */
                   1096:         uint16_t dest_ea;
                   1097:         dest_ea = ((insn >> 9) & 7) | (op << 3);
                   1098:         gen_ea(s, dest_ea, opsize, src, NULL);
                   1099:         /* This will be correct because loads sign extend.  */
                   1100:         gen_logic_cc(s, src);
                   1101:     }
                   1102: }
                   1103: 
                   1104: DISAS_INSN(negx)
                   1105: {
                   1106:     int reg;
                   1107:     int dest;
                   1108:     int tmp;
                   1109: 
                   1110:     gen_flush_flags(s);
                   1111:     reg = DREG(insn, 0);
                   1112:     dest = gen_new_qreg(QMODE_I32);
                   1113:     gen_op_mov32 (dest, gen_im32(0));
                   1114:     gen_op_subx_cc(dest, reg);
                   1115:     /* !Z is sticky.  */
                   1116:     tmp = gen_new_qreg(QMODE_I32);
                   1117:     gen_op_mov32 (tmp, QREG_CC_DEST);
                   1118:     gen_op_update_cc_add(dest, reg);
                   1119:     gen_op_mov32(reg, dest);
                   1120:     s->cc_op = CC_OP_DYNAMIC;
                   1121:     gen_flush_flags(s);
                   1122:     gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
                   1123:     gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
                   1124:     s->cc_op = CC_OP_FLAGS;
                   1125: }
                   1126: 
                   1127: DISAS_INSN(lea)
                   1128: {
                   1129:     int reg;
                   1130:     int tmp;
                   1131: 
                   1132:     reg = AREG(insn, 9);
                   1133:     tmp = gen_lea(s, insn, OS_LONG);
                   1134:     gen_op_mov32(reg, tmp);
                   1135: }
                   1136: 
                   1137: DISAS_INSN(clr)
                   1138: {
                   1139:     int opsize;
                   1140: 
                   1141:     switch ((insn >> 6) & 3) {
                   1142:     case 0: /* clr.b */
                   1143:         opsize = OS_BYTE;
                   1144:         break;
                   1145:     case 1: /* clr.w */
                   1146:         opsize = OS_WORD;
                   1147:         break;
                   1148:     case 2: /* clr.l */
                   1149:         opsize = OS_LONG;
                   1150:         break;
                   1151:     default:
                   1152:         abort();
                   1153:     }
                   1154:     gen_ea (s, insn, opsize, gen_im32(0), NULL);
                   1155:     gen_logic_cc(s, gen_im32(0));
                   1156: }
                   1157: 
                   1158: DISAS_INSN(move_from_ccr)
                   1159: {
                   1160:     int reg;
                   1161:     int dest;
                   1162: 
                   1163:     gen_flush_flags(s);
                   1164:     dest = gen_new_qreg(QMODE_I32);
                   1165:     gen_op_get_xflag(dest);
                   1166:     gen_op_shl32(dest, dest, gen_im32(4));
                   1167:     gen_op_or32(dest, dest, QREG_CC_DEST);
                   1168:     reg = DREG(insn, 0);
                   1169:     gen_partset_reg(OS_WORD, reg, dest);
                   1170: }
                   1171: 
                   1172: DISAS_INSN(neg)
                   1173: {
                   1174:     int reg;
                   1175:     int src1;
                   1176: 
                   1177:     reg = DREG(insn, 0);
                   1178:     src1 = gen_new_qreg(QMODE_I32);
                   1179:     gen_op_mov32(src1, reg);
                   1180:     gen_op_neg32(reg, src1);
                   1181:     s->cc_op = CC_OP_SUB;
                   1182:     gen_op_update_cc_add(reg, src1);
                   1183:     gen_op_update_xflag_lt(gen_im32(0), src1);
                   1184:     s->cc_op = CC_OP_SUB;
                   1185: }
                   1186: 
                   1187: DISAS_INSN(move_to_ccr)
                   1188: {
                   1189:     int src1;
                   1190:     int reg;
                   1191: 
                   1192:     s->cc_op = CC_OP_FLAGS;
                   1193:     if ((insn & 0x38) == 0)
                   1194:       {
                   1195:         src1 = gen_new_qreg(QMODE_I32);
                   1196:         reg = DREG(insn, 0);
                   1197:         gen_op_and32(src1, reg, gen_im32(0xf));
                   1198:         gen_op_logic_cc(src1);
                   1199:         gen_op_shr32(src1, reg, gen_im32(4));
                   1200:         gen_op_and32(src1, src1, gen_im32(1));
                   1201:         gen_op_update_xflag_tst(src1);
                   1202:       }
                   1203:     else if ((insn & 0x3f) != 0x3c)
                   1204:       {
                   1205:         uint8_t val;
                   1206:         val = ldsb(s->pc);
                   1207:         s->pc += 2;
                   1208:         gen_op_logic_cc(gen_im32(val & 0xf));
                   1209:         gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
                   1210:       }
                   1211:     else
                   1212:         disas_undef(s, insn);
                   1213: }
                   1214: 
                   1215: DISAS_INSN(not)
                   1216: {
                   1217:     int reg;
                   1218: 
                   1219:     reg = DREG(insn, 0);
                   1220:     gen_op_not32(reg, reg);
                   1221:     gen_logic_cc(s, reg);
                   1222: }
                   1223: 
                   1224: DISAS_INSN(swap)
                   1225: {
                   1226:     int dest;
                   1227:     int src1;
                   1228:     int src2;
                   1229:     int reg;
                   1230: 
                   1231:     dest = gen_new_qreg(QMODE_I32);
                   1232:     src1 = gen_new_qreg(QMODE_I32);
                   1233:     src2 = gen_new_qreg(QMODE_I32);
                   1234:     reg = DREG(insn, 0);
                   1235:     gen_op_shl32(src1, reg, gen_im32(16));
                   1236:     gen_op_shr32(src2, reg, gen_im32(16));
                   1237:     gen_op_or32(dest, src1, src2);
                   1238:     gen_op_mov32(reg, dest);
                   1239:     gen_logic_cc(s, dest);
                   1240: }
                   1241: 
                   1242: DISAS_INSN(pea)
                   1243: {
                   1244:     int tmp;
                   1245: 
                   1246:     tmp = gen_lea(s, insn, OS_LONG);
                   1247:     gen_push(tmp);
                   1248: }
                   1249: 
                   1250: DISAS_INSN(ext)
                   1251: {
                   1252:     int reg;
                   1253:     int op;
                   1254:     int tmp;
                   1255: 
                   1256:     reg = DREG(insn, 0);
                   1257:     op = (insn >> 6) & 7;
                   1258:     tmp = gen_new_qreg(QMODE_I32);
                   1259:     if (op == 3)
                   1260:         gen_op_ext16s32(tmp, reg);
                   1261:     else
                   1262:         gen_op_ext8s32(tmp, reg);
                   1263:     if (op == 2)
                   1264:         gen_partset_reg(OS_WORD, reg, tmp);
                   1265:     else
                   1266:       gen_op_mov32(reg, tmp);
                   1267:     gen_logic_cc(s, tmp);
                   1268: }
                   1269: 
                   1270: DISAS_INSN(tst)
                   1271: {
                   1272:     int opsize;
                   1273:     int tmp;
                   1274: 
                   1275:     switch ((insn >> 6) & 3) {
                   1276:     case 0: /* tst.b */
                   1277:         opsize = OS_BYTE;
                   1278:         break;
                   1279:     case 1: /* tst.w */
                   1280:         opsize = OS_WORD;
                   1281:         break;
                   1282:     case 2: /* tst.l */
                   1283:         opsize = OS_LONG;
                   1284:         break;
                   1285:     default:
                   1286:         abort();
                   1287:     }
                   1288:     tmp = gen_ea(s, insn, opsize, -1, NULL);
                   1289:     gen_logic_cc(s, tmp);
                   1290: }
                   1291: 
                   1292: DISAS_INSN(pulse)
                   1293: {
                   1294:   /* Implemented as a NOP.  */
                   1295: }
                   1296: 
                   1297: DISAS_INSN(illegal)
                   1298: {
                   1299:     gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
                   1300: }
                   1301: 
                   1302: /* ??? This should be atomic.  */
                   1303: DISAS_INSN(tas)
                   1304: {
                   1305:     int dest;
                   1306:     int src1;
                   1307:     int addr;
                   1308: 
                   1309:     dest = gen_new_qreg(QMODE_I32);
                   1310:     src1 = gen_ea(s, insn, OS_BYTE, -1, &addr);
                   1311:     gen_logic_cc(s, src1);
                   1312:     gen_op_or32(dest, src1, gen_im32(0x80));
                   1313:     gen_ea(s, insn, OS_BYTE, dest, &addr);
                   1314: }
                   1315: 
                   1316: DISAS_INSN(mull)
                   1317: {
                   1318:     uint16_t ext;
                   1319:     int reg;
                   1320:     int src1;
                   1321:     int dest;
                   1322: 
                   1323:     /* The upper 32 bits of the product are discarded, so
                   1324:        muls.l and mulu.l are functionally equivalent.  */
                   1325:     ext = lduw(s->pc);
                   1326:     s->pc += 2;
                   1327:     if (ext & 0x87ff) {
                   1328:         gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
                   1329:         return;
                   1330:     }
                   1331:     reg = DREG(ext, 12);
                   1332:     src1 = gen_ea(s, insn, OS_LONG, 0, NULL);
                   1333:     dest = gen_new_qreg(QMODE_I32);
                   1334:     gen_op_mul32(dest, src1, reg);
                   1335:     gen_op_mov32(reg, dest);
                   1336:     /* Unlike m68k, coldfire always clears the overflow bit.  */
                   1337:     gen_logic_cc(s, dest);
                   1338: }
                   1339: 
                   1340: DISAS_INSN(link)
                   1341: {
                   1342:     int16_t offset;
                   1343:     int reg;
                   1344:     int tmp;
                   1345: 
                   1346:     offset = ldsw(s->pc);
                   1347:     s->pc += 2;
                   1348:     reg = AREG(insn, 0);
                   1349:     tmp = gen_new_qreg(QMODE_I32);
                   1350:     gen_op_sub32(tmp, QREG_SP, gen_im32(4));
                   1351:     gen_store(OS_LONG, tmp, reg);
                   1352:     if (reg != QREG_SP)
                   1353:         gen_op_mov32(reg, tmp);
                   1354:     gen_op_add32(QREG_SP, tmp, gen_im32(offset));
                   1355: }
                   1356: 
                   1357: DISAS_INSN(unlk)
                   1358: {
                   1359:     int src;
                   1360:     int reg;
                   1361:     int tmp;
                   1362: 
                   1363:     src = gen_new_qreg(QMODE_I32);
                   1364:     reg = AREG(insn, 0);
                   1365:     gen_op_mov32(src, reg);
                   1366:     tmp = gen_load(OS_LONG, src, 0);
                   1367:     gen_op_mov32(reg, tmp);
                   1368:     gen_op_add32(QREG_SP, src, gen_im32(4));
                   1369: }
                   1370: 
                   1371: DISAS_INSN(nop)
                   1372: {
                   1373: }
                   1374: 
                   1375: DISAS_INSN(rts)
                   1376: {
                   1377:     int tmp;
                   1378: 
                   1379:     tmp = gen_load(OS_LONG, QREG_SP, 0);
                   1380:     gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
                   1381:     gen_jmp(s, tmp);
                   1382: }
                   1383: 
                   1384: DISAS_INSN(jump)
                   1385: {
                   1386:     int tmp;
                   1387: 
                   1388:     /* Load the target address first to ensure correct exception
                   1389:        behavior.  */
                   1390:     tmp = gen_lea(s, insn, OS_LONG);
                   1391:     if ((insn & 0x40) == 0) {
                   1392:         /* jsr */
                   1393:         gen_push(gen_im32(s->pc));
                   1394:     }
                   1395:     gen_jmp(s, tmp);
                   1396: }
                   1397: 
                   1398: DISAS_INSN(addsubq)
                   1399: {
                   1400:     int src1;
                   1401:     int src2;
                   1402:     int dest;
                   1403:     int val;
                   1404:     int addr;
                   1405: 
                   1406:     src1 = gen_ea(s, insn, OS_LONG, 0, &addr);
                   1407:     val = (insn >> 9) & 7;
                   1408:     if (val == 0)
                   1409:         val = 8;
                   1410:     src2 = gen_im32(val);
                   1411:     dest = gen_new_qreg(QMODE_I32);
                   1412:     gen_op_mov32(dest, src1);
                   1413:     if ((insn & 0x38) == 0x08) {
                   1414:         /* Don't update condition codes if the destination is an
                   1415:            address register.  */
                   1416:         if (insn & 0x0100) {
                   1417:             gen_op_sub32(dest, dest, src2);
                   1418:         } else {
                   1419:             gen_op_add32(dest, dest, src2);
                   1420:         }
                   1421:     } else {
                   1422:         if (insn & 0x0100) {
                   1423:             gen_op_update_xflag_lt(dest, src2);
                   1424:             gen_op_sub32(dest, dest, src2);
                   1425:             s->cc_op = CC_OP_SUB;
                   1426:         } else {
                   1427:             gen_op_add32(dest, dest, src2);
                   1428:             gen_op_update_xflag_lt(dest, src2);
                   1429:             s->cc_op = CC_OP_ADD;
                   1430:         }
                   1431:         gen_op_update_cc_add(dest, src2);
                   1432:     }
                   1433:     gen_ea(s, insn, OS_LONG, dest, &addr);
                   1434: }
                   1435: 
                   1436: DISAS_INSN(tpf)
                   1437: {
                   1438:     switch (insn & 7) {
                   1439:     case 2: /* One extension word.  */
                   1440:         s->pc += 2;
                   1441:         break;
                   1442:     case 3: /* Two extension words.  */
                   1443:         s->pc += 4;
                   1444:         break;
                   1445:     case 4: /* No extension words.  */
                   1446:         break;
                   1447:     default:
                   1448:         disas_undef(s, insn);
                   1449:     }
                   1450: }
                   1451: 
                   1452: DISAS_INSN(branch)
                   1453: {
                   1454:     int32_t offset;
                   1455:     uint32_t base;
                   1456:     int op;
                   1457:     int l1;
                   1458:     
                   1459:     base = s->pc;
                   1460:     op = (insn >> 8) & 0xf;
                   1461:     offset = (int8_t)insn;
                   1462:     if (offset == 0) {
                   1463:         offset = ldsw(s->pc);
                   1464:         s->pc += 2;
                   1465:     } else if (offset == -1) {
                   1466:         offset = read_im32(s);
                   1467:     }
                   1468:     if (op == 1) {
                   1469:         /* bsr */
                   1470:         gen_push(gen_im32(s->pc));
                   1471:     }
                   1472:     gen_flush_cc_op(s);
                   1473:     if (op > 1) {
                   1474:         /* Bcc */
                   1475:         l1 = gen_new_label();
                   1476:         gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
                   1477:         gen_jmp_tb(s, 1, base + offset);
                   1478:         gen_set_label(l1);
                   1479:         gen_jmp_tb(s, 0, s->pc);
                   1480:     } else {
                   1481:         /* Unconditional branch.  */
                   1482:         gen_jmp_tb(s, 0, base + offset);
                   1483:     }
                   1484: }
                   1485: 
                   1486: DISAS_INSN(moveq)
                   1487: {
                   1488:     int tmp;
                   1489: 
                   1490:     tmp = gen_im32((int8_t)insn);
                   1491:     gen_op_mov32(DREG(insn, 9), tmp);
                   1492:     gen_logic_cc(s, tmp);
                   1493: }
                   1494: 
                   1495: DISAS_INSN(mvzs)
                   1496: {
                   1497:     int opsize;
                   1498:     int src;
                   1499:     int reg;
                   1500: 
                   1501:     if (insn & 0x40)
                   1502:         opsize = OS_WORD;
                   1503:     else
                   1504:         opsize = OS_BYTE;
                   1505:     src = gen_ea(s, insn, opsize, (insn & 0x80) ? 0 : -1, NULL);
                   1506:     reg = DREG(insn, 9);
                   1507:     gen_op_mov32(reg, src);
                   1508:     gen_logic_cc(s, src);
                   1509: }
                   1510: 
                   1511: DISAS_INSN(or)
                   1512: {
                   1513:     int reg;
                   1514:     int dest;
                   1515:     int src;
                   1516:     int addr;
                   1517: 
                   1518:     reg = DREG(insn, 9);
                   1519:     dest = gen_new_qreg(QMODE_I32);
                   1520:     if (insn & 0x100) {
                   1521:         src = gen_ea(s, insn, OS_LONG, 0, &addr);
                   1522:         gen_op_or32(dest, src, reg);
                   1523:         gen_ea(s, insn, OS_LONG, dest, &addr);
                   1524:     } else {
                   1525:         src = gen_ea(s, insn, OS_LONG, 0, NULL);
                   1526:         gen_op_or32(dest, src, reg);
                   1527:         gen_op_mov32(reg, dest);
                   1528:     }
                   1529:     gen_logic_cc(s, dest);
                   1530: }
                   1531: 
                   1532: DISAS_INSN(suba)
                   1533: {
                   1534:     int src;
                   1535:     int reg;
                   1536: 
                   1537:     src = gen_ea(s, insn, OS_LONG, 0, NULL);
                   1538:     reg = AREG(insn, 9);
                   1539:     gen_op_sub32(reg, reg, src);
                   1540: }
                   1541: 
                   1542: DISAS_INSN(subx)
                   1543: {
                   1544:     int reg;
                   1545:     int src;
                   1546:     int dest;
                   1547:     int tmp;
                   1548: 
                   1549:     gen_flush_flags(s);
                   1550:     reg = DREG(insn, 9);
                   1551:     src = DREG(insn, 0);
                   1552:     dest = gen_new_qreg(QMODE_I32);
                   1553:     gen_op_mov32 (dest, reg);
                   1554:     gen_op_subx_cc(dest, src);
                   1555:     /* !Z is sticky.  */
                   1556:     tmp = gen_new_qreg(QMODE_I32);
                   1557:     gen_op_mov32 (tmp, QREG_CC_DEST);
                   1558:     gen_op_update_cc_add(dest, src);
                   1559:     gen_op_mov32(reg, dest);
                   1560:     s->cc_op = CC_OP_DYNAMIC;
                   1561:     gen_flush_flags(s);
                   1562:     gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
                   1563:     gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
                   1564:     s->cc_op = CC_OP_FLAGS;
                   1565: }
                   1566: 
                   1567: DISAS_INSN(mov3q)
                   1568: {
                   1569:     int src;
                   1570:     int val;
                   1571: 
                   1572:     val = (insn >> 9) & 7;
                   1573:     if (val == 0)
                   1574:         val = -1;
                   1575:     src = gen_im32(val);
                   1576:     gen_logic_cc(s, src);
                   1577:     gen_ea(s, insn, OS_LONG, src, NULL);
                   1578: }
                   1579: 
                   1580: DISAS_INSN(cmp)
                   1581: {
                   1582:     int op;
                   1583:     int src;
                   1584:     int reg;
                   1585:     int dest;
                   1586:     int opsize;
                   1587: 
                   1588:     op = (insn >> 6) & 3;
                   1589:     switch (op) {
                   1590:     case 0: /* cmp.b */
                   1591:         opsize = OS_BYTE;
                   1592:         s->cc_op = CC_OP_CMPB;
                   1593:         break;
                   1594:     case 1: /* cmp.w */
                   1595:         opsize = OS_WORD;
                   1596:         s->cc_op = CC_OP_CMPW;
                   1597:         break;
                   1598:     case 2: /* cmp.l */
                   1599:         opsize = OS_LONG;
                   1600:         s->cc_op = CC_OP_SUB;
                   1601:         break;
                   1602:     default:
                   1603:         abort();
                   1604:     }
                   1605:     src = gen_ea(s, insn, opsize, -1, NULL);
                   1606:     reg = DREG(insn, 9);
                   1607:     dest = gen_new_qreg(QMODE_I32);
                   1608:     gen_op_sub32(dest, reg, src);
                   1609:     gen_op_update_cc_add(dest, src);
                   1610: }
                   1611: 
                   1612: DISAS_INSN(cmpa)
                   1613: {
                   1614:     int opsize;
                   1615:     int src;
                   1616:     int reg;
                   1617:     int dest;
                   1618: 
                   1619:     if (insn & 0x100) {
                   1620:         opsize = OS_LONG;
                   1621:     } else {
                   1622:         opsize = OS_WORD;
                   1623:     }
                   1624:     src = gen_ea(s, insn, opsize, -1, NULL);
                   1625:     reg = AREG(insn, 9);
                   1626:     dest = gen_new_qreg(QMODE_I32);
                   1627:     gen_op_sub32(dest, reg, src);
                   1628:     gen_op_update_cc_add(dest, src);
                   1629:     s->cc_op = CC_OP_SUB;
                   1630: }
                   1631: 
                   1632: DISAS_INSN(eor)
                   1633: {
                   1634:     int src;
                   1635:     int reg;
                   1636:     int dest;
                   1637:     int addr;
                   1638: 
                   1639:     src = gen_ea(s, insn, OS_LONG, 0, &addr);
                   1640:     reg = DREG(insn, 9);
                   1641:     dest = gen_new_qreg(QMODE_I32);
                   1642:     gen_op_xor32(dest, src, reg);
                   1643:     gen_logic_cc(s, dest);
                   1644:     gen_ea(s, insn, OS_LONG, dest, &addr);
                   1645: }
                   1646: 
                   1647: DISAS_INSN(and)
                   1648: {
                   1649:     int src;
                   1650:     int reg;
                   1651:     int dest;
                   1652:     int addr;
                   1653: 
                   1654:     reg = DREG(insn, 9);
                   1655:     dest = gen_new_qreg(QMODE_I32);
                   1656:     if (insn & 0x100) {
                   1657:         src = gen_ea(s, insn, OS_LONG, 0, &addr);
                   1658:         gen_op_and32(dest, src, reg);
                   1659:         gen_ea(s, insn, OS_LONG, dest, &addr);
                   1660:     } else {
                   1661:         src = gen_ea(s, insn, OS_LONG, 0, NULL);
                   1662:         gen_op_and32(dest, src, reg);
                   1663:         gen_op_mov32(reg, dest);
                   1664:     }
                   1665:     gen_logic_cc(s, dest);
                   1666: }
                   1667: 
                   1668: DISAS_INSN(adda)
                   1669: {
                   1670:     int src;
                   1671:     int reg;
                   1672: 
                   1673:     src = gen_ea(s, insn, OS_LONG, 0, NULL);
                   1674:     reg = AREG(insn, 9);
                   1675:     gen_op_add32(reg, reg, src);
                   1676: }
                   1677: 
                   1678: DISAS_INSN(addx)
                   1679: {
                   1680:     int reg;
                   1681:     int src;
                   1682:     int dest;
                   1683:     int tmp;
                   1684: 
                   1685:     gen_flush_flags(s);
                   1686:     reg = DREG(insn, 9);
                   1687:     src = DREG(insn, 0);
                   1688:     dest = gen_new_qreg(QMODE_I32);
                   1689:     gen_op_mov32 (dest, reg);
                   1690:     gen_op_addx_cc(dest, src);
                   1691:     /* !Z is sticky.  */
                   1692:     tmp = gen_new_qreg(QMODE_I32);
                   1693:     gen_op_mov32 (tmp, QREG_CC_DEST);
                   1694:     gen_op_update_cc_add(dest, src);
                   1695:     gen_op_mov32(reg, dest);
                   1696:     s->cc_op = CC_OP_DYNAMIC;
                   1697:     gen_flush_flags(s);
                   1698:     gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
                   1699:     gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
                   1700:     s->cc_op = CC_OP_FLAGS;
                   1701: }
                   1702: 
                   1703: DISAS_INSN(shift_im)
                   1704: {
                   1705:     int reg;
                   1706:     int tmp;
                   1707: 
                   1708:     reg = DREG(insn, 0);
                   1709:     tmp = (insn >> 9) & 7;
                   1710:     if (tmp == 0)
                   1711:       tmp = 8;
                   1712:     if (insn & 0x100) {
                   1713:         gen_op_shl_im_cc(reg, tmp);
                   1714:         s->cc_op = CC_OP_SHL;
                   1715:     } else {
                   1716:         if (insn & 8) {
                   1717:             gen_op_shr_im_cc(reg, tmp);
                   1718:             s->cc_op = CC_OP_SHR;
                   1719:         } else {
                   1720:             gen_op_sar_im_cc(reg, tmp);
                   1721:             s->cc_op = CC_OP_SAR;
                   1722:         }
                   1723:     }
                   1724: }
                   1725: 
                   1726: DISAS_INSN(shift_reg)
                   1727: {
                   1728:     int reg;
                   1729:     int src;
                   1730:     int tmp;
                   1731: 
                   1732:     reg = DREG(insn, 0);
                   1733:     src = DREG(insn, 9);
                   1734:     tmp = gen_new_qreg(QMODE_I32);
                   1735:     gen_op_and32(tmp, src, gen_im32(63));
                   1736:     if (insn & 0x100) {
                   1737:         gen_op_shl_cc(reg, tmp);
                   1738:         s->cc_op = CC_OP_SHL;
                   1739:     } else {
                   1740:         if (insn & 8) {
                   1741:             gen_op_shr_cc(reg, tmp);
                   1742:             s->cc_op = CC_OP_SHR;
                   1743:         } else {
                   1744:             gen_op_sar_cc(reg, tmp);
                   1745:             s->cc_op = CC_OP_SAR;
                   1746:         }
                   1747:     }
                   1748: }
                   1749: 
                   1750: DISAS_INSN(ff1)
                   1751: {
                   1752:     cpu_abort(NULL, "Unimplemented insn: ff1");
                   1753: }
                   1754: 
                   1755: DISAS_INSN(strldsr)
                   1756: {
                   1757:     uint16_t ext;
                   1758:     uint32_t addr;
                   1759: 
                   1760:     addr = s->pc - 2;
                   1761:     ext = lduw(s->pc);
                   1762:     s->pc += 2;
                   1763:     if (ext != 0x46FC)
                   1764:         gen_exception(s, addr, EXCP_UNSUPPORTED);
                   1765:     else
                   1766:         gen_exception(s, addr, EXCP_PRIVILEGE);
                   1767: }
                   1768: 
                   1769: DISAS_INSN(move_from_sr)
                   1770: {
                   1771:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1772: }
                   1773: 
                   1774: DISAS_INSN(move_to_sr)
                   1775: {
                   1776:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1777: }
                   1778: 
                   1779: DISAS_INSN(move_from_usp)
                   1780: {
                   1781:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1782: }
                   1783: 
                   1784: DISAS_INSN(move_to_usp)
                   1785: {
                   1786:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1787: }
                   1788: 
                   1789: DISAS_INSN(halt)
                   1790: {
                   1791:     gen_exception(s, s->pc, EXCP_HLT);
                   1792: }
                   1793: 
                   1794: DISAS_INSN(stop)
                   1795: {
                   1796:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1797: }
                   1798: 
                   1799: DISAS_INSN(rte)
                   1800: {
                   1801:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1802: }
                   1803: 
                   1804: DISAS_INSN(movec)
                   1805: {
                   1806:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1807: }
                   1808: 
                   1809: DISAS_INSN(intouch)
                   1810: {
                   1811:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1812: }
                   1813: 
                   1814: DISAS_INSN(cpushl)
                   1815: {
                   1816:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1817: }
                   1818: 
                   1819: DISAS_INSN(wddata)
                   1820: {
                   1821:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1822: }
                   1823: 
                   1824: DISAS_INSN(wdebug)
                   1825: {
                   1826:     gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
                   1827: }
                   1828: 
                   1829: DISAS_INSN(trap)
                   1830: {
                   1831:     gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
                   1832: }
                   1833: 
                   1834: /* ??? FP exceptions are not implemented.  Most exceptions are deferred until
                   1835:    immediately before the next FP instruction is executed.  */
                   1836: DISAS_INSN(fpu)
                   1837: {
                   1838:     uint16_t ext;
                   1839:     int opmode;
                   1840:     int src;
                   1841:     int dest;
                   1842:     int res;
                   1843:     int round;
                   1844:     int opsize;
                   1845: 
                   1846:     ext = lduw(s->pc);
                   1847:     s->pc += 2;
                   1848:     opmode = ext & 0x7f;
                   1849:     switch ((ext >> 13) & 7) {
                   1850:     case 0: case 2:
                   1851:         break;
                   1852:     case 1:
                   1853:         goto undef;
                   1854:     case 3: /* fmove out */
                   1855:         src = FREG(ext, 7);
                   1856:         /* fmove */
                   1857:         /* ??? TODO: Proper behavior on overflow.  */
                   1858:         switch ((ext >> 10) & 7) {
                   1859:         case 0:
                   1860:             opsize = OS_LONG;
                   1861:             res = gen_new_qreg(QMODE_I32);
                   1862:             gen_op_f64_to_i32(res, src);
                   1863:             break;
                   1864:         case 1:
                   1865:             opsize = OS_SINGLE;
                   1866:             res = gen_new_qreg(QMODE_F32);
                   1867:             gen_op_f64_to_f32(res, src);
                   1868:             break;
                   1869:         case 4:
                   1870:             opsize = OS_WORD;
                   1871:             res = gen_new_qreg(QMODE_I32);
                   1872:             gen_op_f64_to_i32(res, src);
                   1873:             break;
                   1874:         case 5:
                   1875:             opsize = OS_DOUBLE;
                   1876:             res = src;
                   1877:             break;
                   1878:         case 6:
                   1879:             opsize = OS_BYTE;
                   1880:             res = gen_new_qreg(QMODE_I32);
                   1881:             gen_op_f64_to_i32(res, src);
                   1882:             break;
                   1883:         default:
                   1884:             goto undef;
                   1885:         }
                   1886:         gen_ea(s, insn, opsize, res, NULL);
                   1887:         return;
                   1888:     case 4: /* fmove to control register.  */
                   1889:         switch ((ext >> 10) & 7) {
                   1890:         case 4: /* FPCR */
                   1891:             /* Not implemented.  Ignore writes.  */
                   1892:             break;
                   1893:         case 1: /* FPIAR */
                   1894:         case 2: /* FPSR */
                   1895:         default:
                   1896:             cpu_abort(NULL, "Unimplemented: fmove to control %d",
                   1897:                       (ext >> 10) & 7);
                   1898:         }
                   1899:         break;
                   1900:     case 5: /* fmove from control register.  */
                   1901:         switch ((ext >> 10) & 7) {
                   1902:         case 4: /* FPCR */
                   1903:             /* Not implemented.  Always return zero.  */
                   1904:             res = gen_im32(0);
                   1905:             break;
                   1906:         case 1: /* FPIAR */
                   1907:         case 2: /* FPSR */
                   1908:         default:
                   1909:             cpu_abort(NULL, "Unimplemented: fmove from control %d",
                   1910:                       (ext >> 10) & 7);
                   1911:             goto undef;
                   1912:         }
                   1913:         gen_ea(s, insn, OS_LONG, res, NULL);
                   1914:         break;
                   1915:     case 6: /* fmovem */ 
                   1916:     case 7:
                   1917:         {
                   1918:         int addr;
                   1919:         uint16_t mask;
                   1920:         if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
                   1921:             goto undef;
                   1922:         src = gen_lea(s, insn, OS_LONG);
                   1923:         addr = gen_new_qreg(QMODE_I32);
                   1924:         gen_op_mov32(addr, src);
                   1925:         mask = 0x80;
                   1926:         dest = QREG_F0;
                   1927:         while (mask) {
                   1928:             if (ext & mask) {
                   1929:                 if (ext & (1 << 13)) {
                   1930:                     /* store */
                   1931:                     gen_op_stf64(addr, dest);
                   1932:                 } else {
                   1933:                     /* load */
                   1934:                     gen_op_ldf64(dest, addr);
                   1935:                 }
                   1936:                 if (ext & (mask - 1))
                   1937:                     gen_op_add32(addr, addr, gen_im32(8));
                   1938:             }
                   1939:             mask >>= 1;
                   1940:             dest++;
                   1941:         }
                   1942:         }
                   1943:         return;
                   1944:     }
                   1945:     if (ext & (1 << 14)) {
                   1946:         int tmp;
                   1947: 
                   1948:         /* Source effective address.  */
                   1949:         switch ((ext >> 10) & 7) {
                   1950:         case 0: opsize = OS_LONG; break;
                   1951:         case 1: opsize = OS_SINGLE; break;
                   1952:         case 4: opsize = OS_WORD; break;
                   1953:         case 5: opsize = OS_DOUBLE; break;
                   1954:         case 6: opsize = OS_BYTE; break;
                   1955:         default:
                   1956:             goto undef;
                   1957:         }
                   1958:         tmp = gen_ea(s, insn, opsize, -1, NULL);
                   1959:         if (opsize == OS_DOUBLE) {
                   1960:             src = tmp;
                   1961:         } else {
                   1962:             src = gen_new_qreg(QMODE_F64);
                   1963:             switch (opsize) {
                   1964:             case OS_LONG:
                   1965:             case OS_WORD:
                   1966:             case OS_BYTE:
                   1967:                 gen_op_i32_to_f64(src, tmp);
                   1968:                 break;
                   1969:             case OS_SINGLE:
                   1970:                 gen_op_f32_to_f64(src, tmp);
                   1971:                 break;
                   1972:             }
                   1973:         }
                   1974:     } else {
                   1975:         /* Source register.  */
                   1976:         src = FREG(ext, 10);
                   1977:     }
                   1978:     dest = FREG(ext, 7);
                   1979:     res = gen_new_qreg(QMODE_F64);
                   1980:     if (opmode != 0x3a)
                   1981:         gen_op_movf64(res, dest);
                   1982:     round = 1;
                   1983:     switch (opmode) {
                   1984:     case 0: case 0x40: case 0x44: /* fmove */
                   1985:         gen_op_movf64(res, src);
                   1986:         break;
                   1987:     case 1: /* fint */
                   1988:         gen_op_iround_f64(res, src);
                   1989:         round = 0;
                   1990:         break;
                   1991:     case 3: /* fintrz */
                   1992:         gen_op_itrunc_f64(res, src);
                   1993:         round = 0;
                   1994:         break;
                   1995:     case 4: case 0x41: case 0x45: /* fsqrt */
                   1996:         gen_op_sqrtf64(res, src);
                   1997:         break;
                   1998:     case 0x18: case 0x58: case 0x5c: /* fabs */
                   1999:         gen_op_absf64(res, src);
                   2000:         break;
                   2001:     case 0x1a: case 0x5a: case 0x5e: /* fneg */
                   2002:         gen_op_chsf64(res, src);
                   2003:         break;
                   2004:     case 0x20: case 0x60: case 0x64: /* fdiv */
                   2005:         gen_op_divf64(res, res, src);
                   2006:         break;
                   2007:     case 0x22: case 0x62: case 0x66: /* fadd */
                   2008:         gen_op_addf64(res, res, src);
                   2009:         break;
                   2010:     case 0x23: case 0x63: case 0x67: /* fmul */
                   2011:         gen_op_mulf64(res, res, src);
                   2012:         break;
                   2013:     case 0x28: case 0x68: case 0x6c: /* fsub */
                   2014:         gen_op_subf64(res, res, src);
                   2015:         break;
                   2016:     case 0x38: /* fcmp */
                   2017:         gen_op_sub_cmpf64(res, res, src);
                   2018:         dest = 0;
                   2019:         round = 0;
                   2020:         break;
                   2021:     case 0x3a: /* ftst */
                   2022:         gen_op_movf64(res, src);
                   2023:         dest = 0;
                   2024:         round = 0;
                   2025:         break;
                   2026:     default:
                   2027:         goto undef;
                   2028:     }
                   2029:     if (round) {
                   2030:         if (opmode & 0x40) {
                   2031:             if ((opmode & 0x4) != 0)
                   2032:                 round = 0;
                   2033:         } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
                   2034:             round = 0;
                   2035:         }
                   2036:     }
                   2037:     if (round) {
                   2038:         int tmp;
                   2039: 
                   2040:         tmp = gen_new_qreg(QMODE_F32);
                   2041:         gen_op_f64_to_f32(tmp, res);
                   2042:         gen_op_f32_to_f64(res, tmp);
                   2043:     } 
                   2044:     gen_op_fp_result(res);
                   2045:     if (dest) {
                   2046:         gen_op_movf64(dest, res);
                   2047:     }
                   2048:     return;
                   2049: undef:
                   2050:     s->pc -= 2;
                   2051:     disas_undef_fpu(s, insn);
                   2052: }
                   2053: 
                   2054: DISAS_INSN(fbcc)
                   2055: {
                   2056:     uint32_t offset;
                   2057:     uint32_t addr;
                   2058:     int flag;
                   2059:     int zero;
                   2060:     int l1;
                   2061: 
                   2062:     addr = s->pc;
                   2063:     offset = ldsw(s->pc);
                   2064:     s->pc += 2;
                   2065:     if (insn & (1 << 6)) {
                   2066:         offset = (offset << 16) | lduw(s->pc);
                   2067:         s->pc += 2;
                   2068:     }
                   2069: 
                   2070:     l1 = gen_new_label();
                   2071:     /* TODO: Raise BSUN exception.  */
                   2072:     flag = gen_new_qreg(QMODE_I32);
                   2073:     zero = gen_new_qreg(QMODE_F64);
                   2074:     gen_op_zerof64(zero);
                   2075:     gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
                   2076:     /* Jump to l1 if condition is true.  */
                   2077:     switch (insn & 0xf) {
                   2078:     case 0: /* f */
                   2079:         break;
                   2080:     case 1: /* eq (=0) */
                   2081:         gen_op_jmp_z32(flag, l1);
                   2082:         break;
                   2083:     case 2: /* ogt (=1) */
                   2084:         gen_op_sub32(flag, flag, gen_im32(1));
                   2085:         gen_op_jmp_z32(flag, l1);
                   2086:         break;
                   2087:     case 3: /* oge (=0 or =1) */
                   2088:         gen_op_jmp_z32(flag, l1);
                   2089:         gen_op_sub32(flag, flag, gen_im32(1));
                   2090:         gen_op_jmp_z32(flag, l1);
                   2091:         break;
                   2092:     case 4: /* olt (=-1) */
                   2093:         gen_op_jmp_s32(flag, l1);
                   2094:         break;
                   2095:     case 5: /* ole (=-1 or =0) */
                   2096:         gen_op_jmp_s32(flag, l1);
                   2097:         gen_op_jmp_z32(flag, l1);
                   2098:         break;
                   2099:     case 6: /* ogl (=-1 or =1) */
                   2100:         gen_op_jmp_s32(flag, l1);
                   2101:         gen_op_sub32(flag, flag, gen_im32(1));
                   2102:         gen_op_jmp_z32(flag, l1);
                   2103:         break;
                   2104:     case 7: /* or (=2) */
                   2105:         gen_op_sub32(flag, flag, gen_im32(2));
                   2106:         gen_op_jmp_z32(flag, l1);
                   2107:         break;
                   2108:     case 8: /* un (<2) */
                   2109:         gen_op_sub32(flag, flag, gen_im32(2));
                   2110:         gen_op_jmp_s32(flag, l1);
                   2111:         break;
                   2112:     case 9: /* ueq (=0 or =2) */
                   2113:         gen_op_jmp_z32(flag, l1);
                   2114:         gen_op_sub32(flag, flag, gen_im32(2));
                   2115:         gen_op_jmp_z32(flag, l1);
                   2116:         break;
                   2117:     case 10: /* ugt (>0) */
                   2118:         /* ??? Add jmp_gtu.  */
                   2119:         gen_op_sub32(flag, flag, gen_im32(1));
                   2120:         gen_op_jmp_ns32(flag, l1);
                   2121:         break;
                   2122:     case 11: /* uge (>=0) */
                   2123:         gen_op_jmp_ns32(flag, l1);
                   2124:         break;
                   2125:     case 12: /* ult (=-1 or =2) */
                   2126:         gen_op_jmp_s32(flag, l1);
                   2127:         gen_op_sub32(flag, flag, gen_im32(2));
                   2128:         gen_op_jmp_z32(flag, l1);
                   2129:         break;
                   2130:     case 13: /* ule (!=1) */
                   2131:         gen_op_sub32(flag, flag, gen_im32(1));
                   2132:         gen_op_jmp_nz32(flag, l1);
                   2133:         break;
                   2134:     case 14: /* ne (!=0) */
                   2135:         gen_op_jmp_nz32(flag, l1);
                   2136:         break;
                   2137:     case 15: /* t */
                   2138:         gen_op_mov32(flag, gen_im32(1));
                   2139:         break;
                   2140:     }
                   2141:     gen_jmp_tb(s, 0, s->pc);
                   2142:     gen_set_label(l1);
                   2143:     gen_jmp_tb(s, 1, addr + offset);
                   2144: }
                   2145: 
                   2146: static disas_proc opcode_table[65536];
                   2147: 
                   2148: static void
                   2149: register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
                   2150: {
                   2151:   int i;
                   2152:   int from;
                   2153:   int to;
                   2154: 
                   2155:   /* Sanity check.  All set bits must be included in the mask.  */
                   2156:   if (opcode & ~mask)
                   2157:       abort();
                   2158:   /* This could probably be cleverer.  For now just optimize the case where
                   2159:      the top bits are known.  */
                   2160:   /* Find the first zero bit in the mask.  */
                   2161:   i = 0x8000;
                   2162:   while ((i & mask) != 0)
                   2163:       i >>= 1;
                   2164:   /* Iterate over all combinations of this and lower bits.  */
                   2165:   if (i == 0)
                   2166:       i = 1;
                   2167:   else
                   2168:       i <<= 1;
                   2169:   from = opcode & ~(i - 1);
                   2170:   to = from + i;
                   2171:   for (i = from; i < to; i++)
                   2172:     {
                   2173:       if ((i & mask) == opcode)
                   2174:           opcode_table[i] = proc;
                   2175:     }
                   2176: }
                   2177: 
                   2178: /* Register m68k opcode handlers.  Order is important.
                   2179:    Later insn override earlier ones.  */
                   2180: static void
                   2181: register_m68k_insns (m68k_def_t *def)
                   2182: {
                   2183:     uint32_t iflags;
                   2184: 
                   2185:     iflags = def->insns;
                   2186: #define INSN(name, opcode, mask, isa) \
                   2187:     if (iflags & M68K_INSN_##isa) \
                   2188:         register_opcode(disas_##name, 0x##opcode, 0x##mask)
                   2189:     INSN(undef,     0000, 0000, CF_A);
                   2190:     INSN(arith_im,  0080, fff8, CF_A);
                   2191:     INSN(bitrev,    00c0, fff8, CF_C);
                   2192:     INSN(bitop_reg, 0100, f1c0, CF_A);
                   2193:     INSN(bitop_reg, 0140, f1c0, CF_A);
                   2194:     INSN(bitop_reg, 0180, f1c0, CF_A);
                   2195:     INSN(bitop_reg, 01c0, f1c0, CF_A);
                   2196:     INSN(arith_im,  0280, fff8, CF_A);
                   2197:     INSN(byterev,   02c0, fff8, CF_A);
                   2198:     INSN(arith_im,  0480, fff8, CF_A);
                   2199:     INSN(ff1,       04c0, fff8, CF_C);
                   2200:     INSN(arith_im,  0680, fff8, CF_A);
                   2201:     INSN(bitop_im,  0800, ffc0, CF_A);
                   2202:     INSN(bitop_im,  0840, ffc0, CF_A);
                   2203:     INSN(bitop_im,  0880, ffc0, CF_A);
                   2204:     INSN(bitop_im,  08c0, ffc0, CF_A);
                   2205:     INSN(arith_im,  0a80, fff8, CF_A);
                   2206:     INSN(arith_im,  0c00, ff38, CF_A);
                   2207:     INSN(move,      1000, f000, CF_A);
                   2208:     INSN(move,      2000, f000, CF_A);
                   2209:     INSN(move,      3000, f000, CF_A);
                   2210:     INSN(strldsr,   40e7, ffff, CF_A);
                   2211:     INSN(negx,      4080, fff8, CF_A);
                   2212:     INSN(move_from_sr, 40c0, fff8, CF_A);
                   2213:     INSN(lea,       41c0, f1c0, CF_A);
                   2214:     INSN(clr,       4200, ff00, CF_A);
                   2215:     INSN(undef,     42c0, ffc0, CF_A);
                   2216:     INSN(move_from_ccr, 42c0, fff8, CF_A);
                   2217:     INSN(neg,       4480, fff8, CF_A);
                   2218:     INSN(move_to_ccr, 44c0, ffc0, CF_A);
                   2219:     INSN(not,       4680, fff8, CF_A);
                   2220:     INSN(move_to_sr, 46c0, ffc0, CF_A);
                   2221:     INSN(pea,       4840, ffc0, CF_A);
                   2222:     INSN(swap,      4840, fff8, CF_A);
                   2223:     INSN(movem,     48c0, fbc0, CF_A);
                   2224:     INSN(ext,       4880, fff8, CF_A);
                   2225:     INSN(ext,       48c0, fff8, CF_A);
                   2226:     INSN(ext,       49c0, fff8, CF_A);
                   2227:     INSN(tst,       4a00, ff00, CF_A);
                   2228:     INSN(tas,       4ac0, ffc0, CF_B);
                   2229:     INSN(halt,      4ac8, ffff, CF_A);
                   2230:     INSN(pulse,     4acc, ffff, CF_A);
                   2231:     INSN(illegal,   4afc, ffff, CF_A);
                   2232:     INSN(mull,      4c00, ffc0, CF_A);
                   2233:     INSN(divl,      4c40, ffc0, CF_A);
                   2234:     INSN(sats,      4c80, fff8, CF_B);
                   2235:     INSN(trap,      4e40, fff0, CF_A);
                   2236:     INSN(link,      4e50, fff8, CF_A);
                   2237:     INSN(unlk,      4e58, fff8, CF_A);
                   2238:     INSN(move_to_usp, 4e60, fff8, CF_B);
                   2239:     INSN(move_from_usp, 4e68, fff8, CF_B);
                   2240:     INSN(nop,       4e71, ffff, CF_A);
                   2241:     INSN(stop,      4e72, ffff, CF_A);
                   2242:     INSN(rte,       4e73, ffff, CF_A);
                   2243:     INSN(rts,       4e75, ffff, CF_A);
                   2244:     INSN(movec,     4e7b, ffff, CF_A);
                   2245:     INSN(jump,      4e80, ffc0, CF_A);
                   2246:     INSN(jump,      4ec0, ffc0, CF_A);
                   2247:     INSN(addsubq,   5180, f1c0, CF_A);
                   2248:     INSN(scc,       50c0, f0f8, CF_A);
                   2249:     INSN(addsubq,   5080, f1c0, CF_A);
                   2250:     INSN(tpf,       51f8, fff8, CF_A);
                   2251:     INSN(branch,    6000, f000, CF_A);
                   2252:     INSN(moveq,     7000, f100, CF_A);
                   2253:     INSN(mvzs,      7100, f100, CF_B);
                   2254:     INSN(or,        8000, f000, CF_A);
                   2255:     INSN(divw,      80c0, f0c0, CF_A);
                   2256:     INSN(addsub,    9000, f000, CF_A);
                   2257:     INSN(subx,      9180, f1f8, CF_A);
                   2258:     INSN(suba,      91c0, f1c0, CF_A);
                   2259:     INSN(undef_mac, a000, f000, CF_A);
                   2260:     INSN(mov3q,     a140, f1c0, CF_B);
                   2261:     INSN(cmp,       b000, f1c0, CF_B); /* cmp.b */
                   2262:     INSN(cmp,       b040, f1c0, CF_B); /* cmp.w */
                   2263:     INSN(cmpa,      b0c0, f1c0, CF_B); /* cmpa.w */
                   2264:     INSN(cmp,       b080, f1c0, CF_A);
                   2265:     INSN(cmpa,      b1c0, f1c0, CF_A);
                   2266:     INSN(eor,       b180, f1c0, CF_A);
                   2267:     INSN(and,       c000, f000, CF_A);
                   2268:     INSN(mulw,      c0c0, f0c0, CF_A);
                   2269:     INSN(addsub,    d000, f000, CF_A);
                   2270:     INSN(addx,      d180, f1f8, CF_A);
                   2271:     INSN(adda,      d1c0, f1c0, CF_A);
                   2272:     INSN(shift_im,  e080, f0f0, CF_A);
                   2273:     INSN(shift_reg, e0a0, f0f0, CF_A);
                   2274:     INSN(undef_fpu, f000, f000, CF_A);
                   2275:     INSN(fpu,       f200, ffc0, CF_FPU);
                   2276:     INSN(fbcc,      f280, ffc0, CF_FPU);
                   2277:     INSN(intouch,   f340, ffc0, CF_A);
                   2278:     INSN(cpushl,    f428, ff38, CF_A);
                   2279:     INSN(wddata,    fb00, ff00, CF_A);
                   2280:     INSN(wdebug,    fbc0, ffc0, CF_A);
                   2281: #undef INSN
                   2282: }
                   2283: 
                   2284: /* ??? Some of this implementation is not exception safe.  We should always
                   2285:    write back the result to memory before setting the condition codes.  */
                   2286: static void disas_m68k_insn(CPUState * env, DisasContext *s)
                   2287: {
                   2288:     uint16_t insn;
                   2289: 
                   2290:     insn = lduw(s->pc);
                   2291:     s->pc += 2;
                   2292: 
                   2293:     opcode_table[insn](s, insn);
                   2294: }
                   2295: 
                   2296: #if 0
                   2297: /* Save the result of a floating point operation.  */
                   2298: static void expand_op_fp_result(qOP *qop)
                   2299: {
                   2300:     gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
                   2301: }
                   2302: 
                   2303: /* Dummy op to indicate that the flags have been set.  */
                   2304: static void expand_op_flags_set(qOP *qop)
                   2305: {
                   2306: }
                   2307: 
                   2308: /* Convert the confition codes into CC_OP_FLAGS format.  */
                   2309: static void expand_op_flush_flags(qOP *qop)
                   2310: {
                   2311:     int cc_opreg;
                   2312: 
                   2313:     if (qop->args[0] == CC_OP_DYNAMIC)
                   2314:         cc_opreg = QREG_CC_OP;
                   2315:     else
                   2316:         cc_opreg = gen_im32(qop->args[0]);
                   2317:     gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
                   2318: }
                   2319: 
                   2320: /* Set CC_DEST after a logical or direct flag setting operation.  */
                   2321: static void expand_op_logic_cc(qOP *qop)
                   2322: {
                   2323:     gen_op_mov32(QREG_CC_DEST, qop->args[0]);
                   2324: }
                   2325: 
                   2326: /* Set CC_SRC and CC_DEST after an arithmetic operation.  */
                   2327: static void expand_op_update_cc_add(qOP *qop)
                   2328: {
                   2329:     gen_op_mov32(QREG_CC_DEST, qop->args[0]);
                   2330:     gen_op_mov32(QREG_CC_SRC, qop->args[1]);
                   2331: }
                   2332: 
                   2333: /* Update the X flag.  */
                   2334: static void expand_op_update_xflag(qOP *qop)
                   2335: {
                   2336:     int arg0;
                   2337:     int arg1;
                   2338: 
                   2339:     arg0 = qop->args[0];
                   2340:     arg1 = qop->args[1];
                   2341:     if (arg1 == QREG_NULL) {
                   2342:         /* CC_X = arg0.  */
                   2343:         gen_op_mov32(QREG_CC_X, arg0);
                   2344:     } else {
                   2345:         /* CC_X = arg0 < (unsigned)arg1.  */
                   2346:         gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
                   2347:     }
                   2348: }
                   2349: 
                   2350: /* Set arg0 to the contents of the X flag.  */
                   2351: static void expand_op_get_xflag(qOP *qop)
                   2352: {
                   2353:     gen_op_mov32(qop->args[0], QREG_CC_X);
                   2354: }
                   2355: 
                   2356: /* Expand a shift by immediate.  The ISA only allows shifts by 1-8, so we
                   2357:    already know the shift is within range.  */
                   2358: static inline void expand_shift_im(qOP *qop, int right, int arith)
                   2359: {
                   2360:     int val;
                   2361:     int reg;
                   2362:     int tmp;
                   2363:     int im;
                   2364: 
                   2365:     reg = qop->args[0];
                   2366:     im = qop->args[1];
                   2367:     tmp = gen_im32(im);
                   2368:     val = gen_new_qreg(QMODE_I32);
                   2369:     gen_op_mov32(val, reg);
                   2370:     gen_op_mov32(QREG_CC_DEST, val);
                   2371:     gen_op_mov32(QREG_CC_SRC, tmp);
                   2372:     if (right) {
                   2373:         if (arith) {
                   2374:             gen_op_sar32(reg, val, tmp);
                   2375:         } else {
                   2376:             gen_op_shr32(reg, val, tmp);
                   2377:         }
                   2378:         if (im == 1)
                   2379:             tmp = QREG_NULL;
                   2380:         else
                   2381:             tmp = gen_im32(im - 1);
                   2382:     } else {
                   2383:         gen_op_shl32(reg, val, tmp);
                   2384:         tmp = gen_im32(32 - im);
                   2385:     }
                   2386:     if (tmp != QREG_NULL)
                   2387:         gen_op_shr32(val, val, tmp);
                   2388:     gen_op_and32(QREG_CC_X, val, gen_im32(1));
                   2389: }
                   2390: 
                   2391: static void expand_op_shl_im_cc(qOP *qop)
                   2392: {
                   2393:     expand_shift_im(qop, 0, 0);
                   2394: }
                   2395: 
                   2396: static void expand_op_shr_im_cc(qOP *qop)
                   2397: {
                   2398:     expand_shift_im(qop, 1, 0);
                   2399: }
                   2400: 
                   2401: static void expand_op_sar_im_cc(qOP *qop)
                   2402: {
                   2403:     expand_shift_im(qop, 1, 1);
                   2404: }
                   2405: 
                   2406: /* Expand a shift by register.  */
                   2407: /* ??? This gives incorrect answers for shifts by 0 or >= 32 */
                   2408: static inline void expand_shift_reg(qOP *qop, int right, int arith)
                   2409: {
                   2410:     int val;
                   2411:     int reg;
                   2412:     int shift;
                   2413:     int tmp;
                   2414: 
                   2415:     reg = qop->args[0];
                   2416:     shift = qop->args[1];
                   2417:     val = gen_new_qreg(QMODE_I32);
                   2418:     gen_op_mov32(val, reg);
                   2419:     gen_op_mov32(QREG_CC_DEST, val);
                   2420:     gen_op_mov32(QREG_CC_SRC, shift);
                   2421:     tmp = gen_new_qreg(QMODE_I32);
                   2422:     if (right) {
                   2423:         if (arith) {
                   2424:             gen_op_sar32(reg, val, shift);
                   2425:         } else {
                   2426:             gen_op_shr32(reg, val, shift);
                   2427:         }
                   2428:         gen_op_sub32(tmp, shift, gen_im32(1));
                   2429:     } else {
                   2430:         gen_op_shl32(reg, val, shift);
                   2431:         gen_op_sub32(tmp, gen_im32(31), shift);
                   2432:     }
                   2433:     gen_op_shl32(val, val, tmp);
                   2434:     gen_op_and32(QREG_CC_X, val, gen_im32(1));
                   2435: }
                   2436: 
                   2437: static void expand_op_shl_cc(qOP *qop)
                   2438: {
                   2439:     expand_shift_reg(qop, 0, 0);
                   2440: }
                   2441: 
                   2442: static void expand_op_shr_cc(qOP *qop)
                   2443: {
                   2444:     expand_shift_reg(qop, 1, 0);
                   2445: }
                   2446: 
                   2447: static void expand_op_sar_cc(qOP *qop)
                   2448: {
                   2449:     expand_shift_reg(qop, 1, 1);
                   2450: }
                   2451: 
                   2452: /* Set the Z flag to (arg0 & arg1) == 0.  */
                   2453: static void expand_op_btest(qOP *qop)
                   2454: {
                   2455:     int tmp;
                   2456:     int l1;
                   2457: 
                   2458:     l1 = gen_new_label();
                   2459:     tmp = gen_new_qreg(QMODE_I32);
                   2460:     gen_op_and32(tmp, qop->args[0], qop->args[1]);
                   2461:     gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
                   2462:     gen_op_jmp_nz32(tmp, l1);
                   2463:     gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
                   2464:     gen_op_label(l1);
                   2465: }
                   2466: 
                   2467: /* arg0 += arg1 + CC_X */
                   2468: static void expand_op_addx_cc(qOP *qop)
                   2469: {
                   2470:     int arg0 = qop->args[0];
                   2471:     int arg1 = qop->args[1];
                   2472:     int l1, l2;
                   2473:     
                   2474:     gen_op_add32 (arg0, arg0, arg1);
                   2475:     l1 = gen_new_label();
                   2476:     l2 = gen_new_label();
                   2477:     gen_op_jmp_z32(QREG_CC_X, l1);
                   2478:     gen_op_add32(arg0, arg0, gen_im32(1));
                   2479:     gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
                   2480:     gen_op_set_leu32(QREG_CC_X, arg0, arg1);
                   2481:     gen_op_jmp(l2);
                   2482:     gen_set_label(l1);
                   2483:     gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
                   2484:     gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
                   2485:     gen_set_label(l2);
                   2486: }
                   2487: 
                   2488: /* arg0 -= arg1 + CC_X */
                   2489: static void expand_op_subx_cc(qOP *qop)
                   2490: {
                   2491:     int arg0 = qop->args[0];
                   2492:     int arg1 = qop->args[1];
                   2493:     int l1, l2;
                   2494: 
                   2495:     l1 = gen_new_label();
                   2496:     l2 = gen_new_label();
                   2497:     gen_op_jmp_z32(QREG_CC_X, l1);
                   2498:     gen_op_set_leu32(QREG_CC_X, arg0, arg1);
                   2499:     gen_op_sub32(arg0, arg0, gen_im32(1));
                   2500:     gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
                   2501:     gen_op_jmp(l2);
                   2502:     gen_set_label(l1);
                   2503:     gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
                   2504:     gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
                   2505:     gen_set_label(l2);
                   2506:     gen_op_sub32 (arg0, arg0, arg1);
                   2507: }
                   2508: 
                   2509: /* Expand target specific ops to generic qops.  */
                   2510: static void expand_target_qops(void)
                   2511: {
                   2512:     qOP *qop;
                   2513:     qOP *next;
                   2514:     int c;
                   2515: 
                   2516:     /* Copy the list of qops, expanding target specific ops as we go.  */
                   2517:     qop = gen_first_qop;
                   2518:     gen_first_qop = NULL;
                   2519:     gen_last_qop = NULL;
                   2520:     for (; qop; qop = next) {
                   2521:         c = qop->opcode;
                   2522:         next = qop->next;
                   2523:         if (c < FIRST_TARGET_OP) {
                   2524:             qop->prev = gen_last_qop;
                   2525:             qop->next = NULL;
                   2526:             if (gen_last_qop)
                   2527:                 gen_last_qop->next = qop;
                   2528:             else
                   2529:                 gen_first_qop = qop;
                   2530:             gen_last_qop = qop;
                   2531:             continue;
                   2532:         }
                   2533:         switch (c) {
                   2534: #define DEF(name, nargs, barrier) \
                   2535:         case INDEX_op_##name: \
                   2536:             expand_op_##name(qop); \
                   2537:             break;
                   2538: #include "qop-target.def"
                   2539: #undef DEF
                   2540:         default:
                   2541:             cpu_abort(NULL, "Unexpanded target qop");
                   2542:         }
                   2543:     }
                   2544: }
                   2545: 
                   2546: /* ??? Implement this.  */
                   2547: static void
                   2548: optimize_flags(void)
                   2549: {
                   2550: }
                   2551: #endif
                   2552: 
                   2553: /* generate intermediate code for basic block 'tb'.  */
                   2554: int gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
                   2555:                                    int search_pc)
                   2556: {
                   2557:     DisasContext dc1, *dc = &dc1;
                   2558:     uint16_t *gen_opc_end;
                   2559:     int j, lj;
                   2560:     target_ulong pc_start;
                   2561:     int pc_offset;
                   2562:     int last_cc_op;
                   2563: 
                   2564:     /* generate intermediate code */
                   2565:     pc_start = tb->pc;
                   2566:        
                   2567:     dc->tb = tb;
                   2568: 
                   2569:     gen_opc_ptr = gen_opc_buf;
                   2570:     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
                   2571:     gen_opparam_ptr = gen_opparam_buf;
                   2572: 
                   2573:     dc->is_jmp = DISAS_NEXT;
                   2574:     dc->pc = pc_start;
                   2575:     dc->cc_op = CC_OP_DYNAMIC;
                   2576:     dc->singlestep_enabled = env->singlestep_enabled;
                   2577:     dc->fpcr = env->fpcr;
                   2578:     nb_gen_labels = 0;
                   2579:     lj = -1;
                   2580:     do {
                   2581:         free_qreg = 0;
                   2582:         pc_offset = dc->pc - pc_start;
                   2583:         gen_throws_exception = NULL;
                   2584:         if (env->nb_breakpoints > 0) {
                   2585:             for(j = 0; j < env->nb_breakpoints; j++) {
                   2586:                 if (env->breakpoints[j] == dc->pc) {
                   2587:                     gen_exception(dc, dc->pc, EXCP_DEBUG);
                   2588:                     dc->is_jmp = DISAS_JUMP;
                   2589:                     break;
                   2590:                 }
                   2591:             }
                   2592:             if (dc->is_jmp)
                   2593:                 break;
                   2594:         }
                   2595:         if (search_pc) {
                   2596:             j = gen_opc_ptr - gen_opc_buf;
                   2597:             if (lj < j) {
                   2598:                 lj++;
                   2599:                 while (lj < j)
                   2600:                     gen_opc_instr_start[lj++] = 0;
                   2601:             }
                   2602:             gen_opc_pc[lj] = dc->pc;
                   2603:             gen_opc_instr_start[lj] = 1;
                   2604:         }
                   2605:         last_cc_op = dc->cc_op;
                   2606:        disas_m68k_insn(env, dc);
                   2607:     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
                   2608:              !env->singlestep_enabled &&
                   2609:              (pc_offset) < (TARGET_PAGE_SIZE - 32));
                   2610: 
                   2611:     if (__builtin_expect(env->singlestep_enabled, 0)) {
                   2612:         /* Make sure the pc is updated, and raise a debug exception.  */
                   2613:         if (!dc->is_jmp) {
                   2614:             gen_flush_cc_op(dc);
                   2615:             gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
                   2616:         }
                   2617:         gen_op_raise_exception(EXCP_DEBUG);
                   2618:     } else {
                   2619:         switch(dc->is_jmp) {
                   2620:         case DISAS_NEXT:
                   2621:             gen_flush_cc_op(dc);
                   2622:             gen_jmp_tb(dc, 0, dc->pc);
                   2623:             break;
                   2624:         default:
                   2625:         case DISAS_JUMP:
                   2626:         case DISAS_UPDATE:
                   2627:             gen_flush_cc_op(dc);
                   2628:             /* indicate that the hash table must be used to find the next TB */
                   2629:             gen_op_mov32(QREG_T0, gen_im32(0));
                   2630:             gen_op_exit_tb();
                   2631:             break;
                   2632:         case DISAS_TB_JUMP:
                   2633:             /* nothing more to generate */
                   2634:             break;
                   2635:         }
                   2636:     }
                   2637:     *gen_opc_ptr = INDEX_op_end;
                   2638: 
                   2639: #ifdef DEBUG_DISAS
                   2640:     if (loglevel & CPU_LOG_TB_IN_ASM) {
                   2641:         fprintf(logfile, "----------------\n");
                   2642:         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
                   2643:         target_disas(logfile, pc_start, dc->pc - pc_start, 0);
                   2644:         fprintf(logfile, "\n");
                   2645:         if (loglevel & (CPU_LOG_TB_OP)) {
                   2646:             fprintf(logfile, "OP:\n");
                   2647:             dump_ops(gen_opc_buf, gen_opparam_buf);
                   2648:             fprintf(logfile, "\n");
                   2649:         }
                   2650:     }
                   2651: #endif
                   2652:     if (search_pc) {
                   2653:         j = gen_opc_ptr - gen_opc_buf;
                   2654:         lj++;
                   2655:         while (lj <= j)
                   2656:             gen_opc_instr_start[lj++] = 0;
                   2657:         tb->size = 0;
                   2658:     } else {
                   2659:         tb->size = dc->pc - pc_start;
                   2660:     }
                   2661: 
                   2662:     //optimize_flags();
                   2663:     //expand_target_qops();
                   2664:     return 0;
                   2665: }
                   2666: 
                   2667: int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
                   2668: {
                   2669:     return gen_intermediate_code_internal(env, tb, 0);
                   2670: }
                   2671: 
                   2672: int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
                   2673: {
                   2674:     return gen_intermediate_code_internal(env, tb, 1);
                   2675: }
                   2676: 
                   2677: CPUM68KState *cpu_m68k_init(void)
                   2678: {
                   2679:     CPUM68KState *env;
                   2680: 
                   2681:     env = malloc(sizeof(CPUM68KState));
                   2682:     if (!env)
                   2683:         return NULL;
                   2684:     cpu_exec_init(env);
                   2685: 
                   2686:     memset(env, 0, sizeof(CPUM68KState));
                   2687:     /* ??? FP regs should be initialized to NaN.  */
                   2688:     cpu_single_env = env;
                   2689:     env->cc_op = CC_OP_FLAGS;
                   2690:     return env;
                   2691: }
                   2692: 
                   2693: void cpu_m68k_close(CPUM68KState *env)
                   2694: {
                   2695:     free(env);
                   2696: }
                   2697: 
                   2698: m68k_def_t *m68k_find_by_name(const char *name)
                   2699: {
                   2700:     m68k_def_t *def;
                   2701: 
                   2702:     def = m68k_cpu_defs;
                   2703:     while (def->name)
                   2704:       {
                   2705:         if (strcmp(def->name, name) == 0)
                   2706:             return def;
                   2707:         def++;
                   2708:       }
                   2709:     return NULL;
                   2710: }
                   2711: 
                   2712: void cpu_m68k_register(CPUM68KState *env, m68k_def_t *def)
                   2713: {
                   2714:     register_m68k_insns(def);
                   2715: }
                   2716: 
                   2717: void cpu_dump_state(CPUState *env, FILE *f, 
                   2718:                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
                   2719:                     int flags)
                   2720: {
                   2721:     int i;
                   2722:     uint16_t sr;
                   2723:     CPU_DoubleU u;
                   2724:     for (i = 0; i < 8; i++)
                   2725:       {
                   2726:         u.d = env->fregs[i];
                   2727:         cpu_fprintf (f, "D%d = %08x   A%d = %08x   F%d = %08x%08x (%12g)\n",
                   2728:                      i, env->dregs[i], i, env->aregs[i],
                   2729:                      i, u.l.upper, u.l.lower, u.d);
                   2730:       }
                   2731:     cpu_fprintf (f, "PC = %08x   ", env->pc);
                   2732:     sr = env->sr;
                   2733:     cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
                   2734:                  (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
                   2735:                  (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
                   2736:     cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
                   2737: }
                   2738: 
                   2739: /* ??? */
                   2740: target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
                   2741: {
                   2742:     return addr;
                   2743: }
                   2744: 
                   2745: #if defined(CONFIG_USER_ONLY) 
                   2746: 
                   2747: int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                   2748:                                int is_user, int is_softmmu)
                   2749: {
                   2750:     env->exception_index = EXCP_ACCESS;
                   2751:     env->mmu.ar = address;
                   2752:     return 1;
                   2753: }
                   2754: 
                   2755: #else
                   2756: 
                   2757: #error not implemented
                   2758: 
                   2759: #endif

unix.superglobalmegacorp.com

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