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