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

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

unix.superglobalmegacorp.com

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