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

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

unix.superglobalmegacorp.com

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