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

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

unix.superglobalmegacorp.com

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