xref: /openbmc/qemu/target/m68k/translate.c (revision b71fd73c)
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.1 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  * Lesser 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, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "disas/disas.h"
24 #include "exec/exec-all.h"
25 #include "tcg/tcg-op.h"
26 #include "qemu/log.h"
27 #include "qemu/qemu-print.h"
28 #include "exec/cpu_ldst.h"
29 #include "exec/translator.h"
30 
31 #include "exec/helper-proto.h"
32 #include "exec/helper-gen.h"
33 
34 #include "exec/log.h"
35 #include "fpu/softfloat.h"
36 
37 
38 //#define DEBUG_DISPATCH 1
39 
40 #define DEFO32(name, offset) static TCGv QREG_##name;
41 #define DEFO64(name, offset) static TCGv_i64 QREG_##name;
42 #include "qregs.h.inc"
43 #undef DEFO32
44 #undef DEFO64
45 
46 static TCGv_i32 cpu_halted;
47 static TCGv_i32 cpu_exception_index;
48 
49 static char cpu_reg_names[2 * 8 * 3 + 5 * 4];
50 static TCGv cpu_dregs[8];
51 static TCGv cpu_aregs[8];
52 static TCGv_i64 cpu_macc[4];
53 
54 #define REG(insn, pos)  (((insn) >> (pos)) & 7)
55 #define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
56 #define AREG(insn, pos) get_areg(s, REG(insn, pos))
57 #define MACREG(acc)     cpu_macc[acc]
58 #define QREG_SP         get_areg(s, 7)
59 
60 static TCGv NULL_QREG;
61 #define IS_NULL_QREG(t) (t == NULL_QREG)
62 /* Used to distinguish stores from bad addressing modes.  */
63 static TCGv store_dummy;
64 
65 #include "exec/gen-icount.h"
66 
67 void m68k_tcg_init(void)
68 {
69     char *p;
70     int i;
71 
72 #define DEFO32(name, offset) \
73     QREG_##name = tcg_global_mem_new_i32(cpu_env, \
74         offsetof(CPUM68KState, offset), #name);
75 #define DEFO64(name, offset) \
76     QREG_##name = tcg_global_mem_new_i64(cpu_env, \
77         offsetof(CPUM68KState, offset), #name);
78 #include "qregs.h.inc"
79 #undef DEFO32
80 #undef DEFO64
81 
82     cpu_halted = tcg_global_mem_new_i32(cpu_env,
83                                         -offsetof(M68kCPU, env) +
84                                         offsetof(CPUState, halted), "HALTED");
85     cpu_exception_index = tcg_global_mem_new_i32(cpu_env,
86                                                  -offsetof(M68kCPU, env) +
87                                                  offsetof(CPUState, exception_index),
88                                                  "EXCEPTION");
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(cpu_env,
94                                           offsetof(CPUM68KState, dregs[i]), p);
95         p += 3;
96         sprintf(p, "A%d", i);
97         cpu_aregs[i] = tcg_global_mem_new(cpu_env,
98                                           offsetof(CPUM68KState, aregs[i]), p);
99         p += 3;
100     }
101     for (i = 0; i < 4; i++) {
102         sprintf(p, "ACC%d", i);
103         cpu_macc[i] = tcg_global_mem_new_i64(cpu_env,
104                                          offsetof(CPUM68KState, macc[i]), p);
105         p += 5;
106     }
107 
108     NULL_QREG = tcg_global_mem_new(cpu_env, -4, "NULL");
109     store_dummy = tcg_global_mem_new(cpu_env, -8, "NULL");
110 }
111 
112 /* internal defines */
113 typedef struct DisasContext {
114     DisasContextBase base;
115     CPUM68KState *env;
116     target_ulong pc;
117     target_ulong pc_prev;
118     CCOp cc_op; /* Current CC operation */
119     int cc_op_synced;
120     TCGv_i64 mactmp;
121     int done_mac;
122     int writeback_mask;
123     TCGv writeback[8];
124     bool ss_active;
125 } DisasContext;
126 
127 static TCGv get_areg(DisasContext *s, unsigned regno)
128 {
129     if (s->writeback_mask & (1 << regno)) {
130         return s->writeback[regno];
131     } else {
132         return cpu_aregs[regno];
133     }
134 }
135 
136 static void delay_set_areg(DisasContext *s, unsigned regno,
137                            TCGv val, bool give_temp)
138 {
139     if (s->writeback_mask & (1 << regno)) {
140         if (give_temp) {
141             s->writeback[regno] = val;
142         } else {
143             tcg_gen_mov_i32(s->writeback[regno], val);
144         }
145     } else {
146         s->writeback_mask |= 1 << regno;
147         if (give_temp) {
148             s->writeback[regno] = val;
149         } else {
150             TCGv tmp = tcg_temp_new();
151             s->writeback[regno] = tmp;
152             tcg_gen_mov_i32(tmp, val);
153         }
154     }
155 }
156 
157 static void do_writebacks(DisasContext *s)
158 {
159     unsigned mask = s->writeback_mask;
160     if (mask) {
161         s->writeback_mask = 0;
162         do {
163             unsigned regno = ctz32(mask);
164             tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]);
165             mask &= mask - 1;
166         } while (mask);
167     }
168 }
169 
170 /* is_jmp field values */
171 #define DISAS_JUMP      DISAS_TARGET_0 /* only pc was modified dynamically */
172 #define DISAS_EXIT      DISAS_TARGET_1 /* cpu state was modified dynamically */
173 
174 #if defined(CONFIG_USER_ONLY)
175 #define IS_USER(s) 1
176 #else
177 #define IS_USER(s)   (!(s->base.tb->flags & TB_FLAGS_MSR_S))
178 #define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \
179                       MMU_KERNEL_IDX : MMU_USER_IDX)
180 #define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \
181                       MMU_KERNEL_IDX : MMU_USER_IDX)
182 #endif
183 
184 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
185 
186 #ifdef DEBUG_DISPATCH
187 #define DISAS_INSN(name)                                                \
188     static void real_disas_##name(CPUM68KState *env, DisasContext *s,   \
189                                   uint16_t insn);                       \
190     static void disas_##name(CPUM68KState *env, DisasContext *s,        \
191                              uint16_t insn)                             \
192     {                                                                   \
193         qemu_log("Dispatch " #name "\n");                               \
194         real_disas_##name(env, s, insn);                                \
195     }                                                                   \
196     static void real_disas_##name(CPUM68KState *env, DisasContext *s,   \
197                                   uint16_t insn)
198 #else
199 #define DISAS_INSN(name)                                                \
200     static void disas_##name(CPUM68KState *env, DisasContext *s,        \
201                              uint16_t insn)
202 #endif
203 
204 static const uint8_t cc_op_live[CC_OP_NB] = {
205     [CC_OP_DYNAMIC] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
206     [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
207     [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V,
208     [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V,
209     [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V,
210     [CC_OP_LOGIC] = CCF_X | CCF_N
211 };
212 
213 static void set_cc_op(DisasContext *s, CCOp op)
214 {
215     CCOp old_op = s->cc_op;
216     int dead;
217 
218     if (old_op == op) {
219         return;
220     }
221     s->cc_op = op;
222     s->cc_op_synced = 0;
223 
224     /*
225      * Discard CC computation that will no longer be used.
226      * Note that X and N are never dead.
227      */
228     dead = cc_op_live[old_op] & ~cc_op_live[op];
229     if (dead & CCF_C) {
230         tcg_gen_discard_i32(QREG_CC_C);
231     }
232     if (dead & CCF_Z) {
233         tcg_gen_discard_i32(QREG_CC_Z);
234     }
235     if (dead & CCF_V) {
236         tcg_gen_discard_i32(QREG_CC_V);
237     }
238 }
239 
240 /* Update the CPU env CC_OP state.  */
241 static void update_cc_op(DisasContext *s)
242 {
243     if (!s->cc_op_synced) {
244         s->cc_op_synced = 1;
245         tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
246     }
247 }
248 
249 /* Generate a jump to an immediate address.  */
250 static void gen_jmp_im(DisasContext *s, uint32_t dest)
251 {
252     update_cc_op(s);
253     tcg_gen_movi_i32(QREG_PC, dest);
254     s->base.is_jmp = DISAS_JUMP;
255 }
256 
257 /* Generate a jump to the address in qreg DEST.  */
258 static void gen_jmp(DisasContext *s, TCGv dest)
259 {
260     update_cc_op(s);
261     tcg_gen_mov_i32(QREG_PC, dest);
262     s->base.is_jmp = DISAS_JUMP;
263 }
264 
265 static void gen_raise_exception(int nr)
266 {
267     gen_helper_raise_exception(cpu_env, tcg_constant_i32(nr));
268 }
269 
270 static void gen_raise_exception_format2(DisasContext *s, int nr,
271                                         target_ulong this_pc)
272 {
273     /*
274      * Pass the address of the insn to the exception handler,
275      * for recording in the Format $2 (6-word) stack frame.
276      * Re-use mmu.ar for the purpose, since that's only valid
277      * after tlb_fill.
278      */
279     tcg_gen_st_i32(tcg_constant_i32(this_pc), cpu_env,
280                    offsetof(CPUM68KState, mmu.ar));
281     gen_raise_exception(nr);
282     s->base.is_jmp = DISAS_NORETURN;
283 }
284 
285 static void gen_exception(DisasContext *s, uint32_t dest, int nr)
286 {
287     update_cc_op(s);
288     tcg_gen_movi_i32(QREG_PC, dest);
289 
290     gen_raise_exception(nr);
291 
292     s->base.is_jmp = DISAS_NORETURN;
293 }
294 
295 static inline void gen_addr_fault(DisasContext *s)
296 {
297     gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
298 }
299 
300 /*
301  * Generate a load from the specified address.  Narrow values are
302  *  sign extended to full register width.
303  */
304 static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
305                             int sign, int index)
306 {
307     TCGv tmp = tcg_temp_new_i32();
308 
309     switch (opsize) {
310     case OS_BYTE:
311     case OS_WORD:
312     case OS_LONG:
313         tcg_gen_qemu_ld_tl(tmp, addr, index,
314                            opsize | (sign ? MO_SIGN : 0) | MO_TE);
315         break;
316     default:
317         g_assert_not_reached();
318     }
319     return tmp;
320 }
321 
322 /* Generate a store.  */
323 static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val,
324                              int index)
325 {
326     switch (opsize) {
327     case OS_BYTE:
328     case OS_WORD:
329     case OS_LONG:
330         tcg_gen_qemu_st_tl(val, addr, index, opsize | MO_TE);
331         break;
332     default:
333         g_assert_not_reached();
334     }
335 }
336 
337 typedef enum {
338     EA_STORE,
339     EA_LOADU,
340     EA_LOADS
341 } ea_what;
342 
343 /*
344  * Generate an unsigned load if VAL is 0 a signed load if val is -1,
345  * otherwise generate a store.
346  */
347 static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
348                      ea_what what, int index)
349 {
350     if (what == EA_STORE) {
351         gen_store(s, opsize, addr, val, index);
352         return store_dummy;
353     } else {
354         return gen_load(s, opsize, addr, what == EA_LOADS, index);
355     }
356 }
357 
358 /* Read a 16-bit immediate constant */
359 static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
360 {
361     uint16_t im;
362     im = translator_lduw(env, &s->base, s->pc);
363     s->pc += 2;
364     return im;
365 }
366 
367 /* Read an 8-bit immediate constant */
368 static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
369 {
370     return read_im16(env, s);
371 }
372 
373 /* Read a 32-bit immediate constant.  */
374 static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
375 {
376     uint32_t im;
377     im = read_im16(env, s) << 16;
378     im |= 0xffff & read_im16(env, s);
379     return im;
380 }
381 
382 /* Read a 64-bit immediate constant.  */
383 static inline uint64_t read_im64(CPUM68KState *env, DisasContext *s)
384 {
385     uint64_t im;
386     im = (uint64_t)read_im32(env, s) << 32;
387     im |= (uint64_t)read_im32(env, s);
388     return im;
389 }
390 
391 /* Calculate and address index.  */
392 static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp)
393 {
394     TCGv add;
395     int scale;
396 
397     add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
398     if ((ext & 0x800) == 0) {
399         tcg_gen_ext16s_i32(tmp, add);
400         add = tmp;
401     }
402     scale = (ext >> 9) & 3;
403     if (scale != 0) {
404         tcg_gen_shli_i32(tmp, add, scale);
405         add = tmp;
406     }
407     return add;
408 }
409 
410 /*
411  * Handle a base + index + displacement effective address.
412  * A NULL_QREG base means pc-relative.
413  */
414 static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
415 {
416     uint32_t offset;
417     uint16_t ext;
418     TCGv add;
419     TCGv tmp;
420     uint32_t bd, od;
421 
422     offset = s->pc;
423     ext = read_im16(env, s);
424 
425     if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
426         return NULL_QREG;
427 
428     if (m68k_feature(s->env, M68K_FEATURE_M68K) &&
429         !m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) {
430         ext &= ~(3 << 9);
431     }
432 
433     if (ext & 0x100) {
434         /* full extension word format */
435         if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
436             return NULL_QREG;
437 
438         if ((ext & 0x30) > 0x10) {
439             /* base displacement */
440             if ((ext & 0x30) == 0x20) {
441                 bd = (int16_t)read_im16(env, s);
442             } else {
443                 bd = read_im32(env, s);
444             }
445         } else {
446             bd = 0;
447         }
448         tmp = tcg_temp_new();
449         if ((ext & 0x44) == 0) {
450             /* pre-index */
451             add = gen_addr_index(s, ext, tmp);
452         } else {
453             add = NULL_QREG;
454         }
455         if ((ext & 0x80) == 0) {
456             /* base not suppressed */
457             if (IS_NULL_QREG(base)) {
458                 base = tcg_constant_i32(offset + bd);
459                 bd = 0;
460             }
461             if (!IS_NULL_QREG(add)) {
462                 tcg_gen_add_i32(tmp, add, base);
463                 add = tmp;
464             } else {
465                 add = base;
466             }
467         }
468         if (!IS_NULL_QREG(add)) {
469             if (bd != 0) {
470                 tcg_gen_addi_i32(tmp, add, bd);
471                 add = tmp;
472             }
473         } else {
474             add = tcg_constant_i32(bd);
475         }
476         if ((ext & 3) != 0) {
477             /* memory indirect */
478             base = gen_load(s, OS_LONG, add, 0, IS_USER(s));
479             if ((ext & 0x44) == 4) {
480                 add = gen_addr_index(s, ext, tmp);
481                 tcg_gen_add_i32(tmp, add, base);
482                 add = tmp;
483             } else {
484                 add = base;
485             }
486             if ((ext & 3) > 1) {
487                 /* outer displacement */
488                 if ((ext & 3) == 2) {
489                     od = (int16_t)read_im16(env, s);
490                 } else {
491                     od = read_im32(env, s);
492                 }
493             } else {
494                 od = 0;
495             }
496             if (od != 0) {
497                 tcg_gen_addi_i32(tmp, add, od);
498                 add = tmp;
499             }
500         }
501     } else {
502         /* brief extension word format */
503         tmp = tcg_temp_new();
504         add = gen_addr_index(s, ext, tmp);
505         if (!IS_NULL_QREG(base)) {
506             tcg_gen_add_i32(tmp, add, base);
507             if ((int8_t)ext)
508                 tcg_gen_addi_i32(tmp, tmp, (int8_t)ext);
509         } else {
510             tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext);
511         }
512         add = tmp;
513     }
514     return add;
515 }
516 
517 /* Sign or zero extend a value.  */
518 
519 static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
520 {
521     switch (opsize) {
522     case OS_BYTE:
523         if (sign) {
524             tcg_gen_ext8s_i32(res, val);
525         } else {
526             tcg_gen_ext8u_i32(res, val);
527         }
528         break;
529     case OS_WORD:
530         if (sign) {
531             tcg_gen_ext16s_i32(res, val);
532         } else {
533             tcg_gen_ext16u_i32(res, val);
534         }
535         break;
536     case OS_LONG:
537         tcg_gen_mov_i32(res, val);
538         break;
539     default:
540         g_assert_not_reached();
541     }
542 }
543 
544 /* Evaluate all the CC flags.  */
545 
546 static void gen_flush_flags(DisasContext *s)
547 {
548     TCGv t0, t1;
549 
550     switch (s->cc_op) {
551     case CC_OP_FLAGS:
552         return;
553 
554     case CC_OP_ADDB:
555     case CC_OP_ADDW:
556     case CC_OP_ADDL:
557         tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
558         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
559         /* Compute signed overflow for addition.  */
560         t0 = tcg_temp_new();
561         t1 = tcg_temp_new();
562         tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
563         gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1);
564         tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
565         tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
566         tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V);
567         break;
568 
569     case CC_OP_SUBB:
570     case CC_OP_SUBW:
571     case CC_OP_SUBL:
572         tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
573         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
574         /* Compute signed overflow for subtraction.  */
575         t0 = tcg_temp_new();
576         t1 = tcg_temp_new();
577         tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
578         gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1);
579         tcg_gen_xor_i32(t1, QREG_CC_N, t0);
580         tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
581         tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
582         break;
583 
584     case CC_OP_CMPB:
585     case CC_OP_CMPW:
586     case CC_OP_CMPL:
587         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
588         tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
589         gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1);
590         /* Compute signed overflow for subtraction.  */
591         t0 = tcg_temp_new();
592         tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
593         tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N);
594         tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0);
595         tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z);
596         break;
597 
598     case CC_OP_LOGIC:
599         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
600         tcg_gen_movi_i32(QREG_CC_C, 0);
601         tcg_gen_movi_i32(QREG_CC_V, 0);
602         break;
603 
604     case CC_OP_DYNAMIC:
605         gen_helper_flush_flags(cpu_env, QREG_CC_OP);
606         s->cc_op_synced = 1;
607         break;
608 
609     default:
610         gen_helper_flush_flags(cpu_env, tcg_constant_i32(s->cc_op));
611         s->cc_op_synced = 1;
612         break;
613     }
614 
615     /* Note that flush_flags also assigned to env->cc_op.  */
616     s->cc_op = CC_OP_FLAGS;
617 }
618 
619 static inline TCGv gen_extend(DisasContext *s, TCGv val, int opsize, int sign)
620 {
621     TCGv tmp;
622 
623     if (opsize == OS_LONG) {
624         tmp = val;
625     } else {
626         tmp = tcg_temp_new();
627         gen_ext(tmp, val, opsize, sign);
628     }
629 
630     return tmp;
631 }
632 
633 static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
634 {
635     gen_ext(QREG_CC_N, val, opsize, 1);
636     set_cc_op(s, CC_OP_LOGIC);
637 }
638 
639 static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize)
640 {
641     tcg_gen_mov_i32(QREG_CC_N, dest);
642     tcg_gen_mov_i32(QREG_CC_V, src);
643     set_cc_op(s, CC_OP_CMPB + opsize);
644 }
645 
646 static void gen_update_cc_add(TCGv dest, TCGv src, int opsize)
647 {
648     gen_ext(QREG_CC_N, dest, opsize, 1);
649     tcg_gen_mov_i32(QREG_CC_V, src);
650 }
651 
652 static inline int opsize_bytes(int opsize)
653 {
654     switch (opsize) {
655     case OS_BYTE: return 1;
656     case OS_WORD: return 2;
657     case OS_LONG: return 4;
658     case OS_SINGLE: return 4;
659     case OS_DOUBLE: return 8;
660     case OS_EXTENDED: return 12;
661     case OS_PACKED: return 12;
662     default:
663         g_assert_not_reached();
664     }
665 }
666 
667 static inline int insn_opsize(int insn)
668 {
669     switch ((insn >> 6) & 3) {
670     case 0: return OS_BYTE;
671     case 1: return OS_WORD;
672     case 2: return OS_LONG;
673     default:
674         g_assert_not_reached();
675     }
676 }
677 
678 static inline int ext_opsize(int ext, int pos)
679 {
680     switch ((ext >> pos) & 7) {
681     case 0: return OS_LONG;
682     case 1: return OS_SINGLE;
683     case 2: return OS_EXTENDED;
684     case 3: return OS_PACKED;
685     case 4: return OS_WORD;
686     case 5: return OS_DOUBLE;
687     case 6: return OS_BYTE;
688     default:
689         g_assert_not_reached();
690     }
691 }
692 
693 /*
694  * Assign value to a register.  If the width is less than the register width
695  * only the low part of the register is set.
696  */
697 static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
698 {
699     TCGv tmp;
700     switch (opsize) {
701     case OS_BYTE:
702         tcg_gen_andi_i32(reg, reg, 0xffffff00);
703         tmp = tcg_temp_new();
704         tcg_gen_ext8u_i32(tmp, val);
705         tcg_gen_or_i32(reg, reg, tmp);
706         break;
707     case OS_WORD:
708         tcg_gen_andi_i32(reg, reg, 0xffff0000);
709         tmp = tcg_temp_new();
710         tcg_gen_ext16u_i32(tmp, val);
711         tcg_gen_or_i32(reg, reg, tmp);
712         break;
713     case OS_LONG:
714     case OS_SINGLE:
715         tcg_gen_mov_i32(reg, val);
716         break;
717     default:
718         g_assert_not_reached();
719     }
720 }
721 
722 /*
723  * Generate code for an "effective address".  Does not adjust the base
724  * register for autoincrement addressing modes.
725  */
726 static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
727                          int mode, int reg0, int opsize)
728 {
729     TCGv reg;
730     TCGv tmp;
731     uint16_t ext;
732     uint32_t offset;
733 
734     switch (mode) {
735     case 0: /* Data register direct.  */
736     case 1: /* Address register direct.  */
737         return NULL_QREG;
738     case 3: /* Indirect postincrement.  */
739         if (opsize == OS_UNSIZED) {
740             return NULL_QREG;
741         }
742         /* fallthru */
743     case 2: /* Indirect register */
744         return get_areg(s, reg0);
745     case 4: /* Indirect predecrememnt.  */
746         if (opsize == OS_UNSIZED) {
747             return NULL_QREG;
748         }
749         reg = get_areg(s, reg0);
750         tmp = tcg_temp_new();
751         if (reg0 == 7 && opsize == OS_BYTE &&
752             m68k_feature(s->env, M68K_FEATURE_M68K)) {
753             tcg_gen_subi_i32(tmp, reg, 2);
754         } else {
755             tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
756         }
757         return tmp;
758     case 5: /* Indirect displacement.  */
759         reg = get_areg(s, reg0);
760         tmp = tcg_temp_new();
761         ext = read_im16(env, s);
762         tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
763         return tmp;
764     case 6: /* Indirect index + displacement.  */
765         reg = get_areg(s, reg0);
766         return gen_lea_indexed(env, s, reg);
767     case 7: /* Other */
768         switch (reg0) {
769         case 0: /* Absolute short.  */
770             offset = (int16_t)read_im16(env, s);
771             return tcg_constant_i32(offset);
772         case 1: /* Absolute long.  */
773             offset = read_im32(env, s);
774             return tcg_constant_i32(offset);
775         case 2: /* pc displacement  */
776             offset = s->pc;
777             offset += (int16_t)read_im16(env, s);
778             return tcg_constant_i32(offset);
779         case 3: /* pc index+displacement.  */
780             return gen_lea_indexed(env, s, NULL_QREG);
781         case 4: /* Immediate.  */
782         default:
783             return NULL_QREG;
784         }
785     }
786     /* Should never happen.  */
787     return NULL_QREG;
788 }
789 
790 static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
791                     int opsize)
792 {
793     int mode = extract32(insn, 3, 3);
794     int reg0 = REG(insn, 0);
795     return gen_lea_mode(env, s, mode, reg0, opsize);
796 }
797 
798 /*
799  * Generate code to load/store a value from/into an EA.  If WHAT > 0 this is
800  * a write otherwise it is a read (0 == sign extend, -1 == zero extend).
801  * ADDRP is non-null for readwrite operands.
802  */
803 static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
804                         int opsize, TCGv val, TCGv *addrp, ea_what what,
805                         int index)
806 {
807     TCGv reg, tmp, result;
808     int32_t offset;
809 
810     switch (mode) {
811     case 0: /* Data register direct.  */
812         reg = cpu_dregs[reg0];
813         if (what == EA_STORE) {
814             gen_partset_reg(opsize, reg, val);
815             return store_dummy;
816         } else {
817             return gen_extend(s, reg, opsize, what == EA_LOADS);
818         }
819     case 1: /* Address register direct.  */
820         reg = get_areg(s, reg0);
821         if (what == EA_STORE) {
822             tcg_gen_mov_i32(reg, val);
823             return store_dummy;
824         } else {
825             return gen_extend(s, reg, opsize, what == EA_LOADS);
826         }
827     case 2: /* Indirect register */
828         reg = get_areg(s, reg0);
829         return gen_ldst(s, opsize, reg, val, what, index);
830     case 3: /* Indirect postincrement.  */
831         reg = get_areg(s, reg0);
832         result = gen_ldst(s, opsize, reg, val, what, index);
833         if (what == EA_STORE || !addrp) {
834             TCGv tmp = tcg_temp_new();
835             if (reg0 == 7 && opsize == OS_BYTE &&
836                 m68k_feature(s->env, M68K_FEATURE_M68K)) {
837                 tcg_gen_addi_i32(tmp, reg, 2);
838             } else {
839                 tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize));
840             }
841             delay_set_areg(s, reg0, tmp, true);
842         }
843         return result;
844     case 4: /* Indirect predecrememnt.  */
845         if (addrp && what == EA_STORE) {
846             tmp = *addrp;
847         } else {
848             tmp = gen_lea_mode(env, s, mode, reg0, opsize);
849             if (IS_NULL_QREG(tmp)) {
850                 return tmp;
851             }
852             if (addrp) {
853                 *addrp = tmp;
854             }
855         }
856         result = gen_ldst(s, opsize, tmp, val, what, index);
857         if (what == EA_STORE || !addrp) {
858             delay_set_areg(s, reg0, tmp, false);
859         }
860         return result;
861     case 5: /* Indirect displacement.  */
862     case 6: /* Indirect index + displacement.  */
863     do_indirect:
864         if (addrp && what == EA_STORE) {
865             tmp = *addrp;
866         } else {
867             tmp = gen_lea_mode(env, s, mode, reg0, opsize);
868             if (IS_NULL_QREG(tmp)) {
869                 return tmp;
870             }
871             if (addrp) {
872                 *addrp = tmp;
873             }
874         }
875         return gen_ldst(s, opsize, tmp, val, what, index);
876     case 7: /* Other */
877         switch (reg0) {
878         case 0: /* Absolute short.  */
879         case 1: /* Absolute long.  */
880         case 2: /* pc displacement  */
881         case 3: /* pc index+displacement.  */
882             goto do_indirect;
883         case 4: /* Immediate.  */
884             /* Sign extend values for consistency.  */
885             switch (opsize) {
886             case OS_BYTE:
887                 if (what == EA_LOADS) {
888                     offset = (int8_t)read_im8(env, s);
889                 } else {
890                     offset = read_im8(env, s);
891                 }
892                 break;
893             case OS_WORD:
894                 if (what == EA_LOADS) {
895                     offset = (int16_t)read_im16(env, s);
896                 } else {
897                     offset = read_im16(env, s);
898                 }
899                 break;
900             case OS_LONG:
901                 offset = read_im32(env, s);
902                 break;
903             default:
904                 g_assert_not_reached();
905             }
906             return tcg_constant_i32(offset);
907         default:
908             return NULL_QREG;
909         }
910     }
911     /* Should never happen.  */
912     return NULL_QREG;
913 }
914 
915 static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
916                    int opsize, TCGv val, TCGv *addrp, ea_what what, int index)
917 {
918     int mode = extract32(insn, 3, 3);
919     int reg0 = REG(insn, 0);
920     return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what, index);
921 }
922 
923 static TCGv_ptr gen_fp_ptr(int freg)
924 {
925     TCGv_ptr fp = tcg_temp_new_ptr();
926     tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fregs[freg]));
927     return fp;
928 }
929 
930 static TCGv_ptr gen_fp_result_ptr(void)
931 {
932     TCGv_ptr fp = tcg_temp_new_ptr();
933     tcg_gen_addi_ptr(fp, cpu_env, offsetof(CPUM68KState, fp_result));
934     return fp;
935 }
936 
937 static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src)
938 {
939     TCGv t32;
940     TCGv_i64 t64;
941 
942     t32 = tcg_temp_new();
943     tcg_gen_ld16u_i32(t32, src, offsetof(FPReg, l.upper));
944     tcg_gen_st16_i32(t32, dest, offsetof(FPReg, l.upper));
945 
946     t64 = tcg_temp_new_i64();
947     tcg_gen_ld_i64(t64, src, offsetof(FPReg, l.lower));
948     tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower));
949 }
950 
951 static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
952                         int index)
953 {
954     TCGv tmp;
955     TCGv_i64 t64;
956 
957     t64 = tcg_temp_new_i64();
958     tmp = tcg_temp_new();
959     switch (opsize) {
960     case OS_BYTE:
961     case OS_WORD:
962         tcg_gen_qemu_ld_tl(tmp, addr, index, opsize | MO_SIGN | MO_TE);
963         gen_helper_exts32(cpu_env, fp, tmp);
964         break;
965     case OS_SINGLE:
966         tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL);
967         gen_helper_extf32(cpu_env, fp, tmp);
968         break;
969     case OS_DOUBLE:
970         tcg_gen_qemu_ld_i64(t64, addr, index, MO_TEUQ);
971         gen_helper_extf64(cpu_env, fp, t64);
972         break;
973     case OS_EXTENDED:
974         if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
975             gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
976             break;
977         }
978         tcg_gen_qemu_ld_i32(tmp, addr, index, MO_TEUL);
979         tcg_gen_shri_i32(tmp, tmp, 16);
980         tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
981         tcg_gen_addi_i32(tmp, addr, 4);
982         tcg_gen_qemu_ld_i64(t64, tmp, index, MO_TEUQ);
983         tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
984         break;
985     case OS_PACKED:
986         /*
987          * unimplemented data type on 68040/ColdFire
988          * FIXME if needed for another FPU
989          */
990         gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
991         break;
992     default:
993         g_assert_not_reached();
994     }
995 }
996 
997 static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
998                          int index)
999 {
1000     TCGv tmp;
1001     TCGv_i64 t64;
1002 
1003     t64 = tcg_temp_new_i64();
1004     tmp = tcg_temp_new();
1005     switch (opsize) {
1006     case OS_BYTE:
1007     case OS_WORD:
1008     case OS_LONG:
1009         gen_helper_reds32(tmp, cpu_env, fp);
1010         tcg_gen_qemu_st_tl(tmp, addr, index, opsize | MO_TE);
1011         break;
1012     case OS_SINGLE:
1013         gen_helper_redf32(tmp, cpu_env, fp);
1014         tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
1015         break;
1016     case OS_DOUBLE:
1017         gen_helper_redf64(t64, cpu_env, fp);
1018         tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ);
1019         break;
1020     case OS_EXTENDED:
1021         if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1022             gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1023             break;
1024         }
1025         tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
1026         tcg_gen_shli_i32(tmp, tmp, 16);
1027         tcg_gen_qemu_st_i32(tmp, addr, index, MO_TEUL);
1028         tcg_gen_addi_i32(tmp, addr, 4);
1029         tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower));
1030         tcg_gen_qemu_st_i64(t64, tmp, index, MO_TEUQ);
1031         break;
1032     case OS_PACKED:
1033         /*
1034          * unimplemented data type on 68040/ColdFire
1035          * FIXME if needed for another FPU
1036          */
1037         gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1038         break;
1039     default:
1040         g_assert_not_reached();
1041     }
1042 }
1043 
1044 static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr,
1045                         TCGv_ptr fp, ea_what what, int index)
1046 {
1047     if (what == EA_STORE) {
1048         gen_store_fp(s, opsize, addr, fp, index);
1049     } else {
1050         gen_load_fp(s, opsize, addr, fp, index);
1051     }
1052 }
1053 
1054 static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
1055                           int reg0, int opsize, TCGv_ptr fp, ea_what what,
1056                           int index)
1057 {
1058     TCGv reg, addr, tmp;
1059     TCGv_i64 t64;
1060 
1061     switch (mode) {
1062     case 0: /* Data register direct.  */
1063         reg = cpu_dregs[reg0];
1064         if (what == EA_STORE) {
1065             switch (opsize) {
1066             case OS_BYTE:
1067             case OS_WORD:
1068             case OS_LONG:
1069                 gen_helper_reds32(reg, cpu_env, fp);
1070                 break;
1071             case OS_SINGLE:
1072                 gen_helper_redf32(reg, cpu_env, fp);
1073                 break;
1074             default:
1075                 g_assert_not_reached();
1076             }
1077         } else {
1078             tmp = tcg_temp_new();
1079             switch (opsize) {
1080             case OS_BYTE:
1081                 tcg_gen_ext8s_i32(tmp, reg);
1082                 gen_helper_exts32(cpu_env, fp, tmp);
1083                 break;
1084             case OS_WORD:
1085                 tcg_gen_ext16s_i32(tmp, reg);
1086                 gen_helper_exts32(cpu_env, fp, tmp);
1087                 break;
1088             case OS_LONG:
1089                 gen_helper_exts32(cpu_env, fp, reg);
1090                 break;
1091             case OS_SINGLE:
1092                 gen_helper_extf32(cpu_env, fp, reg);
1093                 break;
1094             default:
1095                 g_assert_not_reached();
1096             }
1097         }
1098         return 0;
1099     case 1: /* Address register direct.  */
1100         return -1;
1101     case 2: /* Indirect register */
1102         addr = get_areg(s, reg0);
1103         gen_ldst_fp(s, opsize, addr, fp, what, index);
1104         return 0;
1105     case 3: /* Indirect postincrement.  */
1106         addr = cpu_aregs[reg0];
1107         gen_ldst_fp(s, opsize, addr, fp, what, index);
1108         tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize));
1109         return 0;
1110     case 4: /* Indirect predecrememnt.  */
1111         addr = gen_lea_mode(env, s, mode, reg0, opsize);
1112         if (IS_NULL_QREG(addr)) {
1113             return -1;
1114         }
1115         gen_ldst_fp(s, opsize, addr, fp, what, index);
1116         tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1117         return 0;
1118     case 5: /* Indirect displacement.  */
1119     case 6: /* Indirect index + displacement.  */
1120     do_indirect:
1121         addr = gen_lea_mode(env, s, mode, reg0, opsize);
1122         if (IS_NULL_QREG(addr)) {
1123             return -1;
1124         }
1125         gen_ldst_fp(s, opsize, addr, fp, what, index);
1126         return 0;
1127     case 7: /* Other */
1128         switch (reg0) {
1129         case 0: /* Absolute short.  */
1130         case 1: /* Absolute long.  */
1131         case 2: /* pc displacement  */
1132         case 3: /* pc index+displacement.  */
1133             goto do_indirect;
1134         case 4: /* Immediate.  */
1135             if (what == EA_STORE) {
1136                 return -1;
1137             }
1138             switch (opsize) {
1139             case OS_BYTE:
1140                 tmp = tcg_constant_i32((int8_t)read_im8(env, s));
1141                 gen_helper_exts32(cpu_env, fp, tmp);
1142                 break;
1143             case OS_WORD:
1144                 tmp = tcg_constant_i32((int16_t)read_im16(env, s));
1145                 gen_helper_exts32(cpu_env, fp, tmp);
1146                 break;
1147             case OS_LONG:
1148                 tmp = tcg_constant_i32(read_im32(env, s));
1149                 gen_helper_exts32(cpu_env, fp, tmp);
1150                 break;
1151             case OS_SINGLE:
1152                 tmp = tcg_constant_i32(read_im32(env, s));
1153                 gen_helper_extf32(cpu_env, fp, tmp);
1154                 break;
1155             case OS_DOUBLE:
1156                 t64 = tcg_constant_i64(read_im64(env, s));
1157                 gen_helper_extf64(cpu_env, fp, t64);
1158                 break;
1159             case OS_EXTENDED:
1160                 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1161                     gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1162                     break;
1163                 }
1164                 tmp = tcg_constant_i32(read_im32(env, s) >> 16);
1165                 tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
1166                 t64 = tcg_constant_i64(read_im64(env, s));
1167                 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
1168                 break;
1169             case OS_PACKED:
1170                 /*
1171                  * unimplemented data type on 68040/ColdFire
1172                  * FIXME if needed for another FPU
1173                  */
1174                 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1175                 break;
1176             default:
1177                 g_assert_not_reached();
1178             }
1179             return 0;
1180         default:
1181             return -1;
1182         }
1183     }
1184     return -1;
1185 }
1186 
1187 static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn,
1188                        int opsize, TCGv_ptr fp, ea_what what, int index)
1189 {
1190     int mode = extract32(insn, 3, 3);
1191     int reg0 = REG(insn, 0);
1192     return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what, index);
1193 }
1194 
1195 typedef struct {
1196     TCGCond tcond;
1197     TCGv v1;
1198     TCGv v2;
1199 } DisasCompare;
1200 
1201 static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
1202 {
1203     TCGv tmp, tmp2;
1204     TCGCond tcond;
1205     CCOp op = s->cc_op;
1206 
1207     /* The CC_OP_CMP form can handle most normal comparisons directly.  */
1208     if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) {
1209         c->v1 = QREG_CC_N;
1210         c->v2 = QREG_CC_V;
1211         switch (cond) {
1212         case 2: /* HI */
1213         case 3: /* LS */
1214             tcond = TCG_COND_LEU;
1215             goto done;
1216         case 4: /* CC */
1217         case 5: /* CS */
1218             tcond = TCG_COND_LTU;
1219             goto done;
1220         case 6: /* NE */
1221         case 7: /* EQ */
1222             tcond = TCG_COND_EQ;
1223             goto done;
1224         case 10: /* PL */
1225         case 11: /* MI */
1226             c->v2 = tcg_constant_i32(0);
1227             c->v1 = tmp = tcg_temp_new();
1228             tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V);
1229             gen_ext(tmp, tmp, op - CC_OP_CMPB, 1);
1230             /* fallthru */
1231         case 12: /* GE */
1232         case 13: /* LT */
1233             tcond = TCG_COND_LT;
1234             goto done;
1235         case 14: /* GT */
1236         case 15: /* LE */
1237             tcond = TCG_COND_LE;
1238             goto done;
1239         }
1240     }
1241 
1242     c->v2 = tcg_constant_i32(0);
1243 
1244     switch (cond) {
1245     case 0: /* T */
1246     case 1: /* F */
1247         c->v1 = c->v2;
1248         tcond = TCG_COND_NEVER;
1249         goto done;
1250     case 14: /* GT (!(Z || (N ^ V))) */
1251     case 15: /* LE (Z || (N ^ V)) */
1252         /*
1253          * Logic operations clear V, which simplifies LE to (Z || N),
1254          * and since Z and N are co-located, this becomes a normal
1255          * comparison vs N.
1256          */
1257         if (op == CC_OP_LOGIC) {
1258             c->v1 = QREG_CC_N;
1259             tcond = TCG_COND_LE;
1260             goto done;
1261         }
1262         break;
1263     case 12: /* GE (!(N ^ V)) */
1264     case 13: /* LT (N ^ V) */
1265         /* Logic operations clear V, which simplifies this to N.  */
1266         if (op != CC_OP_LOGIC) {
1267             break;
1268         }
1269         /* fallthru */
1270     case 10: /* PL (!N) */
1271     case 11: /* MI (N) */
1272         /* Several cases represent N normally.  */
1273         if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1274             op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1275             op == CC_OP_LOGIC) {
1276             c->v1 = QREG_CC_N;
1277             tcond = TCG_COND_LT;
1278             goto done;
1279         }
1280         break;
1281     case 6: /* NE (!Z) */
1282     case 7: /* EQ (Z) */
1283         /* Some cases fold Z into N.  */
1284         if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1285             op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1286             op == CC_OP_LOGIC) {
1287             tcond = TCG_COND_EQ;
1288             c->v1 = QREG_CC_N;
1289             goto done;
1290         }
1291         break;
1292     case 4: /* CC (!C) */
1293     case 5: /* CS (C) */
1294         /* Some cases fold C into X.  */
1295         if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1296             op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL) {
1297             tcond = TCG_COND_NE;
1298             c->v1 = QREG_CC_X;
1299             goto done;
1300         }
1301         /* fallthru */
1302     case 8: /* VC (!V) */
1303     case 9: /* VS (V) */
1304         /* Logic operations clear V and C.  */
1305         if (op == CC_OP_LOGIC) {
1306             tcond = TCG_COND_NEVER;
1307             c->v1 = c->v2;
1308             goto done;
1309         }
1310         break;
1311     }
1312 
1313     /* Otherwise, flush flag state to CC_OP_FLAGS.  */
1314     gen_flush_flags(s);
1315 
1316     switch (cond) {
1317     case 0: /* T */
1318     case 1: /* F */
1319     default:
1320         /* Invalid, or handled above.  */
1321         abort();
1322     case 2: /* HI (!C && !Z) -> !(C || Z)*/
1323     case 3: /* LS (C || Z) */
1324         c->v1 = tmp = tcg_temp_new();
1325         tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1326         tcg_gen_or_i32(tmp, tmp, QREG_CC_C);
1327         tcond = TCG_COND_NE;
1328         break;
1329     case 4: /* CC (!C) */
1330     case 5: /* CS (C) */
1331         c->v1 = QREG_CC_C;
1332         tcond = TCG_COND_NE;
1333         break;
1334     case 6: /* NE (!Z) */
1335     case 7: /* EQ (Z) */
1336         c->v1 = QREG_CC_Z;
1337         tcond = TCG_COND_EQ;
1338         break;
1339     case 8: /* VC (!V) */
1340     case 9: /* VS (V) */
1341         c->v1 = QREG_CC_V;
1342         tcond = TCG_COND_LT;
1343         break;
1344     case 10: /* PL (!N) */
1345     case 11: /* MI (N) */
1346         c->v1 = QREG_CC_N;
1347         tcond = TCG_COND_LT;
1348         break;
1349     case 12: /* GE (!(N ^ V)) */
1350     case 13: /* LT (N ^ V) */
1351         c->v1 = tmp = tcg_temp_new();
1352         tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V);
1353         tcond = TCG_COND_LT;
1354         break;
1355     case 14: /* GT (!(Z || (N ^ V))) */
1356     case 15: /* LE (Z || (N ^ V)) */
1357         c->v1 = tmp = tcg_temp_new();
1358         tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1359         tcg_gen_neg_i32(tmp, tmp);
1360         tmp2 = tcg_temp_new();
1361         tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
1362         tcg_gen_or_i32(tmp, tmp, tmp2);
1363         tcond = TCG_COND_LT;
1364         break;
1365     }
1366 
1367  done:
1368     if ((cond & 1) == 0) {
1369         tcond = tcg_invert_cond(tcond);
1370     }
1371     c->tcond = tcond;
1372 }
1373 
1374 static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
1375 {
1376   DisasCompare c;
1377 
1378   gen_cc_cond(&c, s, cond);
1379   update_cc_op(s);
1380   tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
1381 }
1382 
1383 /* Force a TB lookup after an instruction that changes the CPU state.  */
1384 static void gen_exit_tb(DisasContext *s)
1385 {
1386     update_cc_op(s);
1387     tcg_gen_movi_i32(QREG_PC, s->pc);
1388     s->base.is_jmp = DISAS_EXIT;
1389 }
1390 
1391 #define SRC_EA(env, result, opsize, op_sign, addrp) do {                \
1392         result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp,         \
1393                         op_sign ? EA_LOADS : EA_LOADU, IS_USER(s));     \
1394         if (IS_NULL_QREG(result)) {                                     \
1395             gen_addr_fault(s);                                          \
1396             return;                                                     \
1397         }                                                               \
1398     } while (0)
1399 
1400 #define DEST_EA(env, insn, opsize, val, addrp) do {                     \
1401         TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp,       \
1402                                 EA_STORE, IS_USER(s));                  \
1403         if (IS_NULL_QREG(ea_result)) {                                  \
1404             gen_addr_fault(s);                                          \
1405             return;                                                     \
1406         }                                                               \
1407     } while (0)
1408 
1409 /* Generate a jump to an immediate address.  */
1410 static void gen_jmp_tb(DisasContext *s, int n, target_ulong dest,
1411                        target_ulong src)
1412 {
1413     if (unlikely(s->ss_active)) {
1414         update_cc_op(s);
1415         tcg_gen_movi_i32(QREG_PC, dest);
1416         gen_raise_exception_format2(s, EXCP_TRACE, src);
1417     } else if (translator_use_goto_tb(&s->base, dest)) {
1418         tcg_gen_goto_tb(n);
1419         tcg_gen_movi_i32(QREG_PC, dest);
1420         tcg_gen_exit_tb(s->base.tb, n);
1421     } else {
1422         gen_jmp_im(s, dest);
1423         tcg_gen_exit_tb(NULL, 0);
1424     }
1425     s->base.is_jmp = DISAS_NORETURN;
1426 }
1427 
1428 DISAS_INSN(scc)
1429 {
1430     DisasCompare c;
1431     int cond;
1432     TCGv tmp;
1433 
1434     cond = (insn >> 8) & 0xf;
1435     gen_cc_cond(&c, s, cond);
1436 
1437     tmp = tcg_temp_new();
1438     tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
1439 
1440     tcg_gen_neg_i32(tmp, tmp);
1441     DEST_EA(env, insn, OS_BYTE, tmp, NULL);
1442 }
1443 
1444 DISAS_INSN(dbcc)
1445 {
1446     TCGLabel *l1;
1447     TCGv reg;
1448     TCGv tmp;
1449     int16_t offset;
1450     uint32_t base;
1451 
1452     reg = DREG(insn, 0);
1453     base = s->pc;
1454     offset = (int16_t)read_im16(env, s);
1455     l1 = gen_new_label();
1456     gen_jmpcc(s, (insn >> 8) & 0xf, l1);
1457 
1458     tmp = tcg_temp_new();
1459     tcg_gen_ext16s_i32(tmp, reg);
1460     tcg_gen_addi_i32(tmp, tmp, -1);
1461     gen_partset_reg(OS_WORD, reg, tmp);
1462     tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
1463     gen_jmp_tb(s, 1, base + offset, s->base.pc_next);
1464     gen_set_label(l1);
1465     gen_jmp_tb(s, 0, s->pc, s->base.pc_next);
1466 }
1467 
1468 DISAS_INSN(undef_mac)
1469 {
1470     gen_exception(s, s->base.pc_next, EXCP_LINEA);
1471 }
1472 
1473 DISAS_INSN(undef_fpu)
1474 {
1475     gen_exception(s, s->base.pc_next, EXCP_LINEF);
1476 }
1477 
1478 DISAS_INSN(undef)
1479 {
1480     /*
1481      * ??? This is both instructions that are as yet unimplemented
1482      * for the 680x0 series, as well as those that are implemented
1483      * but actually illegal for CPU32 or pre-68020.
1484      */
1485     qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x\n",
1486                   insn, s->base.pc_next);
1487     gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1488 }
1489 
1490 DISAS_INSN(mulw)
1491 {
1492     TCGv reg;
1493     TCGv tmp;
1494     TCGv src;
1495     int sign;
1496 
1497     sign = (insn & 0x100) != 0;
1498     reg = DREG(insn, 9);
1499     tmp = tcg_temp_new();
1500     if (sign)
1501         tcg_gen_ext16s_i32(tmp, reg);
1502     else
1503         tcg_gen_ext16u_i32(tmp, reg);
1504     SRC_EA(env, src, OS_WORD, sign, NULL);
1505     tcg_gen_mul_i32(tmp, tmp, src);
1506     tcg_gen_mov_i32(reg, tmp);
1507     gen_logic_cc(s, tmp, OS_LONG);
1508 }
1509 
1510 DISAS_INSN(divw)
1511 {
1512     int sign;
1513     TCGv src;
1514     TCGv destr;
1515     TCGv ilen;
1516 
1517     /* divX.w <EA>,Dn    32/16 -> 16r:16q */
1518 
1519     sign = (insn & 0x100) != 0;
1520 
1521     /* dest.l / src.w */
1522 
1523     SRC_EA(env, src, OS_WORD, sign, NULL);
1524     destr = tcg_constant_i32(REG(insn, 9));
1525     ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1526     if (sign) {
1527         gen_helper_divsw(cpu_env, destr, src, ilen);
1528     } else {
1529         gen_helper_divuw(cpu_env, destr, src, ilen);
1530     }
1531 
1532     set_cc_op(s, CC_OP_FLAGS);
1533 }
1534 
1535 DISAS_INSN(divl)
1536 {
1537     TCGv num, reg, den, ilen;
1538     int sign;
1539     uint16_t ext;
1540 
1541     ext = read_im16(env, s);
1542 
1543     sign = (ext & 0x0800) != 0;
1544 
1545     if (ext & 0x400) {
1546         if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
1547             gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1548             return;
1549         }
1550 
1551         /* divX.l <EA>, Dr:Dq    64/32 -> 32r:32q */
1552 
1553         SRC_EA(env, den, OS_LONG, 0, NULL);
1554         num = tcg_constant_i32(REG(ext, 12));
1555         reg = tcg_constant_i32(REG(ext, 0));
1556         ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1557         if (sign) {
1558             gen_helper_divsll(cpu_env, num, reg, den, ilen);
1559         } else {
1560             gen_helper_divull(cpu_env, num, reg, den, ilen);
1561         }
1562         set_cc_op(s, CC_OP_FLAGS);
1563         return;
1564     }
1565 
1566     /* divX.l <EA>, Dq        32/32 -> 32q     */
1567     /* divXl.l <EA>, Dr:Dq    32/32 -> 32r:32q */
1568 
1569     SRC_EA(env, den, OS_LONG, 0, NULL);
1570     num = tcg_constant_i32(REG(ext, 12));
1571     reg = tcg_constant_i32(REG(ext, 0));
1572     ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1573     if (sign) {
1574         gen_helper_divsl(cpu_env, num, reg, den, ilen);
1575     } else {
1576         gen_helper_divul(cpu_env, num, reg, den, ilen);
1577     }
1578 
1579     set_cc_op(s, CC_OP_FLAGS);
1580 }
1581 
1582 static void bcd_add(TCGv dest, TCGv src)
1583 {
1584     TCGv t0, t1;
1585 
1586     /*
1587      * dest10 = dest10 + src10 + X
1588      *
1589      *        t1 = src
1590      *        t2 = t1 + 0x066
1591      *        t3 = t2 + dest + X
1592      *        t4 = t2 ^ dest
1593      *        t5 = t3 ^ t4
1594      *        t6 = ~t5 & 0x110
1595      *        t7 = (t6 >> 2) | (t6 >> 3)
1596      *        return t3 - t7
1597      */
1598 
1599     /*
1600      * t1 = (src + 0x066) + dest + X
1601      *    = result with some possible exceeding 0x6
1602      */
1603 
1604     t0 = tcg_temp_new();
1605     tcg_gen_addi_i32(t0, src, 0x066);
1606 
1607     t1 = tcg_temp_new();
1608     tcg_gen_add_i32(t1, t0, dest);
1609     tcg_gen_add_i32(t1, t1, QREG_CC_X);
1610 
1611     /* we will remove exceeding 0x6 where there is no carry */
1612 
1613     /*
1614      * t0 = (src + 0x0066) ^ dest
1615      *    = t1 without carries
1616      */
1617 
1618     tcg_gen_xor_i32(t0, t0, dest);
1619 
1620     /*
1621      * extract the carries
1622      * t0 = t0 ^ t1
1623      *    = only the carries
1624      */
1625 
1626     tcg_gen_xor_i32(t0, t0, t1);
1627 
1628     /*
1629      * generate 0x1 where there is no carry
1630      * and for each 0x10, generate a 0x6
1631      */
1632 
1633     tcg_gen_shri_i32(t0, t0, 3);
1634     tcg_gen_not_i32(t0, t0);
1635     tcg_gen_andi_i32(t0, t0, 0x22);
1636     tcg_gen_add_i32(dest, t0, t0);
1637     tcg_gen_add_i32(dest, dest, t0);
1638 
1639     /*
1640      * remove the exceeding 0x6
1641      * for digits that have not generated a carry
1642      */
1643 
1644     tcg_gen_sub_i32(dest, t1, dest);
1645 }
1646 
1647 static void bcd_sub(TCGv dest, TCGv src)
1648 {
1649     TCGv t0, t1, t2;
1650 
1651     /*
1652      *  dest10 = dest10 - src10 - X
1653      *         = bcd_add(dest + 1 - X, 0x199 - src)
1654      */
1655 
1656     /* t0 = 0x066 + (0x199 - src) */
1657 
1658     t0 = tcg_temp_new();
1659     tcg_gen_subfi_i32(t0, 0x1ff, src);
1660 
1661     /* t1 = t0 + dest + 1 - X*/
1662 
1663     t1 = tcg_temp_new();
1664     tcg_gen_add_i32(t1, t0, dest);
1665     tcg_gen_addi_i32(t1, t1, 1);
1666     tcg_gen_sub_i32(t1, t1, QREG_CC_X);
1667 
1668     /* t2 = t0 ^ dest */
1669 
1670     t2 = tcg_temp_new();
1671     tcg_gen_xor_i32(t2, t0, dest);
1672 
1673     /* t0 = t1 ^ t2 */
1674 
1675     tcg_gen_xor_i32(t0, t1, t2);
1676 
1677     /*
1678      * t2 = ~t0 & 0x110
1679      * t0 = (t2 >> 2) | (t2 >> 3)
1680      *
1681      * to fit on 8bit operands, changed in:
1682      *
1683      * t2 = ~(t0 >> 3) & 0x22
1684      * t0 = t2 + t2
1685      * t0 = t0 + t2
1686      */
1687 
1688     tcg_gen_shri_i32(t2, t0, 3);
1689     tcg_gen_not_i32(t2, t2);
1690     tcg_gen_andi_i32(t2, t2, 0x22);
1691     tcg_gen_add_i32(t0, t2, t2);
1692     tcg_gen_add_i32(t0, t0, t2);
1693 
1694     /* return t1 - t0 */
1695 
1696     tcg_gen_sub_i32(dest, t1, t0);
1697 }
1698 
1699 static void bcd_flags(TCGv val)
1700 {
1701     tcg_gen_andi_i32(QREG_CC_C, val, 0x0ff);
1702     tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_C);
1703 
1704     tcg_gen_extract_i32(QREG_CC_C, val, 8, 1);
1705 
1706     tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
1707 }
1708 
1709 DISAS_INSN(abcd_reg)
1710 {
1711     TCGv src;
1712     TCGv dest;
1713 
1714     gen_flush_flags(s); /* !Z is sticky */
1715 
1716     src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1717     dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1718     bcd_add(dest, src);
1719     gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1720 
1721     bcd_flags(dest);
1722 }
1723 
1724 DISAS_INSN(abcd_mem)
1725 {
1726     TCGv src, dest, addr;
1727 
1728     gen_flush_flags(s); /* !Z is sticky */
1729 
1730     /* Indirect pre-decrement load (mode 4) */
1731 
1732     src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1733                       NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1734     dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1735                        NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1736 
1737     bcd_add(dest, src);
1738 
1739     gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1740                 EA_STORE, IS_USER(s));
1741 
1742     bcd_flags(dest);
1743 }
1744 
1745 DISAS_INSN(sbcd_reg)
1746 {
1747     TCGv src, dest;
1748 
1749     gen_flush_flags(s); /* !Z is sticky */
1750 
1751     src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1752     dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1753 
1754     bcd_sub(dest, src);
1755 
1756     gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1757 
1758     bcd_flags(dest);
1759 }
1760 
1761 DISAS_INSN(sbcd_mem)
1762 {
1763     TCGv src, dest, addr;
1764 
1765     gen_flush_flags(s); /* !Z is sticky */
1766 
1767     /* Indirect pre-decrement load (mode 4) */
1768 
1769     src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1770                       NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1771     dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1772                        NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1773 
1774     bcd_sub(dest, src);
1775 
1776     gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1777                 EA_STORE, IS_USER(s));
1778 
1779     bcd_flags(dest);
1780 }
1781 
1782 DISAS_INSN(nbcd)
1783 {
1784     TCGv src, dest;
1785     TCGv addr;
1786 
1787     gen_flush_flags(s); /* !Z is sticky */
1788 
1789     SRC_EA(env, src, OS_BYTE, 0, &addr);
1790 
1791     dest = tcg_temp_new();
1792     tcg_gen_movi_i32(dest, 0);
1793     bcd_sub(dest, src);
1794 
1795     DEST_EA(env, insn, OS_BYTE, dest, &addr);
1796 
1797     bcd_flags(dest);
1798 }
1799 
1800 DISAS_INSN(addsub)
1801 {
1802     TCGv reg;
1803     TCGv dest;
1804     TCGv src;
1805     TCGv tmp;
1806     TCGv addr;
1807     int add;
1808     int opsize;
1809 
1810     add = (insn & 0x4000) != 0;
1811     opsize = insn_opsize(insn);
1812     reg = gen_extend(s, DREG(insn, 9), opsize, 1);
1813     dest = tcg_temp_new();
1814     if (insn & 0x100) {
1815         SRC_EA(env, tmp, opsize, 1, &addr);
1816         src = reg;
1817     } else {
1818         tmp = reg;
1819         SRC_EA(env, src, opsize, 1, NULL);
1820     }
1821     if (add) {
1822         tcg_gen_add_i32(dest, tmp, src);
1823         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
1824         set_cc_op(s, CC_OP_ADDB + opsize);
1825     } else {
1826         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
1827         tcg_gen_sub_i32(dest, tmp, src);
1828         set_cc_op(s, CC_OP_SUBB + opsize);
1829     }
1830     gen_update_cc_add(dest, src, opsize);
1831     if (insn & 0x100) {
1832         DEST_EA(env, insn, opsize, dest, &addr);
1833     } else {
1834         gen_partset_reg(opsize, DREG(insn, 9), dest);
1835     }
1836 }
1837 
1838 /* Reverse the order of the bits in REG.  */
1839 DISAS_INSN(bitrev)
1840 {
1841     TCGv reg;
1842     reg = DREG(insn, 0);
1843     gen_helper_bitrev(reg, reg);
1844 }
1845 
1846 DISAS_INSN(bitop_reg)
1847 {
1848     int opsize;
1849     int op;
1850     TCGv src1;
1851     TCGv src2;
1852     TCGv tmp;
1853     TCGv addr;
1854     TCGv dest;
1855 
1856     if ((insn & 0x38) != 0)
1857         opsize = OS_BYTE;
1858     else
1859         opsize = OS_LONG;
1860     op = (insn >> 6) & 3;
1861     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
1862 
1863     gen_flush_flags(s);
1864     src2 = tcg_temp_new();
1865     if (opsize == OS_BYTE)
1866         tcg_gen_andi_i32(src2, DREG(insn, 9), 7);
1867     else
1868         tcg_gen_andi_i32(src2, DREG(insn, 9), 31);
1869 
1870     tmp = tcg_temp_new();
1871     tcg_gen_shl_i32(tmp, tcg_constant_i32(1), src2);
1872 
1873     tcg_gen_and_i32(QREG_CC_Z, src1, tmp);
1874 
1875     dest = tcg_temp_new();
1876     switch (op) {
1877     case 1: /* bchg */
1878         tcg_gen_xor_i32(dest, src1, tmp);
1879         break;
1880     case 2: /* bclr */
1881         tcg_gen_andc_i32(dest, src1, tmp);
1882         break;
1883     case 3: /* bset */
1884         tcg_gen_or_i32(dest, src1, tmp);
1885         break;
1886     default: /* btst */
1887         break;
1888     }
1889     if (op) {
1890         DEST_EA(env, insn, opsize, dest, &addr);
1891     }
1892 }
1893 
1894 DISAS_INSN(sats)
1895 {
1896     TCGv reg;
1897     reg = DREG(insn, 0);
1898     gen_flush_flags(s);
1899     gen_helper_sats(reg, reg, QREG_CC_V);
1900     gen_logic_cc(s, reg, OS_LONG);
1901 }
1902 
1903 static void gen_push(DisasContext *s, TCGv val)
1904 {
1905     TCGv tmp;
1906 
1907     tmp = tcg_temp_new();
1908     tcg_gen_subi_i32(tmp, QREG_SP, 4);
1909     gen_store(s, OS_LONG, tmp, val, IS_USER(s));
1910     tcg_gen_mov_i32(QREG_SP, tmp);
1911 }
1912 
1913 static TCGv mreg(int reg)
1914 {
1915     if (reg < 8) {
1916         /* Dx */
1917         return cpu_dregs[reg];
1918     }
1919     /* Ax */
1920     return cpu_aregs[reg & 7];
1921 }
1922 
1923 DISAS_INSN(movem)
1924 {
1925     TCGv addr, incr, tmp, r[16];
1926     int is_load = (insn & 0x0400) != 0;
1927     int opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
1928     uint16_t mask = read_im16(env, s);
1929     int mode = extract32(insn, 3, 3);
1930     int reg0 = REG(insn, 0);
1931     int i;
1932 
1933     tmp = cpu_aregs[reg0];
1934 
1935     switch (mode) {
1936     case 0: /* data register direct */
1937     case 1: /* addr register direct */
1938     do_addr_fault:
1939         gen_addr_fault(s);
1940         return;
1941 
1942     case 2: /* indirect */
1943         break;
1944 
1945     case 3: /* indirect post-increment */
1946         if (!is_load) {
1947             /* post-increment is not allowed */
1948             goto do_addr_fault;
1949         }
1950         break;
1951 
1952     case 4: /* indirect pre-decrement */
1953         if (is_load) {
1954             /* pre-decrement is not allowed */
1955             goto do_addr_fault;
1956         }
1957         /*
1958          * We want a bare copy of the address reg, without any pre-decrement
1959          * adjustment, as gen_lea would provide.
1960          */
1961         break;
1962 
1963     default:
1964         tmp = gen_lea_mode(env, s, mode, reg0, opsize);
1965         if (IS_NULL_QREG(tmp)) {
1966             goto do_addr_fault;
1967         }
1968         break;
1969     }
1970 
1971     addr = tcg_temp_new();
1972     tcg_gen_mov_i32(addr, tmp);
1973     incr = tcg_constant_i32(opsize_bytes(opsize));
1974 
1975     if (is_load) {
1976         /* memory to register */
1977         for (i = 0; i < 16; i++) {
1978             if (mask & (1 << i)) {
1979                 r[i] = gen_load(s, opsize, addr, 1, IS_USER(s));
1980                 tcg_gen_add_i32(addr, addr, incr);
1981             }
1982         }
1983         for (i = 0; i < 16; i++) {
1984             if (mask & (1 << i)) {
1985                 tcg_gen_mov_i32(mreg(i), r[i]);
1986             }
1987         }
1988         if (mode == 3) {
1989             /* post-increment: movem (An)+,X */
1990             tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1991         }
1992     } else {
1993         /* register to memory */
1994         if (mode == 4) {
1995             /* pre-decrement: movem X,-(An) */
1996             for (i = 15; i >= 0; i--) {
1997                 if ((mask << i) & 0x8000) {
1998                     tcg_gen_sub_i32(addr, addr, incr);
1999                     if (reg0 + 8 == i &&
2000                         m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
2001                         /*
2002                          * M68020+: if the addressing register is the
2003                          * register moved to memory, the value written
2004                          * is the initial value decremented by the size of
2005                          * the operation, regardless of how many actual
2006                          * stores have been performed until this point.
2007                          * M68000/M68010: the value is the initial value.
2008                          */
2009                         tmp = tcg_temp_new();
2010                         tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr);
2011                         gen_store(s, opsize, addr, tmp, IS_USER(s));
2012                     } else {
2013                         gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2014                     }
2015                 }
2016             }
2017             tcg_gen_mov_i32(cpu_aregs[reg0], addr);
2018         } else {
2019             for (i = 0; i < 16; i++) {
2020                 if (mask & (1 << i)) {
2021                     gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2022                     tcg_gen_add_i32(addr, addr, incr);
2023                 }
2024             }
2025         }
2026     }
2027 }
2028 
2029 DISAS_INSN(movep)
2030 {
2031     uint8_t i;
2032     int16_t displ;
2033     TCGv reg;
2034     TCGv addr;
2035     TCGv abuf;
2036     TCGv dbuf;
2037 
2038     displ = read_im16(env, s);
2039 
2040     addr = AREG(insn, 0);
2041     reg = DREG(insn, 9);
2042 
2043     abuf = tcg_temp_new();
2044     tcg_gen_addi_i32(abuf, addr, displ);
2045     dbuf = tcg_temp_new();
2046 
2047     if (insn & 0x40) {
2048         i = 4;
2049     } else {
2050         i = 2;
2051     }
2052 
2053     if (insn & 0x80) {
2054         for ( ; i > 0 ; i--) {
2055             tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8);
2056             tcg_gen_qemu_st_i32(dbuf, abuf, IS_USER(s), MO_UB);
2057             if (i > 1) {
2058                 tcg_gen_addi_i32(abuf, abuf, 2);
2059             }
2060         }
2061     } else {
2062         for ( ; i > 0 ; i--) {
2063             tcg_gen_qemu_ld_tl(dbuf, abuf, IS_USER(s), MO_UB);
2064             tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8);
2065             if (i > 1) {
2066                 tcg_gen_addi_i32(abuf, abuf, 2);
2067             }
2068         }
2069     }
2070 }
2071 
2072 DISAS_INSN(bitop_im)
2073 {
2074     int opsize;
2075     int op;
2076     TCGv src1;
2077     uint32_t mask;
2078     int bitnum;
2079     TCGv tmp;
2080     TCGv addr;
2081 
2082     if ((insn & 0x38) != 0)
2083         opsize = OS_BYTE;
2084     else
2085         opsize = OS_LONG;
2086     op = (insn >> 6) & 3;
2087 
2088     bitnum = read_im16(env, s);
2089     if (m68k_feature(s->env, M68K_FEATURE_M68K)) {
2090         if (bitnum & 0xfe00) {
2091             disas_undef(env, s, insn);
2092             return;
2093         }
2094     } else {
2095         if (bitnum & 0xff00) {
2096             disas_undef(env, s, insn);
2097             return;
2098         }
2099     }
2100 
2101     SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
2102 
2103     gen_flush_flags(s);
2104     if (opsize == OS_BYTE)
2105         bitnum &= 7;
2106     else
2107         bitnum &= 31;
2108     mask = 1 << bitnum;
2109 
2110    tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
2111 
2112     if (op) {
2113         tmp = tcg_temp_new();
2114         switch (op) {
2115         case 1: /* bchg */
2116             tcg_gen_xori_i32(tmp, src1, mask);
2117             break;
2118         case 2: /* bclr */
2119             tcg_gen_andi_i32(tmp, src1, ~mask);
2120             break;
2121         case 3: /* bset */
2122             tcg_gen_ori_i32(tmp, src1, mask);
2123             break;
2124         default: /* btst */
2125             break;
2126         }
2127         DEST_EA(env, insn, opsize, tmp, &addr);
2128     }
2129 }
2130 
2131 static TCGv gen_get_ccr(DisasContext *s)
2132 {
2133     TCGv dest;
2134 
2135     update_cc_op(s);
2136     dest = tcg_temp_new();
2137     gen_helper_get_ccr(dest, cpu_env);
2138     return dest;
2139 }
2140 
2141 static TCGv gen_get_sr(DisasContext *s)
2142 {
2143     TCGv ccr;
2144     TCGv sr;
2145 
2146     ccr = gen_get_ccr(s);
2147     sr = tcg_temp_new();
2148     tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
2149     tcg_gen_or_i32(sr, sr, ccr);
2150     return sr;
2151 }
2152 
2153 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
2154 {
2155     if (ccr_only) {
2156         tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
2157         tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
2158         tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
2159         tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
2160         tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
2161     } else {
2162         /* Must writeback before changing security state. */
2163         do_writebacks(s);
2164         gen_helper_set_sr(cpu_env, tcg_constant_i32(val));
2165     }
2166     set_cc_op(s, CC_OP_FLAGS);
2167 }
2168 
2169 static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
2170 {
2171     if (ccr_only) {
2172         gen_helper_set_ccr(cpu_env, val);
2173     } else {
2174         /* Must writeback before changing security state. */
2175         do_writebacks(s);
2176         gen_helper_set_sr(cpu_env, val);
2177     }
2178     set_cc_op(s, CC_OP_FLAGS);
2179 }
2180 
2181 static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
2182                            bool ccr_only)
2183 {
2184     if ((insn & 0x3f) == 0x3c) {
2185         uint16_t val;
2186         val = read_im16(env, s);
2187         gen_set_sr_im(s, val, ccr_only);
2188     } else {
2189         TCGv src;
2190         SRC_EA(env, src, OS_WORD, 0, NULL);
2191         gen_set_sr(s, src, ccr_only);
2192     }
2193 }
2194 
2195 DISAS_INSN(arith_im)
2196 {
2197     int op;
2198     TCGv im;
2199     TCGv src1;
2200     TCGv dest;
2201     TCGv addr;
2202     int opsize;
2203     bool with_SR = ((insn & 0x3f) == 0x3c);
2204 
2205     op = (insn >> 9) & 7;
2206     opsize = insn_opsize(insn);
2207     switch (opsize) {
2208     case OS_BYTE:
2209         im = tcg_constant_i32((int8_t)read_im8(env, s));
2210         break;
2211     case OS_WORD:
2212         im = tcg_constant_i32((int16_t)read_im16(env, s));
2213         break;
2214     case OS_LONG:
2215         im = tcg_constant_i32(read_im32(env, s));
2216         break;
2217     default:
2218         g_assert_not_reached();
2219     }
2220 
2221     if (with_SR) {
2222         /* SR/CCR can only be used with andi/eori/ori */
2223         if (op == 2 || op == 3 || op == 6) {
2224             disas_undef(env, s, insn);
2225             return;
2226         }
2227         switch (opsize) {
2228         case OS_BYTE:
2229             src1 = gen_get_ccr(s);
2230             break;
2231         case OS_WORD:
2232             if (IS_USER(s)) {
2233                 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2234                 return;
2235             }
2236             src1 = gen_get_sr(s);
2237             break;
2238         default:
2239             /* OS_LONG; others already g_assert_not_reached.  */
2240             disas_undef(env, s, insn);
2241             return;
2242         }
2243     } else {
2244         SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
2245     }
2246     dest = tcg_temp_new();
2247     switch (op) {
2248     case 0: /* ori */
2249         tcg_gen_or_i32(dest, src1, im);
2250         if (with_SR) {
2251             gen_set_sr(s, dest, opsize == OS_BYTE);
2252             gen_exit_tb(s);
2253         } else {
2254             DEST_EA(env, insn, opsize, dest, &addr);
2255             gen_logic_cc(s, dest, opsize);
2256         }
2257         break;
2258     case 1: /* andi */
2259         tcg_gen_and_i32(dest, src1, im);
2260         if (with_SR) {
2261             gen_set_sr(s, dest, opsize == OS_BYTE);
2262             gen_exit_tb(s);
2263         } else {
2264             DEST_EA(env, insn, opsize, dest, &addr);
2265             gen_logic_cc(s, dest, opsize);
2266         }
2267         break;
2268     case 2: /* subi */
2269         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
2270         tcg_gen_sub_i32(dest, src1, im);
2271         gen_update_cc_add(dest, im, opsize);
2272         set_cc_op(s, CC_OP_SUBB + opsize);
2273         DEST_EA(env, insn, opsize, dest, &addr);
2274         break;
2275     case 3: /* addi */
2276         tcg_gen_add_i32(dest, src1, im);
2277         gen_update_cc_add(dest, im, opsize);
2278         tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
2279         set_cc_op(s, CC_OP_ADDB + opsize);
2280         DEST_EA(env, insn, opsize, dest, &addr);
2281         break;
2282     case 5: /* eori */
2283         tcg_gen_xor_i32(dest, src1, im);
2284         if (with_SR) {
2285             gen_set_sr(s, dest, opsize == OS_BYTE);
2286             gen_exit_tb(s);
2287         } else {
2288             DEST_EA(env, insn, opsize, dest, &addr);
2289             gen_logic_cc(s, dest, opsize);
2290         }
2291         break;
2292     case 6: /* cmpi */
2293         gen_update_cc_cmp(s, src1, im, opsize);
2294         break;
2295     default:
2296         abort();
2297     }
2298 }
2299 
2300 DISAS_INSN(cas)
2301 {
2302     int opsize;
2303     TCGv addr;
2304     uint16_t ext;
2305     TCGv load;
2306     TCGv cmp;
2307     MemOp opc;
2308 
2309     switch ((insn >> 9) & 3) {
2310     case 1:
2311         opsize = OS_BYTE;
2312         opc = MO_SB;
2313         break;
2314     case 2:
2315         opsize = OS_WORD;
2316         opc = MO_TESW;
2317         break;
2318     case 3:
2319         opsize = OS_LONG;
2320         opc = MO_TESL;
2321         break;
2322     default:
2323         g_assert_not_reached();
2324     }
2325 
2326     ext = read_im16(env, s);
2327 
2328     /* cas Dc,Du,<EA> */
2329 
2330     addr = gen_lea(env, s, insn, opsize);
2331     if (IS_NULL_QREG(addr)) {
2332         gen_addr_fault(s);
2333         return;
2334     }
2335 
2336     cmp = gen_extend(s, DREG(ext, 0), opsize, 1);
2337 
2338     /*
2339      * if  <EA> == Dc then
2340      *     <EA> = Du
2341      *     Dc = <EA> (because <EA> == Dc)
2342      * else
2343      *     Dc = <EA>
2344      */
2345 
2346     load = tcg_temp_new();
2347     tcg_gen_atomic_cmpxchg_i32(load, addr, cmp, DREG(ext, 6),
2348                                IS_USER(s), opc);
2349     /* update flags before setting cmp to load */
2350     gen_update_cc_cmp(s, load, cmp, opsize);
2351     gen_partset_reg(opsize, DREG(ext, 0), load);
2352 
2353     switch (extract32(insn, 3, 3)) {
2354     case 3: /* Indirect postincrement.  */
2355         tcg_gen_addi_i32(AREG(insn, 0), addr, opsize_bytes(opsize));
2356         break;
2357     case 4: /* Indirect predecrememnt.  */
2358         tcg_gen_mov_i32(AREG(insn, 0), addr);
2359         break;
2360     }
2361 }
2362 
2363 DISAS_INSN(cas2w)
2364 {
2365     uint16_t ext1, ext2;
2366     TCGv addr1, addr2;
2367 
2368     /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2369 
2370     ext1 = read_im16(env, s);
2371 
2372     if (ext1 & 0x8000) {
2373         /* Address Register */
2374         addr1 = AREG(ext1, 12);
2375     } else {
2376         /* Data Register */
2377         addr1 = DREG(ext1, 12);
2378     }
2379 
2380     ext2 = read_im16(env, s);
2381     if (ext2 & 0x8000) {
2382         /* Address Register */
2383         addr2 = AREG(ext2, 12);
2384     } else {
2385         /* Data Register */
2386         addr2 = DREG(ext2, 12);
2387     }
2388 
2389     /*
2390      * if (R1) == Dc1 && (R2) == Dc2 then
2391      *     (R1) = Du1
2392      *     (R2) = Du2
2393      * else
2394      *     Dc1 = (R1)
2395      *     Dc2 = (R2)
2396      */
2397 
2398     if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2399         gen_helper_exit_atomic(cpu_env);
2400     } else {
2401         TCGv regs = tcg_constant_i32(REG(ext2, 6) |
2402                                      (REG(ext1, 6) << 3) |
2403                                      (REG(ext2, 0) << 6) |
2404                                      (REG(ext1, 0) << 9));
2405         gen_helper_cas2w(cpu_env, regs, addr1, addr2);
2406     }
2407 
2408     /* Note that cas2w also assigned to env->cc_op.  */
2409     s->cc_op = CC_OP_CMPW;
2410     s->cc_op_synced = 1;
2411 }
2412 
2413 DISAS_INSN(cas2l)
2414 {
2415     uint16_t ext1, ext2;
2416     TCGv addr1, addr2, regs;
2417 
2418     /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2419 
2420     ext1 = read_im16(env, s);
2421 
2422     if (ext1 & 0x8000) {
2423         /* Address Register */
2424         addr1 = AREG(ext1, 12);
2425     } else {
2426         /* Data Register */
2427         addr1 = DREG(ext1, 12);
2428     }
2429 
2430     ext2 = read_im16(env, s);
2431     if (ext2 & 0x8000) {
2432         /* Address Register */
2433         addr2 = AREG(ext2, 12);
2434     } else {
2435         /* Data Register */
2436         addr2 = DREG(ext2, 12);
2437     }
2438 
2439     /*
2440      * if (R1) == Dc1 && (R2) == Dc2 then
2441      *     (R1) = Du1
2442      *     (R2) = Du2
2443      * else
2444      *     Dc1 = (R1)
2445      *     Dc2 = (R2)
2446      */
2447 
2448     regs = tcg_constant_i32(REG(ext2, 6) |
2449                             (REG(ext1, 6) << 3) |
2450                             (REG(ext2, 0) << 6) |
2451                             (REG(ext1, 0) << 9));
2452     if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2453         gen_helper_cas2l_parallel(cpu_env, regs, addr1, addr2);
2454     } else {
2455         gen_helper_cas2l(cpu_env, regs, addr1, addr2);
2456     }
2457 
2458     /* Note that cas2l also assigned to env->cc_op.  */
2459     s->cc_op = CC_OP_CMPL;
2460     s->cc_op_synced = 1;
2461 }
2462 
2463 DISAS_INSN(byterev)
2464 {
2465     TCGv reg;
2466 
2467     reg = DREG(insn, 0);
2468     tcg_gen_bswap32_i32(reg, reg);
2469 }
2470 
2471 DISAS_INSN(move)
2472 {
2473     TCGv src;
2474     TCGv dest;
2475     int op;
2476     int opsize;
2477 
2478     switch (insn >> 12) {
2479     case 1: /* move.b */
2480         opsize = OS_BYTE;
2481         break;
2482     case 2: /* move.l */
2483         opsize = OS_LONG;
2484         break;
2485     case 3: /* move.w */
2486         opsize = OS_WORD;
2487         break;
2488     default:
2489         abort();
2490     }
2491     SRC_EA(env, src, opsize, 1, NULL);
2492     op = (insn >> 6) & 7;
2493     if (op == 1) {
2494         /* movea */
2495         /* The value will already have been sign extended.  */
2496         dest = AREG(insn, 9);
2497         tcg_gen_mov_i32(dest, src);
2498     } else {
2499         /* normal move */
2500         uint16_t dest_ea;
2501         dest_ea = ((insn >> 9) & 7) | (op << 3);
2502         DEST_EA(env, dest_ea, opsize, src, NULL);
2503         /* This will be correct because loads sign extend.  */
2504         gen_logic_cc(s, src, opsize);
2505     }
2506 }
2507 
2508 DISAS_INSN(negx)
2509 {
2510     TCGv z;
2511     TCGv src;
2512     TCGv addr;
2513     int opsize;
2514 
2515     opsize = insn_opsize(insn);
2516     SRC_EA(env, src, opsize, 1, &addr);
2517 
2518     gen_flush_flags(s); /* compute old Z */
2519 
2520     /*
2521      * Perform subtract with borrow.
2522      * (X, N) =  -(src + X);
2523      */
2524 
2525     z = tcg_constant_i32(0);
2526     tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
2527     tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X);
2528     gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
2529 
2530     tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
2531 
2532     /*
2533      * Compute signed-overflow for negation.  The normal formula for
2534      * subtraction is (res ^ src) & (src ^ dest), but with dest==0
2535      * this simplifies to res & src.
2536      */
2537 
2538     tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src);
2539 
2540     /* Copy the rest of the results into place.  */
2541     tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
2542     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
2543 
2544     set_cc_op(s, CC_OP_FLAGS);
2545 
2546     /* result is in QREG_CC_N */
2547 
2548     DEST_EA(env, insn, opsize, QREG_CC_N, &addr);
2549 }
2550 
2551 DISAS_INSN(lea)
2552 {
2553     TCGv reg;
2554     TCGv tmp;
2555 
2556     reg = AREG(insn, 9);
2557     tmp = gen_lea(env, s, insn, OS_LONG);
2558     if (IS_NULL_QREG(tmp)) {
2559         gen_addr_fault(s);
2560         return;
2561     }
2562     tcg_gen_mov_i32(reg, tmp);
2563 }
2564 
2565 DISAS_INSN(clr)
2566 {
2567     int opsize;
2568     TCGv zero;
2569 
2570     zero = tcg_constant_i32(0);
2571     opsize = insn_opsize(insn);
2572     DEST_EA(env, insn, opsize, zero, NULL);
2573     gen_logic_cc(s, zero, opsize);
2574 }
2575 
2576 DISAS_INSN(move_from_ccr)
2577 {
2578     TCGv ccr;
2579 
2580     ccr = gen_get_ccr(s);
2581     DEST_EA(env, insn, OS_WORD, ccr, NULL);
2582 }
2583 
2584 DISAS_INSN(neg)
2585 {
2586     TCGv src1;
2587     TCGv dest;
2588     TCGv addr;
2589     int opsize;
2590 
2591     opsize = insn_opsize(insn);
2592     SRC_EA(env, src1, opsize, 1, &addr);
2593     dest = tcg_temp_new();
2594     tcg_gen_neg_i32(dest, src1);
2595     set_cc_op(s, CC_OP_SUBB + opsize);
2596     gen_update_cc_add(dest, src1, opsize);
2597     tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, dest, 0);
2598     DEST_EA(env, insn, opsize, dest, &addr);
2599 }
2600 
2601 DISAS_INSN(move_to_ccr)
2602 {
2603     gen_move_to_sr(env, s, insn, true);
2604 }
2605 
2606 DISAS_INSN(not)
2607 {
2608     TCGv src1;
2609     TCGv dest;
2610     TCGv addr;
2611     int opsize;
2612 
2613     opsize = insn_opsize(insn);
2614     SRC_EA(env, src1, opsize, 1, &addr);
2615     dest = tcg_temp_new();
2616     tcg_gen_not_i32(dest, src1);
2617     DEST_EA(env, insn, opsize, dest, &addr);
2618     gen_logic_cc(s, dest, opsize);
2619 }
2620 
2621 DISAS_INSN(swap)
2622 {
2623     TCGv src1;
2624     TCGv src2;
2625     TCGv reg;
2626 
2627     src1 = tcg_temp_new();
2628     src2 = tcg_temp_new();
2629     reg = DREG(insn, 0);
2630     tcg_gen_shli_i32(src1, reg, 16);
2631     tcg_gen_shri_i32(src2, reg, 16);
2632     tcg_gen_or_i32(reg, src1, src2);
2633     gen_logic_cc(s, reg, OS_LONG);
2634 }
2635 
2636 DISAS_INSN(bkpt)
2637 {
2638 #if defined(CONFIG_SOFTMMU)
2639     gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2640 #else
2641     gen_exception(s, s->base.pc_next, EXCP_DEBUG);
2642 #endif
2643 }
2644 
2645 DISAS_INSN(pea)
2646 {
2647     TCGv tmp;
2648 
2649     tmp = gen_lea(env, s, insn, OS_LONG);
2650     if (IS_NULL_QREG(tmp)) {
2651         gen_addr_fault(s);
2652         return;
2653     }
2654     gen_push(s, tmp);
2655 }
2656 
2657 DISAS_INSN(ext)
2658 {
2659     int op;
2660     TCGv reg;
2661     TCGv tmp;
2662 
2663     reg = DREG(insn, 0);
2664     op = (insn >> 6) & 7;
2665     tmp = tcg_temp_new();
2666     if (op == 3)
2667         tcg_gen_ext16s_i32(tmp, reg);
2668     else
2669         tcg_gen_ext8s_i32(tmp, reg);
2670     if (op == 2)
2671         gen_partset_reg(OS_WORD, reg, tmp);
2672     else
2673         tcg_gen_mov_i32(reg, tmp);
2674     gen_logic_cc(s, tmp, OS_LONG);
2675 }
2676 
2677 DISAS_INSN(tst)
2678 {
2679     int opsize;
2680     TCGv tmp;
2681 
2682     opsize = insn_opsize(insn);
2683     SRC_EA(env, tmp, opsize, 1, NULL);
2684     gen_logic_cc(s, tmp, opsize);
2685 }
2686 
2687 DISAS_INSN(pulse)
2688 {
2689   /* Implemented as a NOP.  */
2690 }
2691 
2692 DISAS_INSN(illegal)
2693 {
2694     gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2695 }
2696 
2697 DISAS_INSN(tas)
2698 {
2699     int mode = extract32(insn, 3, 3);
2700     int reg0 = REG(insn, 0);
2701 
2702     if (mode == 0) {
2703         /* data register direct */
2704         TCGv dest = cpu_dregs[reg0];
2705         gen_logic_cc(s, dest, OS_BYTE);
2706         tcg_gen_ori_tl(dest, dest, 0x80);
2707     } else {
2708         TCGv src1, addr;
2709 
2710         addr = gen_lea_mode(env, s, mode, reg0, OS_BYTE);
2711         if (IS_NULL_QREG(addr)) {
2712             gen_addr_fault(s);
2713             return;
2714         }
2715         src1 = tcg_temp_new();
2716         tcg_gen_atomic_fetch_or_tl(src1, addr, tcg_constant_tl(0x80),
2717                                    IS_USER(s), MO_SB);
2718         gen_logic_cc(s, src1, OS_BYTE);
2719 
2720         switch (mode) {
2721         case 3: /* Indirect postincrement.  */
2722             tcg_gen_addi_i32(AREG(insn, 0), addr, 1);
2723             break;
2724         case 4: /* Indirect predecrememnt.  */
2725             tcg_gen_mov_i32(AREG(insn, 0), addr);
2726             break;
2727         }
2728     }
2729 }
2730 
2731 DISAS_INSN(mull)
2732 {
2733     uint16_t ext;
2734     TCGv src1;
2735     int sign;
2736 
2737     ext = read_im16(env, s);
2738 
2739     sign = ext & 0x800;
2740 
2741     if (ext & 0x400) {
2742         if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
2743             gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2744             return;
2745         }
2746 
2747         SRC_EA(env, src1, OS_LONG, 0, NULL);
2748 
2749         if (sign) {
2750             tcg_gen_muls2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2751         } else {
2752             tcg_gen_mulu2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2753         }
2754         /* if Dl == Dh, 68040 returns low word */
2755         tcg_gen_mov_i32(DREG(ext, 0), QREG_CC_N);
2756         tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_Z);
2757         tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N);
2758 
2759         tcg_gen_movi_i32(QREG_CC_V, 0);
2760         tcg_gen_movi_i32(QREG_CC_C, 0);
2761 
2762         set_cc_op(s, CC_OP_FLAGS);
2763         return;
2764     }
2765     SRC_EA(env, src1, OS_LONG, 0, NULL);
2766     if (m68k_feature(s->env, M68K_FEATURE_M68K)) {
2767         tcg_gen_movi_i32(QREG_CC_C, 0);
2768         if (sign) {
2769             tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2770             /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */
2771             tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31);
2772             tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_Z);
2773         } else {
2774             tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2775             /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */
2776             tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, QREG_CC_C);
2777         }
2778         tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
2779         tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
2780 
2781         tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
2782 
2783         set_cc_op(s, CC_OP_FLAGS);
2784     } else {
2785         /*
2786          * The upper 32 bits of the product are discarded, so
2787          * muls.l and mulu.l are functionally equivalent.
2788          */
2789         tcg_gen_mul_i32(DREG(ext, 12), src1, DREG(ext, 12));
2790         gen_logic_cc(s, DREG(ext, 12), OS_LONG);
2791     }
2792 }
2793 
2794 static void gen_link(DisasContext *s, uint16_t insn, int32_t offset)
2795 {
2796     TCGv reg;
2797     TCGv tmp;
2798 
2799     reg = AREG(insn, 0);
2800     tmp = tcg_temp_new();
2801     tcg_gen_subi_i32(tmp, QREG_SP, 4);
2802     gen_store(s, OS_LONG, tmp, reg, IS_USER(s));
2803     if ((insn & 7) != 7) {
2804         tcg_gen_mov_i32(reg, tmp);
2805     }
2806     tcg_gen_addi_i32(QREG_SP, tmp, offset);
2807 }
2808 
2809 DISAS_INSN(link)
2810 {
2811     int16_t offset;
2812 
2813     offset = read_im16(env, s);
2814     gen_link(s, insn, offset);
2815 }
2816 
2817 DISAS_INSN(linkl)
2818 {
2819     int32_t offset;
2820 
2821     offset = read_im32(env, s);
2822     gen_link(s, insn, offset);
2823 }
2824 
2825 DISAS_INSN(unlk)
2826 {
2827     TCGv src;
2828     TCGv reg;
2829     TCGv tmp;
2830 
2831     src = tcg_temp_new();
2832     reg = AREG(insn, 0);
2833     tcg_gen_mov_i32(src, reg);
2834     tmp = gen_load(s, OS_LONG, src, 0, IS_USER(s));
2835     tcg_gen_mov_i32(reg, tmp);
2836     tcg_gen_addi_i32(QREG_SP, src, 4);
2837 }
2838 
2839 #if defined(CONFIG_SOFTMMU)
2840 DISAS_INSN(reset)
2841 {
2842     if (IS_USER(s)) {
2843         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2844         return;
2845     }
2846 
2847     gen_helper_reset(cpu_env);
2848 }
2849 #endif
2850 
2851 DISAS_INSN(nop)
2852 {
2853 }
2854 
2855 DISAS_INSN(rtd)
2856 {
2857     TCGv tmp;
2858     int16_t offset = read_im16(env, s);
2859 
2860     tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2861     tcg_gen_addi_i32(QREG_SP, QREG_SP, offset + 4);
2862     gen_jmp(s, tmp);
2863 }
2864 
2865 DISAS_INSN(rtr)
2866 {
2867     TCGv tmp;
2868     TCGv ccr;
2869     TCGv sp;
2870 
2871     sp = tcg_temp_new();
2872     ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
2873     tcg_gen_addi_i32(sp, QREG_SP, 2);
2874     tmp = gen_load(s, OS_LONG, sp, 0, IS_USER(s));
2875     tcg_gen_addi_i32(QREG_SP, sp, 4);
2876 
2877     gen_set_sr(s, ccr, true);
2878 
2879     gen_jmp(s, tmp);
2880 }
2881 
2882 DISAS_INSN(rts)
2883 {
2884     TCGv tmp;
2885 
2886     tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2887     tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
2888     gen_jmp(s, tmp);
2889 }
2890 
2891 DISAS_INSN(jump)
2892 {
2893     TCGv tmp;
2894 
2895     /*
2896      * Load the target address first to ensure correct exception
2897      * behavior.
2898      */
2899     tmp = gen_lea(env, s, insn, OS_LONG);
2900     if (IS_NULL_QREG(tmp)) {
2901         gen_addr_fault(s);
2902         return;
2903     }
2904     if ((insn & 0x40) == 0) {
2905         /* jsr */
2906         gen_push(s, tcg_constant_i32(s->pc));
2907     }
2908     gen_jmp(s, tmp);
2909 }
2910 
2911 DISAS_INSN(addsubq)
2912 {
2913     TCGv src;
2914     TCGv dest;
2915     TCGv val;
2916     int imm;
2917     TCGv addr;
2918     int opsize;
2919 
2920     if ((insn & 070) == 010) {
2921         /* Operation on address register is always long.  */
2922         opsize = OS_LONG;
2923     } else {
2924         opsize = insn_opsize(insn);
2925     }
2926     SRC_EA(env, src, opsize, 1, &addr);
2927     imm = (insn >> 9) & 7;
2928     if (imm == 0) {
2929         imm = 8;
2930     }
2931     val = tcg_constant_i32(imm);
2932     dest = tcg_temp_new();
2933     tcg_gen_mov_i32(dest, src);
2934     if ((insn & 0x38) == 0x08) {
2935         /*
2936          * Don't update condition codes if the destination is an
2937          * address register.
2938          */
2939         if (insn & 0x0100) {
2940             tcg_gen_sub_i32(dest, dest, val);
2941         } else {
2942             tcg_gen_add_i32(dest, dest, val);
2943         }
2944     } else {
2945         if (insn & 0x0100) {
2946             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
2947             tcg_gen_sub_i32(dest, dest, val);
2948             set_cc_op(s, CC_OP_SUBB + opsize);
2949         } else {
2950             tcg_gen_add_i32(dest, dest, val);
2951             tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
2952             set_cc_op(s, CC_OP_ADDB + opsize);
2953         }
2954         gen_update_cc_add(dest, val, opsize);
2955     }
2956     DEST_EA(env, insn, opsize, dest, &addr);
2957 }
2958 
2959 DISAS_INSN(branch)
2960 {
2961     int32_t offset;
2962     uint32_t base;
2963     int op;
2964 
2965     base = s->pc;
2966     op = (insn >> 8) & 0xf;
2967     offset = (int8_t)insn;
2968     if (offset == 0) {
2969         offset = (int16_t)read_im16(env, s);
2970     } else if (offset == -1) {
2971         offset = read_im32(env, s);
2972     }
2973     if (op == 1) {
2974         /* bsr */
2975         gen_push(s, tcg_constant_i32(s->pc));
2976     }
2977     if (op > 1) {
2978         /* Bcc */
2979         TCGLabel *l1 = gen_new_label();
2980         gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
2981         gen_jmp_tb(s, 1, base + offset, s->base.pc_next);
2982         gen_set_label(l1);
2983         gen_jmp_tb(s, 0, s->pc, s->base.pc_next);
2984     } else {
2985         /* Unconditional branch.  */
2986         update_cc_op(s);
2987         gen_jmp_tb(s, 0, base + offset, s->base.pc_next);
2988     }
2989 }
2990 
2991 DISAS_INSN(moveq)
2992 {
2993     tcg_gen_movi_i32(DREG(insn, 9), (int8_t)insn);
2994     gen_logic_cc(s, DREG(insn, 9), OS_LONG);
2995 }
2996 
2997 DISAS_INSN(mvzs)
2998 {
2999     int opsize;
3000     TCGv src;
3001     TCGv reg;
3002 
3003     if (insn & 0x40)
3004         opsize = OS_WORD;
3005     else
3006         opsize = OS_BYTE;
3007     SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL);
3008     reg = DREG(insn, 9);
3009     tcg_gen_mov_i32(reg, src);
3010     gen_logic_cc(s, src, opsize);
3011 }
3012 
3013 DISAS_INSN(or)
3014 {
3015     TCGv reg;
3016     TCGv dest;
3017     TCGv src;
3018     TCGv addr;
3019     int opsize;
3020 
3021     opsize = insn_opsize(insn);
3022     reg = gen_extend(s, DREG(insn, 9), opsize, 0);
3023     dest = tcg_temp_new();
3024     if (insn & 0x100) {
3025         SRC_EA(env, src, opsize, 0, &addr);
3026         tcg_gen_or_i32(dest, src, reg);
3027         DEST_EA(env, insn, opsize, dest, &addr);
3028     } else {
3029         SRC_EA(env, src, opsize, 0, NULL);
3030         tcg_gen_or_i32(dest, src, reg);
3031         gen_partset_reg(opsize, DREG(insn, 9), dest);
3032     }
3033     gen_logic_cc(s, dest, opsize);
3034 }
3035 
3036 DISAS_INSN(suba)
3037 {
3038     TCGv src;
3039     TCGv reg;
3040 
3041     SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3042     reg = AREG(insn, 9);
3043     tcg_gen_sub_i32(reg, reg, src);
3044 }
3045 
3046 static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3047 {
3048     TCGv tmp, zero;
3049 
3050     gen_flush_flags(s); /* compute old Z */
3051 
3052     /*
3053      * Perform subtract with borrow.
3054      * (X, N) = dest - (src + X);
3055      */
3056 
3057     zero = tcg_constant_i32(0);
3058     tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, zero, QREG_CC_X, zero);
3059     tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, zero, QREG_CC_N, QREG_CC_X);
3060     gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3061     tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
3062 
3063     /* Compute signed-overflow for subtract.  */
3064 
3065     tmp = tcg_temp_new();
3066     tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest);
3067     tcg_gen_xor_i32(tmp, dest, src);
3068     tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp);
3069 
3070     /* Copy the rest of the results into place.  */
3071     tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3072     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3073 
3074     set_cc_op(s, CC_OP_FLAGS);
3075 
3076     /* result is in QREG_CC_N */
3077 }
3078 
3079 DISAS_INSN(subx_reg)
3080 {
3081     TCGv dest;
3082     TCGv src;
3083     int opsize;
3084 
3085     opsize = insn_opsize(insn);
3086 
3087     src = gen_extend(s, DREG(insn, 0), opsize, 1);
3088     dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3089 
3090     gen_subx(s, src, dest, opsize);
3091 
3092     gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3093 }
3094 
3095 DISAS_INSN(subx_mem)
3096 {
3097     TCGv src;
3098     TCGv addr_src;
3099     TCGv dest;
3100     TCGv addr_dest;
3101     int opsize;
3102 
3103     opsize = insn_opsize(insn);
3104 
3105     addr_src = AREG(insn, 0);
3106     tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3107     src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3108 
3109     addr_dest = AREG(insn, 9);
3110     tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3111     dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3112 
3113     gen_subx(s, src, dest, opsize);
3114 
3115     gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3116 }
3117 
3118 DISAS_INSN(mov3q)
3119 {
3120     TCGv src;
3121     int val;
3122 
3123     val = (insn >> 9) & 7;
3124     if (val == 0) {
3125         val = -1;
3126     }
3127     src = tcg_constant_i32(val);
3128     gen_logic_cc(s, src, OS_LONG);
3129     DEST_EA(env, insn, OS_LONG, src, NULL);
3130 }
3131 
3132 DISAS_INSN(cmp)
3133 {
3134     TCGv src;
3135     TCGv reg;
3136     int opsize;
3137 
3138     opsize = insn_opsize(insn);
3139     SRC_EA(env, src, opsize, 1, NULL);
3140     reg = gen_extend(s, DREG(insn, 9), opsize, 1);
3141     gen_update_cc_cmp(s, reg, src, opsize);
3142 }
3143 
3144 DISAS_INSN(cmpa)
3145 {
3146     int opsize;
3147     TCGv src;
3148     TCGv reg;
3149 
3150     if (insn & 0x100) {
3151         opsize = OS_LONG;
3152     } else {
3153         opsize = OS_WORD;
3154     }
3155     SRC_EA(env, src, opsize, 1, NULL);
3156     reg = AREG(insn, 9);
3157     gen_update_cc_cmp(s, reg, src, OS_LONG);
3158 }
3159 
3160 DISAS_INSN(cmpm)
3161 {
3162     int opsize = insn_opsize(insn);
3163     TCGv src, dst;
3164 
3165     /* Post-increment load (mode 3) from Ay.  */
3166     src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize,
3167                       NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3168     /* Post-increment load (mode 3) from Ax.  */
3169     dst = gen_ea_mode(env, s, 3, REG(insn, 9), opsize,
3170                       NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3171 
3172     gen_update_cc_cmp(s, dst, src, opsize);
3173 }
3174 
3175 DISAS_INSN(eor)
3176 {
3177     TCGv src;
3178     TCGv dest;
3179     TCGv addr;
3180     int opsize;
3181 
3182     opsize = insn_opsize(insn);
3183 
3184     SRC_EA(env, src, opsize, 0, &addr);
3185     dest = tcg_temp_new();
3186     tcg_gen_xor_i32(dest, src, DREG(insn, 9));
3187     gen_logic_cc(s, dest, opsize);
3188     DEST_EA(env, insn, opsize, dest, &addr);
3189 }
3190 
3191 static void do_exg(TCGv reg1, TCGv reg2)
3192 {
3193     TCGv temp = tcg_temp_new();
3194     tcg_gen_mov_i32(temp, reg1);
3195     tcg_gen_mov_i32(reg1, reg2);
3196     tcg_gen_mov_i32(reg2, temp);
3197 }
3198 
3199 DISAS_INSN(exg_dd)
3200 {
3201     /* exchange Dx and Dy */
3202     do_exg(DREG(insn, 9), DREG(insn, 0));
3203 }
3204 
3205 DISAS_INSN(exg_aa)
3206 {
3207     /* exchange Ax and Ay */
3208     do_exg(AREG(insn, 9), AREG(insn, 0));
3209 }
3210 
3211 DISAS_INSN(exg_da)
3212 {
3213     /* exchange Dx and Ay */
3214     do_exg(DREG(insn, 9), AREG(insn, 0));
3215 }
3216 
3217 DISAS_INSN(and)
3218 {
3219     TCGv src;
3220     TCGv reg;
3221     TCGv dest;
3222     TCGv addr;
3223     int opsize;
3224 
3225     dest = tcg_temp_new();
3226 
3227     opsize = insn_opsize(insn);
3228     reg = DREG(insn, 9);
3229     if (insn & 0x100) {
3230         SRC_EA(env, src, opsize, 0, &addr);
3231         tcg_gen_and_i32(dest, src, reg);
3232         DEST_EA(env, insn, opsize, dest, &addr);
3233     } else {
3234         SRC_EA(env, src, opsize, 0, NULL);
3235         tcg_gen_and_i32(dest, src, reg);
3236         gen_partset_reg(opsize, reg, dest);
3237     }
3238     gen_logic_cc(s, dest, opsize);
3239 }
3240 
3241 DISAS_INSN(adda)
3242 {
3243     TCGv src;
3244     TCGv reg;
3245 
3246     SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3247     reg = AREG(insn, 9);
3248     tcg_gen_add_i32(reg, reg, src);
3249 }
3250 
3251 static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3252 {
3253     TCGv tmp, zero;
3254 
3255     gen_flush_flags(s); /* compute old Z */
3256 
3257     /*
3258      * Perform addition with carry.
3259      * (X, N) = src + dest + X;
3260      */
3261 
3262     zero = tcg_constant_i32(0);
3263     tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, zero, dest, zero);
3264     tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, zero);
3265     gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3266 
3267     /* Compute signed-overflow for addition.  */
3268 
3269     tmp = tcg_temp_new();
3270     tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3271     tcg_gen_xor_i32(tmp, dest, src);
3272     tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp);
3273 
3274     /* Copy the rest of the results into place.  */
3275     tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3276     tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3277 
3278     set_cc_op(s, CC_OP_FLAGS);
3279 
3280     /* result is in QREG_CC_N */
3281 }
3282 
3283 DISAS_INSN(addx_reg)
3284 {
3285     TCGv dest;
3286     TCGv src;
3287     int opsize;
3288 
3289     opsize = insn_opsize(insn);
3290 
3291     dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3292     src = gen_extend(s, DREG(insn, 0), opsize, 1);
3293 
3294     gen_addx(s, src, dest, opsize);
3295 
3296     gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3297 }
3298 
3299 DISAS_INSN(addx_mem)
3300 {
3301     TCGv src;
3302     TCGv addr_src;
3303     TCGv dest;
3304     TCGv addr_dest;
3305     int opsize;
3306 
3307     opsize = insn_opsize(insn);
3308 
3309     addr_src = AREG(insn, 0);
3310     tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3311     src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3312 
3313     addr_dest = AREG(insn, 9);
3314     tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3315     dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3316 
3317     gen_addx(s, src, dest, opsize);
3318 
3319     gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3320 }
3321 
3322 static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
3323 {
3324     int count = (insn >> 9) & 7;
3325     int logical = insn & 8;
3326     int left = insn & 0x100;
3327     int bits = opsize_bytes(opsize) * 8;
3328     TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3329 
3330     if (count == 0) {
3331         count = 8;
3332     }
3333 
3334     tcg_gen_movi_i32(QREG_CC_V, 0);
3335     if (left) {
3336         tcg_gen_shri_i32(QREG_CC_C, reg, bits - count);
3337         tcg_gen_shli_i32(QREG_CC_N, reg, count);
3338 
3339         /*
3340          * Note that ColdFire always clears V (done above),
3341          * while M68000 sets if the most significant bit is changed at
3342          * any time during the shift operation.
3343          */
3344         if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3345             /* if shift count >= bits, V is (reg != 0) */
3346             if (count >= bits) {
3347                 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V);
3348             } else {
3349                 TCGv t0 = tcg_temp_new();
3350                 tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1);
3351                 tcg_gen_sari_i32(t0, reg, bits - count - 1);
3352                 tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0);
3353             }
3354             tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
3355         }
3356     } else {
3357         tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
3358         if (logical) {
3359             tcg_gen_shri_i32(QREG_CC_N, reg, count);
3360         } else {
3361             tcg_gen_sari_i32(QREG_CC_N, reg, count);
3362         }
3363     }
3364 
3365     gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3366     tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3367     tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3368     tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3369 
3370     gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3371     set_cc_op(s, CC_OP_FLAGS);
3372 }
3373 
3374 static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
3375 {
3376     int logical = insn & 8;
3377     int left = insn & 0x100;
3378     int bits = opsize_bytes(opsize) * 8;
3379     TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3380     TCGv s32;
3381     TCGv_i64 t64, s64;
3382 
3383     t64 = tcg_temp_new_i64();
3384     s64 = tcg_temp_new_i64();
3385     s32 = tcg_temp_new();
3386 
3387     /*
3388      * Note that m68k truncates the shift count modulo 64, not 32.
3389      * In addition, a 64-bit shift makes it easy to find "the last
3390      * bit shifted out", for the carry flag.
3391      */
3392     tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
3393     tcg_gen_extu_i32_i64(s64, s32);
3394     tcg_gen_extu_i32_i64(t64, reg);
3395 
3396     /* Optimistically set V=0.  Also used as a zero source below.  */
3397     tcg_gen_movi_i32(QREG_CC_V, 0);
3398     if (left) {
3399         tcg_gen_shl_i64(t64, t64, s64);
3400 
3401         if (opsize == OS_LONG) {
3402             tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
3403             /* Note that C=0 if shift count is 0, and we get that for free.  */
3404         } else {
3405             TCGv zero = tcg_constant_i32(0);
3406             tcg_gen_extrl_i64_i32(QREG_CC_N, t64);
3407             tcg_gen_shri_i32(QREG_CC_C, QREG_CC_N, bits);
3408             tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3409                                 s32, zero, zero, QREG_CC_C);
3410         }
3411         tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3412 
3413         /* X = C, but only if the shift count was non-zero.  */
3414         tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3415                             QREG_CC_C, QREG_CC_X);
3416 
3417         /*
3418          * M68000 sets V if the most significant bit is changed at
3419          * any time during the shift operation.  Do this via creating
3420          * an extension of the sign bit, comparing, and discarding
3421          * the bits below the sign bit.  I.e.
3422          *     int64_t s = (intN_t)reg;
3423          *     int64_t t = (int64_t)(intN_t)reg << count;
3424          *     V = ((s ^ t) & (-1 << (bits - 1))) != 0
3425          */
3426         if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3427             TCGv_i64 tt = tcg_constant_i64(32);
3428             /* if shift is greater than 32, use 32 */
3429             tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64);
3430             /* Sign extend the input to 64 bits; re-do the shift.  */
3431             tcg_gen_ext_i32_i64(t64, reg);
3432             tcg_gen_shl_i64(s64, t64, s64);
3433             /* Clear all bits that are unchanged.  */
3434             tcg_gen_xor_i64(t64, t64, s64);
3435             /* Ignore the bits below the sign bit.  */
3436             tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
3437             /* If any bits remain set, we have overflow.  */
3438             tcg_gen_setcondi_i64(TCG_COND_NE, t64, t64, 0);
3439             tcg_gen_extrl_i64_i32(QREG_CC_V, t64);
3440             tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
3441         }
3442     } else {
3443         tcg_gen_shli_i64(t64, t64, 32);
3444         if (logical) {
3445             tcg_gen_shr_i64(t64, t64, s64);
3446         } else {
3447             tcg_gen_sar_i64(t64, t64, s64);
3448         }
3449         tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
3450 
3451         /* Note that C=0 if shift count is 0, and we get that for free.  */
3452         tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
3453 
3454         /* X = C, but only if the shift count was non-zero.  */
3455         tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3456                             QREG_CC_C, QREG_CC_X);
3457     }
3458     gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3459     tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3460 
3461     /* Write back the result.  */
3462     gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3463     set_cc_op(s, CC_OP_FLAGS);
3464 }
3465 
3466 DISAS_INSN(shift8_im)
3467 {
3468     shift_im(s, insn, OS_BYTE);
3469 }
3470 
3471 DISAS_INSN(shift16_im)
3472 {
3473     shift_im(s, insn, OS_WORD);
3474 }
3475 
3476 DISAS_INSN(shift_im)
3477 {
3478     shift_im(s, insn, OS_LONG);
3479 }
3480 
3481 DISAS_INSN(shift8_reg)
3482 {
3483     shift_reg(s, insn, OS_BYTE);
3484 }
3485 
3486 DISAS_INSN(shift16_reg)
3487 {
3488     shift_reg(s, insn, OS_WORD);
3489 }
3490 
3491 DISAS_INSN(shift_reg)
3492 {
3493     shift_reg(s, insn, OS_LONG);
3494 }
3495 
3496 DISAS_INSN(shift_mem)
3497 {
3498     int logical = insn & 8;
3499     int left = insn & 0x100;
3500     TCGv src;
3501     TCGv addr;
3502 
3503     SRC_EA(env, src, OS_WORD, !logical, &addr);
3504     tcg_gen_movi_i32(QREG_CC_V, 0);
3505     if (left) {
3506         tcg_gen_shri_i32(QREG_CC_C, src, 15);
3507         tcg_gen_shli_i32(QREG_CC_N, src, 1);
3508 
3509         /*
3510          * Note that ColdFire always clears V,
3511          * while M68000 sets if the most significant bit is changed at
3512          * any time during the shift operation
3513          */
3514         if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3515             src = gen_extend(s, src, OS_WORD, 1);
3516             tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3517         }
3518     } else {
3519         tcg_gen_mov_i32(QREG_CC_C, src);
3520         if (logical) {
3521             tcg_gen_shri_i32(QREG_CC_N, src, 1);
3522         } else {
3523             tcg_gen_sari_i32(QREG_CC_N, src, 1);
3524         }
3525     }
3526 
3527     gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1);
3528     tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3529     tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3530     tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3531 
3532     DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr);
3533     set_cc_op(s, CC_OP_FLAGS);
3534 }
3535 
3536 static void rotate(TCGv reg, TCGv shift, int left, int size)
3537 {
3538     switch (size) {
3539     case 8:
3540         /* Replicate the 8-bit input so that a 32-bit rotate works.  */
3541         tcg_gen_ext8u_i32(reg, reg);
3542         tcg_gen_muli_i32(reg, reg, 0x01010101);
3543         goto do_long;
3544     case 16:
3545         /* Replicate the 16-bit input so that a 32-bit rotate works.  */
3546         tcg_gen_deposit_i32(reg, reg, reg, 16, 16);
3547         goto do_long;
3548     do_long:
3549     default:
3550         if (left) {
3551             tcg_gen_rotl_i32(reg, reg, shift);
3552         } else {
3553             tcg_gen_rotr_i32(reg, reg, shift);
3554         }
3555     }
3556 
3557     /* compute flags */
3558 
3559     switch (size) {
3560     case 8:
3561         tcg_gen_ext8s_i32(reg, reg);
3562         break;
3563     case 16:
3564         tcg_gen_ext16s_i32(reg, reg);
3565         break;
3566     default:
3567         break;
3568     }
3569 
3570     /* QREG_CC_X is not affected */
3571 
3572     tcg_gen_mov_i32(QREG_CC_N, reg);
3573     tcg_gen_mov_i32(QREG_CC_Z, reg);
3574 
3575     if (left) {
3576         tcg_gen_andi_i32(QREG_CC_C, reg, 1);
3577     } else {
3578         tcg_gen_shri_i32(QREG_CC_C, reg, 31);
3579     }
3580 
3581     tcg_gen_movi_i32(QREG_CC_V, 0); /* always cleared */
3582 }
3583 
3584 static void rotate_x_flags(TCGv reg, TCGv X, int size)
3585 {
3586     switch (size) {
3587     case 8:
3588         tcg_gen_ext8s_i32(reg, reg);
3589         break;
3590     case 16:
3591         tcg_gen_ext16s_i32(reg, reg);
3592         break;
3593     default:
3594         break;
3595     }
3596     tcg_gen_mov_i32(QREG_CC_N, reg);
3597     tcg_gen_mov_i32(QREG_CC_Z, reg);
3598     tcg_gen_mov_i32(QREG_CC_X, X);
3599     tcg_gen_mov_i32(QREG_CC_C, X);
3600     tcg_gen_movi_i32(QREG_CC_V, 0);
3601 }
3602 
3603 /* Result of rotate_x() is valid if 0 <= shift <= size */
3604 static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size)
3605 {
3606     TCGv X, shl, shr, shx, sz, zero;
3607 
3608     sz = tcg_constant_i32(size);
3609 
3610     shr = tcg_temp_new();
3611     shl = tcg_temp_new();
3612     shx = tcg_temp_new();
3613     if (left) {
3614         tcg_gen_mov_i32(shl, shift);      /* shl = shift */
3615         tcg_gen_movi_i32(shr, size + 1);
3616         tcg_gen_sub_i32(shr, shr, shift); /* shr = size + 1 - shift */
3617         tcg_gen_subi_i32(shx, shift, 1);  /* shx = shift - 1 */
3618         /* shx = shx < 0 ? size : shx; */
3619         zero = tcg_constant_i32(0);
3620         tcg_gen_movcond_i32(TCG_COND_LT, shx, shx, zero, sz, shx);
3621     } else {
3622         tcg_gen_mov_i32(shr, shift);      /* shr = shift */
3623         tcg_gen_movi_i32(shl, size + 1);
3624         tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */
3625         tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */
3626     }
3627 
3628     /* reg = (reg << shl) | (reg >> shr) | (x << shx); */
3629 
3630     tcg_gen_shl_i32(shl, reg, shl);
3631     tcg_gen_shr_i32(shr, reg, shr);
3632     tcg_gen_or_i32(reg, shl, shr);
3633     tcg_gen_shl_i32(shx, QREG_CC_X, shx);
3634     tcg_gen_or_i32(reg, reg, shx);
3635 
3636     /* X = (reg >> size) & 1 */
3637 
3638     X = tcg_temp_new();
3639     tcg_gen_extract_i32(X, reg, size, 1);
3640 
3641     return X;
3642 }
3643 
3644 /* Result of rotate32_x() is valid if 0 <= shift < 33 */
3645 static TCGv rotate32_x(TCGv reg, TCGv shift, int left)
3646 {
3647     TCGv_i64 t0, shift64;
3648     TCGv X, lo, hi, zero;
3649 
3650     shift64 = tcg_temp_new_i64();
3651     tcg_gen_extu_i32_i64(shift64, shift);
3652 
3653     t0 = tcg_temp_new_i64();
3654 
3655     X = tcg_temp_new();
3656     lo = tcg_temp_new();
3657     hi = tcg_temp_new();
3658 
3659     if (left) {
3660         /* create [reg:X:..] */
3661 
3662         tcg_gen_shli_i32(lo, QREG_CC_X, 31);
3663         tcg_gen_concat_i32_i64(t0, lo, reg);
3664 
3665         /* rotate */
3666 
3667         tcg_gen_rotl_i64(t0, t0, shift64);
3668 
3669         /* result is [reg:..:reg:X] */
3670 
3671         tcg_gen_extr_i64_i32(lo, hi, t0);
3672         tcg_gen_andi_i32(X, lo, 1);
3673 
3674         tcg_gen_shri_i32(lo, lo, 1);
3675     } else {
3676         /* create [..:X:reg] */
3677 
3678         tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X);
3679 
3680         tcg_gen_rotr_i64(t0, t0, shift64);
3681 
3682         /* result is value: [X:reg:..:reg] */
3683 
3684         tcg_gen_extr_i64_i32(lo, hi, t0);
3685 
3686         /* extract X */
3687 
3688         tcg_gen_shri_i32(X, hi, 31);
3689 
3690         /* extract result */
3691 
3692         tcg_gen_shli_i32(hi, hi, 1);
3693     }
3694     tcg_gen_or_i32(lo, lo, hi);
3695 
3696     /* if shift == 0, register and X are not affected */
3697 
3698     zero = tcg_constant_i32(0);
3699     tcg_gen_movcond_i32(TCG_COND_EQ, X, shift, zero, QREG_CC_X, X);
3700     tcg_gen_movcond_i32(TCG_COND_EQ, reg, shift, zero, reg, lo);
3701 
3702     return X;
3703 }
3704 
3705 DISAS_INSN(rotate_im)
3706 {
3707     TCGv shift;
3708     int tmp;
3709     int left = (insn & 0x100);
3710 
3711     tmp = (insn >> 9) & 7;
3712     if (tmp == 0) {
3713         tmp = 8;
3714     }
3715 
3716     shift = tcg_constant_i32(tmp);
3717     if (insn & 8) {
3718         rotate(DREG(insn, 0), shift, left, 32);
3719     } else {
3720         TCGv X = rotate32_x(DREG(insn, 0), shift, left);
3721         rotate_x_flags(DREG(insn, 0), X, 32);
3722     }
3723 
3724     set_cc_op(s, CC_OP_FLAGS);
3725 }
3726 
3727 DISAS_INSN(rotate8_im)
3728 {
3729     int left = (insn & 0x100);
3730     TCGv reg;
3731     TCGv shift;
3732     int tmp;
3733 
3734     reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3735 
3736     tmp = (insn >> 9) & 7;
3737     if (tmp == 0) {
3738         tmp = 8;
3739     }
3740 
3741     shift = tcg_constant_i32(tmp);
3742     if (insn & 8) {
3743         rotate(reg, shift, left, 8);
3744     } else {
3745         TCGv X = rotate_x(reg, shift, left, 8);
3746         rotate_x_flags(reg, X, 8);
3747     }
3748     gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3749     set_cc_op(s, CC_OP_FLAGS);
3750 }
3751 
3752 DISAS_INSN(rotate16_im)
3753 {
3754     int left = (insn & 0x100);
3755     TCGv reg;
3756     TCGv shift;
3757     int tmp;
3758 
3759     reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
3760     tmp = (insn >> 9) & 7;
3761     if (tmp == 0) {
3762         tmp = 8;
3763     }
3764 
3765     shift = tcg_constant_i32(tmp);
3766     if (insn & 8) {
3767         rotate(reg, shift, left, 16);
3768     } else {
3769         TCGv X = rotate_x(reg, shift, left, 16);
3770         rotate_x_flags(reg, X, 16);
3771     }
3772     gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
3773     set_cc_op(s, CC_OP_FLAGS);
3774 }
3775 
3776 DISAS_INSN(rotate_reg)
3777 {
3778     TCGv reg;
3779     TCGv src;
3780     TCGv t0, t1;
3781     int left = (insn & 0x100);
3782 
3783     reg = DREG(insn, 0);
3784     src = DREG(insn, 9);
3785     /* shift in [0..63] */
3786     t0 = tcg_temp_new();
3787     tcg_gen_andi_i32(t0, src, 63);
3788     t1 = tcg_temp_new_i32();
3789     if (insn & 8) {
3790         tcg_gen_andi_i32(t1, src, 31);
3791         rotate(reg, t1, left, 32);
3792         /* if shift == 0, clear C */
3793         tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3794                             t0, QREG_CC_V /* 0 */,
3795                             QREG_CC_V /* 0 */, QREG_CC_C);
3796     } else {
3797         TCGv X;
3798         /* modulo 33 */
3799         tcg_gen_movi_i32(t1, 33);
3800         tcg_gen_remu_i32(t1, t0, t1);
3801         X = rotate32_x(DREG(insn, 0), t1, left);
3802         rotate_x_flags(DREG(insn, 0), X, 32);
3803     }
3804     set_cc_op(s, CC_OP_FLAGS);
3805 }
3806 
3807 DISAS_INSN(rotate8_reg)
3808 {
3809     TCGv reg;
3810     TCGv src;
3811     TCGv t0, t1;
3812     int left = (insn & 0x100);
3813 
3814     reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3815     src = DREG(insn, 9);
3816     /* shift in [0..63] */
3817     t0 = tcg_temp_new_i32();
3818     tcg_gen_andi_i32(t0, src, 63);
3819     t1 = tcg_temp_new_i32();
3820     if (insn & 8) {
3821         tcg_gen_andi_i32(t1, src, 7);
3822         rotate(reg, t1, left, 8);
3823         /* if shift == 0, clear C */
3824         tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3825                             t0, QREG_CC_V /* 0 */,
3826                             QREG_CC_V /* 0 */, QREG_CC_C);
3827     } else {
3828         TCGv X;
3829         /* modulo 9 */
3830         tcg_gen_movi_i32(t1, 9);
3831         tcg_gen_remu_i32(t1, t0, t1);
3832         X = rotate_x(reg, t1, left, 8);
3833         rotate_x_flags(reg, X, 8);
3834     }
3835     gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3836     set_cc_op(s, CC_OP_FLAGS);
3837 }
3838 
3839 DISAS_INSN(rotate16_reg)
3840 {
3841     TCGv reg;
3842     TCGv src;
3843     TCGv t0, t1;
3844     int left = (insn & 0x100);
3845 
3846     reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
3847     src = DREG(insn, 9);
3848     /* shift in [0..63] */
3849     t0 = tcg_temp_new_i32();
3850     tcg_gen_andi_i32(t0, src, 63);
3851     t1 = tcg_temp_new_i32();
3852     if (insn & 8) {
3853         tcg_gen_andi_i32(t1, src, 15);
3854         rotate(reg, t1, left, 16);
3855         /* if shift == 0, clear C */
3856         tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3857                             t0, QREG_CC_V /* 0 */,
3858                             QREG_CC_V /* 0 */, QREG_CC_C);
3859     } else {
3860         TCGv X;
3861         /* modulo 17 */
3862         tcg_gen_movi_i32(t1, 17);
3863         tcg_gen_remu_i32(t1, t0, t1);
3864         X = rotate_x(reg, t1, left, 16);
3865         rotate_x_flags(reg, X, 16);
3866     }
3867     gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
3868     set_cc_op(s, CC_OP_FLAGS);
3869 }
3870 
3871 DISAS_INSN(rotate_mem)
3872 {
3873     TCGv src;
3874     TCGv addr;
3875     TCGv shift;
3876     int left = (insn & 0x100);
3877 
3878     SRC_EA(env, src, OS_WORD, 0, &addr);
3879 
3880     shift = tcg_constant_i32(1);
3881     if (insn & 0x0200) {
3882         rotate(src, shift, left, 16);
3883     } else {
3884         TCGv X = rotate_x(src, shift, left, 16);
3885         rotate_x_flags(src, X, 16);
3886     }
3887     DEST_EA(env, insn, OS_WORD, src, &addr);
3888     set_cc_op(s, CC_OP_FLAGS);
3889 }
3890 
3891 DISAS_INSN(bfext_reg)
3892 {
3893     int ext = read_im16(env, s);
3894     int is_sign = insn & 0x200;
3895     TCGv src = DREG(insn, 0);
3896     TCGv dst = DREG(ext, 12);
3897     int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
3898     int ofs = extract32(ext, 6, 5);  /* big bit-endian */
3899     int pos = 32 - ofs - len;        /* little bit-endian */
3900     TCGv tmp = tcg_temp_new();
3901     TCGv shift;
3902 
3903     /*
3904      * In general, we're going to rotate the field so that it's at the
3905      * top of the word and then right-shift by the complement of the
3906      * width to extend the field.
3907      */
3908     if (ext & 0x20) {
3909         /* Variable width.  */
3910         if (ext & 0x800) {
3911             /* Variable offset.  */
3912             tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
3913             tcg_gen_rotl_i32(tmp, src, tmp);
3914         } else {
3915             tcg_gen_rotli_i32(tmp, src, ofs);
3916         }
3917 
3918         shift = tcg_temp_new();
3919         tcg_gen_neg_i32(shift, DREG(ext, 0));
3920         tcg_gen_andi_i32(shift, shift, 31);
3921         tcg_gen_sar_i32(QREG_CC_N, tmp, shift);
3922         if (is_sign) {
3923             tcg_gen_mov_i32(dst, QREG_CC_N);
3924         } else {
3925             tcg_gen_shr_i32(dst, tmp, shift);
3926         }
3927     } else {
3928         /* Immediate width.  */
3929         if (ext & 0x800) {
3930             /* Variable offset */
3931             tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
3932             tcg_gen_rotl_i32(tmp, src, tmp);
3933             src = tmp;
3934             pos = 32 - len;
3935         } else {
3936             /*
3937              * Immediate offset.  If the field doesn't wrap around the
3938              * end of the word, rely on (s)extract completely.
3939              */
3940             if (pos < 0) {
3941                 tcg_gen_rotli_i32(tmp, src, ofs);
3942                 src = tmp;
3943                 pos = 32 - len;
3944             }
3945         }
3946 
3947         tcg_gen_sextract_i32(QREG_CC_N, src, pos, len);
3948         if (is_sign) {
3949             tcg_gen_mov_i32(dst, QREG_CC_N);
3950         } else {
3951             tcg_gen_extract_i32(dst, src, pos, len);
3952         }
3953     }
3954 
3955     set_cc_op(s, CC_OP_LOGIC);
3956 }
3957 
3958 DISAS_INSN(bfext_mem)
3959 {
3960     int ext = read_im16(env, s);
3961     int is_sign = insn & 0x200;
3962     TCGv dest = DREG(ext, 12);
3963     TCGv addr, len, ofs;
3964 
3965     addr = gen_lea(env, s, insn, OS_UNSIZED);
3966     if (IS_NULL_QREG(addr)) {
3967         gen_addr_fault(s);
3968         return;
3969     }
3970 
3971     if (ext & 0x20) {
3972         len = DREG(ext, 0);
3973     } else {
3974         len = tcg_constant_i32(extract32(ext, 0, 5));
3975     }
3976     if (ext & 0x800) {
3977         ofs = DREG(ext, 6);
3978     } else {
3979         ofs = tcg_constant_i32(extract32(ext, 6, 5));
3980     }
3981 
3982     if (is_sign) {
3983         gen_helper_bfexts_mem(dest, cpu_env, addr, ofs, len);
3984         tcg_gen_mov_i32(QREG_CC_N, dest);
3985     } else {
3986         TCGv_i64 tmp = tcg_temp_new_i64();
3987         gen_helper_bfextu_mem(tmp, cpu_env, addr, ofs, len);
3988         tcg_gen_extr_i64_i32(dest, QREG_CC_N, tmp);
3989     }
3990     set_cc_op(s, CC_OP_LOGIC);
3991 }
3992 
3993 DISAS_INSN(bfop_reg)
3994 {
3995     int ext = read_im16(env, s);
3996     TCGv src = DREG(insn, 0);
3997     int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
3998     int ofs = extract32(ext, 6, 5);  /* big bit-endian */
3999     TCGv mask, tofs = NULL, tlen = NULL;
4000     bool is_bfffo = (insn & 0x0f00) == 0x0d00;
4001 
4002     if ((ext & 0x820) == 0) {
4003         /* Immediate width and offset.  */
4004         uint32_t maski = 0x7fffffffu >> (len - 1);
4005         if (ofs + len <= 32) {
4006             tcg_gen_shli_i32(QREG_CC_N, src, ofs);
4007         } else {
4008             tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4009         }
4010         tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski);
4011 
4012         mask = tcg_constant_i32(ror32(maski, ofs));
4013         if (is_bfffo) {
4014             tofs = tcg_constant_i32(ofs);
4015             tlen = tcg_constant_i32(len);
4016         }
4017     } else {
4018         TCGv tmp = tcg_temp_new();
4019 
4020         mask = tcg_temp_new();
4021         if (ext & 0x20) {
4022             /* Variable width */
4023             tcg_gen_subi_i32(tmp, DREG(ext, 0), 1);
4024             tcg_gen_andi_i32(tmp, tmp, 31);
4025             tcg_gen_shr_i32(mask, tcg_constant_i32(0x7fffffffu), tmp);
4026             if (is_bfffo) {
4027                 tlen = tcg_temp_new();
4028                 tcg_gen_addi_i32(tlen, tmp, 1);
4029             }
4030         } else {
4031             /* Immediate width */
4032             tcg_gen_movi_i32(mask, 0x7fffffffu >> (len - 1));
4033             if (is_bfffo) {
4034                 tlen = tcg_constant_i32(len);
4035             }
4036         }
4037 
4038         if (ext & 0x800) {
4039             /* Variable offset */
4040             tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
4041             tcg_gen_rotl_i32(QREG_CC_N, src, tmp);
4042             tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4043             tcg_gen_rotr_i32(mask, mask, tmp);
4044             if (is_bfffo) {
4045                 tofs = tmp;
4046             }
4047         } else {
4048             /* Immediate offset (and variable width) */
4049             tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4050             tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4051             tcg_gen_rotri_i32(mask, mask, ofs);
4052             if (is_bfffo) {
4053                 tofs = tcg_constant_i32(ofs);
4054             }
4055         }
4056     }
4057     set_cc_op(s, CC_OP_LOGIC);
4058 
4059     switch (insn & 0x0f00) {
4060     case 0x0a00: /* bfchg */
4061         tcg_gen_eqv_i32(src, src, mask);
4062         break;
4063     case 0x0c00: /* bfclr */
4064         tcg_gen_and_i32(src, src, mask);
4065         break;
4066     case 0x0d00: /* bfffo */
4067         gen_helper_bfffo_reg(DREG(ext, 12), QREG_CC_N, tofs, tlen);
4068         break;
4069     case 0x0e00: /* bfset */
4070         tcg_gen_orc_i32(src, src, mask);
4071         break;
4072     case 0x0800: /* bftst */
4073         /* flags already set; no other work to do.  */
4074         break;
4075     default:
4076         g_assert_not_reached();
4077     }
4078 }
4079 
4080 DISAS_INSN(bfop_mem)
4081 {
4082     int ext = read_im16(env, s);
4083     TCGv addr, len, ofs;
4084     TCGv_i64 t64;
4085 
4086     addr = gen_lea(env, s, insn, OS_UNSIZED);
4087     if (IS_NULL_QREG(addr)) {
4088         gen_addr_fault(s);
4089         return;
4090     }
4091 
4092     if (ext & 0x20) {
4093         len = DREG(ext, 0);
4094     } else {
4095         len = tcg_constant_i32(extract32(ext, 0, 5));
4096     }
4097     if (ext & 0x800) {
4098         ofs = DREG(ext, 6);
4099     } else {
4100         ofs = tcg_constant_i32(extract32(ext, 6, 5));
4101     }
4102 
4103     switch (insn & 0x0f00) {
4104     case 0x0a00: /* bfchg */
4105         gen_helper_bfchg_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4106         break;
4107     case 0x0c00: /* bfclr */
4108         gen_helper_bfclr_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4109         break;
4110     case 0x0d00: /* bfffo */
4111         t64 = tcg_temp_new_i64();
4112         gen_helper_bfffo_mem(t64, cpu_env, addr, ofs, len);
4113         tcg_gen_extr_i64_i32(DREG(ext, 12), QREG_CC_N, t64);
4114         break;
4115     case 0x0e00: /* bfset */
4116         gen_helper_bfset_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4117         break;
4118     case 0x0800: /* bftst */
4119         gen_helper_bfexts_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4120         break;
4121     default:
4122         g_assert_not_reached();
4123     }
4124     set_cc_op(s, CC_OP_LOGIC);
4125 }
4126 
4127 DISAS_INSN(bfins_reg)
4128 {
4129     int ext = read_im16(env, s);
4130     TCGv dst = DREG(insn, 0);
4131     TCGv src = DREG(ext, 12);
4132     int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4133     int ofs = extract32(ext, 6, 5);  /* big bit-endian */
4134     int pos = 32 - ofs - len;        /* little bit-endian */
4135     TCGv tmp;
4136 
4137     tmp = tcg_temp_new();
4138 
4139     if (ext & 0x20) {
4140         /* Variable width */
4141         tcg_gen_neg_i32(tmp, DREG(ext, 0));
4142         tcg_gen_andi_i32(tmp, tmp, 31);
4143         tcg_gen_shl_i32(QREG_CC_N, src, tmp);
4144     } else {
4145         /* Immediate width */
4146         tcg_gen_shli_i32(QREG_CC_N, src, 32 - len);
4147     }
4148     set_cc_op(s, CC_OP_LOGIC);
4149 
4150     /* Immediate width and offset */
4151     if ((ext & 0x820) == 0) {
4152         /* Check for suitability for deposit.  */
4153         if (pos >= 0) {
4154             tcg_gen_deposit_i32(dst, dst, src, pos, len);
4155         } else {
4156             uint32_t maski = -2U << (len - 1);
4157             uint32_t roti = (ofs + len) & 31;
4158             tcg_gen_andi_i32(tmp, src, ~maski);
4159             tcg_gen_rotri_i32(tmp, tmp, roti);
4160             tcg_gen_andi_i32(dst, dst, ror32(maski, roti));
4161             tcg_gen_or_i32(dst, dst, tmp);
4162         }
4163     } else {
4164         TCGv mask = tcg_temp_new();
4165         TCGv rot = tcg_temp_new();
4166 
4167         if (ext & 0x20) {
4168             /* Variable width */
4169             tcg_gen_subi_i32(rot, DREG(ext, 0), 1);
4170             tcg_gen_andi_i32(rot, rot, 31);
4171             tcg_gen_movi_i32(mask, -2);
4172             tcg_gen_shl_i32(mask, mask, rot);
4173             tcg_gen_mov_i32(rot, DREG(ext, 0));
4174             tcg_gen_andc_i32(tmp, src, mask);
4175         } else {
4176             /* Immediate width (variable offset) */
4177             uint32_t maski = -2U << (len - 1);
4178             tcg_gen_andi_i32(tmp, src, ~maski);
4179             tcg_gen_movi_i32(mask, maski);
4180             tcg_gen_movi_i32(rot, len & 31);
4181         }
4182         if (ext & 0x800) {
4183             /* Variable offset */
4184             tcg_gen_add_i32(rot, rot, DREG(ext, 6));
4185         } else {
4186             /* Immediate offset (variable width) */
4187             tcg_gen_addi_i32(rot, rot, ofs);
4188         }
4189         tcg_gen_andi_i32(rot, rot, 31);
4190         tcg_gen_rotr_i32(mask, mask, rot);
4191         tcg_gen_rotr_i32(tmp, tmp, rot);
4192         tcg_gen_and_i32(dst, dst, mask);
4193         tcg_gen_or_i32(dst, dst, tmp);
4194     }
4195 }
4196 
4197 DISAS_INSN(bfins_mem)
4198 {
4199     int ext = read_im16(env, s);
4200     TCGv src = DREG(ext, 12);
4201     TCGv addr, len, ofs;
4202 
4203     addr = gen_lea(env, s, insn, OS_UNSIZED);
4204     if (IS_NULL_QREG(addr)) {
4205         gen_addr_fault(s);
4206         return;
4207     }
4208 
4209     if (ext & 0x20) {
4210         len = DREG(ext, 0);
4211     } else {
4212         len = tcg_constant_i32(extract32(ext, 0, 5));
4213     }
4214     if (ext & 0x800) {
4215         ofs = DREG(ext, 6);
4216     } else {
4217         ofs = tcg_constant_i32(extract32(ext, 6, 5));
4218     }
4219 
4220     gen_helper_bfins_mem(QREG_CC_N, cpu_env, addr, src, ofs, len);
4221     set_cc_op(s, CC_OP_LOGIC);
4222 }
4223 
4224 DISAS_INSN(ff1)
4225 {
4226     TCGv reg;
4227     reg = DREG(insn, 0);
4228     gen_logic_cc(s, reg, OS_LONG);
4229     gen_helper_ff1(reg, reg);
4230 }
4231 
4232 DISAS_INSN(chk)
4233 {
4234     TCGv src, reg;
4235     int opsize;
4236 
4237     switch ((insn >> 7) & 3) {
4238     case 3:
4239         opsize = OS_WORD;
4240         break;
4241     case 2:
4242         if (m68k_feature(env, M68K_FEATURE_CHK2)) {
4243             opsize = OS_LONG;
4244             break;
4245         }
4246         /* fallthru */
4247     default:
4248         gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4249         return;
4250     }
4251     SRC_EA(env, src, opsize, 1, NULL);
4252     reg = gen_extend(s, DREG(insn, 9), opsize, 1);
4253 
4254     gen_flush_flags(s);
4255     gen_helper_chk(cpu_env, reg, src);
4256 }
4257 
4258 DISAS_INSN(chk2)
4259 {
4260     uint16_t ext;
4261     TCGv addr1, addr2, bound1, bound2, reg;
4262     int opsize;
4263 
4264     switch ((insn >> 9) & 3) {
4265     case 0:
4266         opsize = OS_BYTE;
4267         break;
4268     case 1:
4269         opsize = OS_WORD;
4270         break;
4271     case 2:
4272         opsize = OS_LONG;
4273         break;
4274     default:
4275         gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4276         return;
4277     }
4278 
4279     ext = read_im16(env, s);
4280     if ((ext & 0x0800) == 0) {
4281         gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4282         return;
4283     }
4284 
4285     addr1 = gen_lea(env, s, insn, OS_UNSIZED);
4286     addr2 = tcg_temp_new();
4287     tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
4288 
4289     bound1 = gen_load(s, opsize, addr1, 1, IS_USER(s));
4290     bound2 = gen_load(s, opsize, addr2, 1, IS_USER(s));
4291 
4292     reg = tcg_temp_new();
4293     if (ext & 0x8000) {
4294         tcg_gen_mov_i32(reg, AREG(ext, 12));
4295     } else {
4296         gen_ext(reg, DREG(ext, 12), opsize, 1);
4297     }
4298 
4299     gen_flush_flags(s);
4300     gen_helper_chk2(cpu_env, reg, bound1, bound2);
4301 }
4302 
4303 static void m68k_copy_line(TCGv dst, TCGv src, int index)
4304 {
4305     TCGv addr;
4306     TCGv_i64 t0, t1;
4307 
4308     addr = tcg_temp_new();
4309 
4310     t0 = tcg_temp_new_i64();
4311     t1 = tcg_temp_new_i64();
4312 
4313     tcg_gen_andi_i32(addr, src, ~15);
4314     tcg_gen_qemu_ld_i64(t0, addr, index, MO_TEUQ);
4315     tcg_gen_addi_i32(addr, addr, 8);
4316     tcg_gen_qemu_ld_i64(t1, addr, index, MO_TEUQ);
4317 
4318     tcg_gen_andi_i32(addr, dst, ~15);
4319     tcg_gen_qemu_st_i64(t0, addr, index, MO_TEUQ);
4320     tcg_gen_addi_i32(addr, addr, 8);
4321     tcg_gen_qemu_st_i64(t1, addr, index, MO_TEUQ);
4322 }
4323 
4324 DISAS_INSN(move16_reg)
4325 {
4326     int index = IS_USER(s);
4327     TCGv tmp;
4328     uint16_t ext;
4329 
4330     ext = read_im16(env, s);
4331     if ((ext & (1 << 15)) == 0) {
4332         gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4333     }
4334 
4335     m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);
4336 
4337     /* Ax can be Ay, so save Ay before incrementing Ax */
4338     tmp = tcg_temp_new();
4339     tcg_gen_mov_i32(tmp, AREG(ext, 12));
4340     tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
4341     tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
4342 }
4343 
4344 DISAS_INSN(move16_mem)
4345 {
4346     int index = IS_USER(s);
4347     TCGv reg, addr;
4348 
4349     reg = AREG(insn, 0);
4350     addr = tcg_constant_i32(read_im32(env, s));
4351 
4352     if ((insn >> 3) & 1) {
4353         /* MOVE16 (xxx).L, (Ay) */
4354         m68k_copy_line(reg, addr, index);
4355     } else {
4356         /* MOVE16 (Ay), (xxx).L */
4357         m68k_copy_line(addr, reg, index);
4358     }
4359 
4360     if (((insn >> 3) & 2) == 0) {
4361         /* (Ay)+ */
4362         tcg_gen_addi_i32(reg, reg, 16);
4363     }
4364 }
4365 
4366 DISAS_INSN(strldsr)
4367 {
4368     uint16_t ext;
4369     uint32_t addr;
4370 
4371     addr = s->pc - 2;
4372     ext = read_im16(env, s);
4373     if (ext != 0x46FC) {
4374         gen_exception(s, addr, EXCP_ILLEGAL);
4375         return;
4376     }
4377     ext = read_im16(env, s);
4378     if (IS_USER(s) || (ext & SR_S) == 0) {
4379         gen_exception(s, addr, EXCP_PRIVILEGE);
4380         return;
4381     }
4382     gen_push(s, gen_get_sr(s));
4383     gen_set_sr_im(s, ext, 0);
4384     gen_exit_tb(s);
4385 }
4386 
4387 DISAS_INSN(move_from_sr)
4388 {
4389     TCGv sr;
4390 
4391     if (IS_USER(s) && m68k_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV)) {
4392         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4393         return;
4394     }
4395     sr = gen_get_sr(s);
4396     DEST_EA(env, insn, OS_WORD, sr, NULL);
4397 }
4398 
4399 #if defined(CONFIG_SOFTMMU)
4400 DISAS_INSN(moves)
4401 {
4402     int opsize;
4403     uint16_t ext;
4404     TCGv reg;
4405     TCGv addr;
4406     int extend;
4407 
4408     if (IS_USER(s)) {
4409         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4410         return;
4411     }
4412 
4413     ext = read_im16(env, s);
4414 
4415     opsize = insn_opsize(insn);
4416 
4417     if (ext & 0x8000) {
4418         /* address register */
4419         reg = AREG(ext, 12);
4420         extend = 1;
4421     } else {
4422         /* data register */
4423         reg = DREG(ext, 12);
4424         extend = 0;
4425     }
4426 
4427     addr = gen_lea(env, s, insn, opsize);
4428     if (IS_NULL_QREG(addr)) {
4429         gen_addr_fault(s);
4430         return;
4431     }
4432 
4433     if (ext & 0x0800) {
4434         /* from reg to ea */
4435         gen_store(s, opsize, addr, reg, DFC_INDEX(s));
4436     } else {
4437         /* from ea to reg */
4438         TCGv tmp = gen_load(s, opsize, addr, 0, SFC_INDEX(s));
4439         if (extend) {
4440             gen_ext(reg, tmp, opsize, 1);
4441         } else {
4442             gen_partset_reg(opsize, reg, tmp);
4443         }
4444     }
4445     switch (extract32(insn, 3, 3)) {
4446     case 3: /* Indirect postincrement.  */
4447         tcg_gen_addi_i32(AREG(insn, 0), addr,
4448                          REG(insn, 0) == 7 && opsize == OS_BYTE
4449                          ? 2
4450                          : opsize_bytes(opsize));
4451         break;
4452     case 4: /* Indirect predecrememnt.  */
4453         tcg_gen_mov_i32(AREG(insn, 0), addr);
4454         break;
4455     }
4456 }
4457 
4458 DISAS_INSN(move_to_sr)
4459 {
4460     if (IS_USER(s)) {
4461         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4462         return;
4463     }
4464     gen_move_to_sr(env, s, insn, false);
4465     gen_exit_tb(s);
4466 }
4467 
4468 DISAS_INSN(move_from_usp)
4469 {
4470     if (IS_USER(s)) {
4471         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4472         return;
4473     }
4474     tcg_gen_ld_i32(AREG(insn, 0), cpu_env,
4475                    offsetof(CPUM68KState, sp[M68K_USP]));
4476 }
4477 
4478 DISAS_INSN(move_to_usp)
4479 {
4480     if (IS_USER(s)) {
4481         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4482         return;
4483     }
4484     tcg_gen_st_i32(AREG(insn, 0), cpu_env,
4485                    offsetof(CPUM68KState, sp[M68K_USP]));
4486 }
4487 
4488 DISAS_INSN(halt)
4489 {
4490     if (IS_USER(s)) {
4491         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4492         return;
4493     }
4494 
4495     gen_exception(s, s->pc, EXCP_HALT_INSN);
4496 }
4497 
4498 DISAS_INSN(stop)
4499 {
4500     uint16_t ext;
4501 
4502     if (IS_USER(s)) {
4503         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4504         return;
4505     }
4506 
4507     ext = read_im16(env, s);
4508 
4509     gen_set_sr_im(s, ext, 0);
4510     tcg_gen_movi_i32(cpu_halted, 1);
4511     gen_exception(s, s->pc, EXCP_HLT);
4512 }
4513 
4514 DISAS_INSN(rte)
4515 {
4516     if (IS_USER(s)) {
4517         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4518         return;
4519     }
4520     gen_exception(s, s->base.pc_next, EXCP_RTE);
4521 }
4522 
4523 DISAS_INSN(cf_movec)
4524 {
4525     uint16_t ext;
4526     TCGv reg;
4527 
4528     if (IS_USER(s)) {
4529         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4530         return;
4531     }
4532 
4533     ext = read_im16(env, s);
4534 
4535     if (ext & 0x8000) {
4536         reg = AREG(ext, 12);
4537     } else {
4538         reg = DREG(ext, 12);
4539     }
4540     gen_helper_cf_movec_to(cpu_env, tcg_constant_i32(ext & 0xfff), reg);
4541     gen_exit_tb(s);
4542 }
4543 
4544 DISAS_INSN(m68k_movec)
4545 {
4546     uint16_t ext;
4547     TCGv reg, creg;
4548 
4549     if (IS_USER(s)) {
4550         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4551         return;
4552     }
4553 
4554     ext = read_im16(env, s);
4555 
4556     if (ext & 0x8000) {
4557         reg = AREG(ext, 12);
4558     } else {
4559         reg = DREG(ext, 12);
4560     }
4561     creg = tcg_constant_i32(ext & 0xfff);
4562     if (insn & 1) {
4563         gen_helper_m68k_movec_to(cpu_env, creg, reg);
4564     } else {
4565         gen_helper_m68k_movec_from(reg, cpu_env, creg);
4566     }
4567     gen_exit_tb(s);
4568 }
4569 
4570 DISAS_INSN(intouch)
4571 {
4572     if (IS_USER(s)) {
4573         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4574         return;
4575     }
4576     /* ICache fetch.  Implement as no-op.  */
4577 }
4578 
4579 DISAS_INSN(cpushl)
4580 {
4581     if (IS_USER(s)) {
4582         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4583         return;
4584     }
4585     /* Cache push/invalidate.  Implement as no-op.  */
4586 }
4587 
4588 DISAS_INSN(cpush)
4589 {
4590     if (IS_USER(s)) {
4591         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4592         return;
4593     }
4594     /* Cache push/invalidate.  Implement as no-op.  */
4595 }
4596 
4597 DISAS_INSN(cinv)
4598 {
4599     if (IS_USER(s)) {
4600         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4601         return;
4602     }
4603     /* Invalidate cache line.  Implement as no-op.  */
4604 }
4605 
4606 #if defined(CONFIG_SOFTMMU)
4607 DISAS_INSN(pflush)
4608 {
4609     TCGv opmode;
4610 
4611     if (IS_USER(s)) {
4612         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4613         return;
4614     }
4615 
4616     opmode = tcg_constant_i32((insn >> 3) & 3);
4617     gen_helper_pflush(cpu_env, AREG(insn, 0), opmode);
4618 }
4619 
4620 DISAS_INSN(ptest)
4621 {
4622     TCGv is_read;
4623 
4624     if (IS_USER(s)) {
4625         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4626         return;
4627     }
4628     is_read = tcg_constant_i32((insn >> 5) & 1);
4629     gen_helper_ptest(cpu_env, AREG(insn, 0), is_read);
4630 }
4631 #endif
4632 
4633 DISAS_INSN(wddata)
4634 {
4635     gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4636 }
4637 
4638 DISAS_INSN(wdebug)
4639 {
4640     if (IS_USER(s)) {
4641         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4642         return;
4643     }
4644     /* TODO: Implement wdebug.  */
4645     cpu_abort(env_cpu(env), "WDEBUG not implemented");
4646 }
4647 #endif
4648 
4649 DISAS_INSN(trap)
4650 {
4651     gen_exception(s, s->pc, EXCP_TRAP0 + (insn & 0xf));
4652 }
4653 
4654 static void do_trapcc(DisasContext *s, DisasCompare *c)
4655 {
4656     if (c->tcond != TCG_COND_NEVER) {
4657         TCGLabel *over = NULL;
4658 
4659         update_cc_op(s);
4660 
4661         if (c->tcond != TCG_COND_ALWAYS) {
4662             /* Jump over if !c. */
4663             over = gen_new_label();
4664             tcg_gen_brcond_i32(tcg_invert_cond(c->tcond), c->v1, c->v2, over);
4665         }
4666 
4667         tcg_gen_movi_i32(QREG_PC, s->pc);
4668         gen_raise_exception_format2(s, EXCP_TRAPCC, s->base.pc_next);
4669 
4670         if (over != NULL) {
4671             gen_set_label(over);
4672             s->base.is_jmp = DISAS_NEXT;
4673         }
4674     }
4675 }
4676 
4677 DISAS_INSN(trapcc)
4678 {
4679     DisasCompare c;
4680 
4681     /* Consume and discard the immediate operand. */
4682     switch (extract32(insn, 0, 3)) {
4683     case 2: /* trapcc.w */
4684         (void)read_im16(env, s);
4685         break;
4686     case 3: /* trapcc.l */
4687         (void)read_im32(env, s);
4688         break;
4689     case 4: /* trapcc (no operand) */
4690         break;
4691     default:
4692         /* trapcc registered with only valid opmodes */
4693         g_assert_not_reached();
4694     }
4695 
4696     gen_cc_cond(&c, s, extract32(insn, 8, 4));
4697     do_trapcc(s, &c);
4698 }
4699 
4700 DISAS_INSN(trapv)
4701 {
4702     DisasCompare c;
4703 
4704     gen_cc_cond(&c, s, 9); /* V set */
4705     do_trapcc(s, &c);
4706 }
4707 
4708 static void gen_load_fcr(DisasContext *s, TCGv res, int reg)
4709 {
4710     switch (reg) {
4711     case M68K_FPIAR:
4712         tcg_gen_movi_i32(res, 0);
4713         break;
4714     case M68K_FPSR:
4715         tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpsr));
4716         break;
4717     case M68K_FPCR:
4718         tcg_gen_ld_i32(res, cpu_env, offsetof(CPUM68KState, fpcr));
4719         break;
4720     }
4721 }
4722 
4723 static void gen_store_fcr(DisasContext *s, TCGv val, int reg)
4724 {
4725     switch (reg) {
4726     case M68K_FPIAR:
4727         break;
4728     case M68K_FPSR:
4729         tcg_gen_st_i32(val, cpu_env, offsetof(CPUM68KState, fpsr));
4730         break;
4731     case M68K_FPCR:
4732         gen_helper_set_fpcr(cpu_env, val);
4733         break;
4734     }
4735 }
4736 
4737 static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg)
4738 {
4739     int index = IS_USER(s);
4740     TCGv tmp;
4741 
4742     tmp = tcg_temp_new();
4743     gen_load_fcr(s, tmp, reg);
4744     tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
4745 }
4746 
4747 static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg)
4748 {
4749     int index = IS_USER(s);
4750     TCGv tmp;
4751 
4752     tmp = tcg_temp_new();
4753     tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL);
4754     gen_store_fcr(s, tmp, reg);
4755 }
4756 
4757 
4758 static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
4759                              uint32_t insn, uint32_t ext)
4760 {
4761     int mask = (ext >> 10) & 7;
4762     int is_write = (ext >> 13) & 1;
4763     int mode = extract32(insn, 3, 3);
4764     int i;
4765     TCGv addr, tmp;
4766 
4767     switch (mode) {
4768     case 0: /* Dn */
4769         if (mask != M68K_FPIAR && mask != M68K_FPSR && mask != M68K_FPCR) {
4770             gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4771             return;
4772         }
4773         if (is_write) {
4774             gen_load_fcr(s, DREG(insn, 0), mask);
4775         } else {
4776             gen_store_fcr(s, DREG(insn, 0), mask);
4777         }
4778         return;
4779     case 1: /* An, only with FPIAR */
4780         if (mask != M68K_FPIAR) {
4781             gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4782             return;
4783         }
4784         if (is_write) {
4785             gen_load_fcr(s, AREG(insn, 0), mask);
4786         } else {
4787             gen_store_fcr(s, AREG(insn, 0), mask);
4788         }
4789         return;
4790     case 7: /* Immediate */
4791         if (REG(insn, 0) == 4) {
4792             if (is_write ||
4793                 (mask != M68K_FPIAR && mask != M68K_FPSR &&
4794                  mask != M68K_FPCR)) {
4795                 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4796                 return;
4797             }
4798             tmp = tcg_constant_i32(read_im32(env, s));
4799             gen_store_fcr(s, tmp, mask);
4800             return;
4801         }
4802         break;
4803     default:
4804         break;
4805     }
4806 
4807     tmp = gen_lea(env, s, insn, OS_LONG);
4808     if (IS_NULL_QREG(tmp)) {
4809         gen_addr_fault(s);
4810         return;
4811     }
4812 
4813     addr = tcg_temp_new();
4814     tcg_gen_mov_i32(addr, tmp);
4815 
4816     /*
4817      * mask:
4818      *
4819      * 0b100 Floating-Point Control Register
4820      * 0b010 Floating-Point Status Register
4821      * 0b001 Floating-Point Instruction Address Register
4822      *
4823      */
4824 
4825     if (is_write && mode == 4) {
4826         for (i = 2; i >= 0; i--, mask >>= 1) {
4827             if (mask & 1) {
4828                 gen_qemu_store_fcr(s, addr, 1 << i);
4829                 if (mask != 1) {
4830                     tcg_gen_subi_i32(addr, addr, opsize_bytes(OS_LONG));
4831                 }
4832             }
4833        }
4834        tcg_gen_mov_i32(AREG(insn, 0), addr);
4835     } else {
4836         for (i = 0; i < 3; i++, mask >>= 1) {
4837             if (mask & 1) {
4838                 if (is_write) {
4839                     gen_qemu_store_fcr(s, addr, 1 << i);
4840                 } else {
4841                     gen_qemu_load_fcr(s, addr, 1 << i);
4842                 }
4843                 if (mask != 1 || mode == 3) {
4844                     tcg_gen_addi_i32(addr, addr, opsize_bytes(OS_LONG));
4845                 }
4846             }
4847         }
4848         if (mode == 3) {
4849             tcg_gen_mov_i32(AREG(insn, 0), addr);
4850         }
4851     }
4852 }
4853 
4854 static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
4855                           uint32_t insn, uint32_t ext)
4856 {
4857     int opsize;
4858     TCGv addr, tmp;
4859     int mode = (ext >> 11) & 0x3;
4860     int is_load = ((ext & 0x2000) == 0);
4861 
4862     if (m68k_feature(s->env, M68K_FEATURE_FPU)) {
4863         opsize = OS_EXTENDED;
4864     } else {
4865         opsize = OS_DOUBLE;  /* FIXME */
4866     }
4867 
4868     addr = gen_lea(env, s, insn, opsize);
4869     if (IS_NULL_QREG(addr)) {
4870         gen_addr_fault(s);
4871         return;
4872     }
4873 
4874     tmp = tcg_temp_new();
4875     if (mode & 0x1) {
4876         /* Dynamic register list */
4877         tcg_gen_ext8u_i32(tmp, DREG(ext, 4));
4878     } else {
4879         /* Static register list */
4880         tcg_gen_movi_i32(tmp, ext & 0xff);
4881     }
4882 
4883     if (!is_load && (mode & 2) == 0) {
4884         /*
4885          * predecrement addressing mode
4886          * only available to store register to memory
4887          */
4888         if (opsize == OS_EXTENDED) {
4889             gen_helper_fmovemx_st_predec(tmp, cpu_env, addr, tmp);
4890         } else {
4891             gen_helper_fmovemd_st_predec(tmp, cpu_env, addr, tmp);
4892         }
4893     } else {
4894         /* postincrement addressing mode */
4895         if (opsize == OS_EXTENDED) {
4896             if (is_load) {
4897                 gen_helper_fmovemx_ld_postinc(tmp, cpu_env, addr, tmp);
4898             } else {
4899                 gen_helper_fmovemx_st_postinc(tmp, cpu_env, addr, tmp);
4900             }
4901         } else {
4902             if (is_load) {
4903                 gen_helper_fmovemd_ld_postinc(tmp, cpu_env, addr, tmp);
4904             } else {
4905                 gen_helper_fmovemd_st_postinc(tmp, cpu_env, addr, tmp);
4906             }
4907         }
4908     }
4909     if ((insn & 070) == 030 || (insn & 070) == 040) {
4910         tcg_gen_mov_i32(AREG(insn, 0), tmp);
4911     }
4912 }
4913 
4914 /*
4915  * ??? FP exceptions are not implemented.  Most exceptions are deferred until
4916  * immediately before the next FP instruction is executed.
4917  */
4918 DISAS_INSN(fpu)
4919 {
4920     uint16_t ext;
4921     int opmode;
4922     int opsize;
4923     TCGv_ptr cpu_src, cpu_dest;
4924 
4925     ext = read_im16(env, s);
4926     opmode = ext & 0x7f;
4927     switch ((ext >> 13) & 7) {
4928     case 0:
4929         break;
4930     case 1:
4931         goto undef;
4932     case 2:
4933         if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
4934             /* fmovecr */
4935             TCGv rom_offset = tcg_constant_i32(opmode);
4936             cpu_dest = gen_fp_ptr(REG(ext, 7));
4937             gen_helper_fconst(cpu_env, cpu_dest, rom_offset);
4938             return;
4939         }
4940         break;
4941     case 3: /* fmove out */
4942         cpu_src = gen_fp_ptr(REG(ext, 7));
4943         opsize = ext_opsize(ext, 10);
4944         if (gen_ea_fp(env, s, insn, opsize, cpu_src,
4945                       EA_STORE, IS_USER(s)) == -1) {
4946             gen_addr_fault(s);
4947         }
4948         gen_helper_ftst(cpu_env, cpu_src);
4949         return;
4950     case 4: /* fmove to control register.  */
4951     case 5: /* fmove from control register.  */
4952         gen_op_fmove_fcr(env, s, insn, ext);
4953         return;
4954     case 6: /* fmovem */
4955     case 7:
4956         if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) {
4957             goto undef;
4958         }
4959         gen_op_fmovem(env, s, insn, ext);
4960         return;
4961     }
4962     if (ext & (1 << 14)) {
4963         /* Source effective address.  */
4964         opsize = ext_opsize(ext, 10);
4965         cpu_src = gen_fp_result_ptr();
4966         if (gen_ea_fp(env, s, insn, opsize, cpu_src,
4967                       EA_LOADS, IS_USER(s)) == -1) {
4968             gen_addr_fault(s);
4969             return;
4970         }
4971     } else {
4972         /* Source register.  */
4973         opsize = OS_EXTENDED;
4974         cpu_src = gen_fp_ptr(REG(ext, 10));
4975     }
4976     cpu_dest = gen_fp_ptr(REG(ext, 7));
4977     switch (opmode) {
4978     case 0: /* fmove */
4979         gen_fp_move(cpu_dest, cpu_src);
4980         break;
4981     case 0x40: /* fsmove */
4982         gen_helper_fsround(cpu_env, cpu_dest, cpu_src);
4983         break;
4984     case 0x44: /* fdmove */
4985         gen_helper_fdround(cpu_env, cpu_dest, cpu_src);
4986         break;
4987     case 1: /* fint */
4988         gen_helper_firound(cpu_env, cpu_dest, cpu_src);
4989         break;
4990     case 2: /* fsinh */
4991         gen_helper_fsinh(cpu_env, cpu_dest, cpu_src);
4992         break;
4993     case 3: /* fintrz */
4994         gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src);
4995         break;
4996     case 4: /* fsqrt */
4997         gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src);
4998         break;
4999     case 0x41: /* fssqrt */
5000         gen_helper_fssqrt(cpu_env, cpu_dest, cpu_src);
5001         break;
5002     case 0x45: /* fdsqrt */
5003         gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
5004         break;
5005     case 0x06: /* flognp1 */
5006         gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
5007         break;
5008     case 0x08: /* fetoxm1 */
5009         gen_helper_fetoxm1(cpu_env, cpu_dest, cpu_src);
5010         break;
5011     case 0x09: /* ftanh */
5012         gen_helper_ftanh(cpu_env, cpu_dest, cpu_src);
5013         break;
5014     case 0x0a: /* fatan */
5015         gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
5016         break;
5017     case 0x0c: /* fasin */
5018         gen_helper_fasin(cpu_env, cpu_dest, cpu_src);
5019         break;
5020     case 0x0d: /* fatanh */
5021         gen_helper_fatanh(cpu_env, cpu_dest, cpu_src);
5022         break;
5023     case 0x0e: /* fsin */
5024         gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
5025         break;
5026     case 0x0f: /* ftan */
5027         gen_helper_ftan(cpu_env, cpu_dest, cpu_src);
5028         break;
5029     case 0x10: /* fetox */
5030         gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
5031         break;
5032     case 0x11: /* ftwotox */
5033         gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src);
5034         break;
5035     case 0x12: /* ftentox */
5036         gen_helper_ftentox(cpu_env, cpu_dest, cpu_src);
5037         break;
5038     case 0x14: /* flogn */
5039         gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
5040         break;
5041     case 0x15: /* flog10 */
5042         gen_helper_flog10(cpu_env, cpu_dest, cpu_src);
5043         break;
5044     case 0x16: /* flog2 */
5045         gen_helper_flog2(cpu_env, cpu_dest, cpu_src);
5046         break;
5047     case 0x18: /* fabs */
5048         gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
5049         break;
5050     case 0x58: /* fsabs */
5051         gen_helper_fsabs(cpu_env, cpu_dest, cpu_src);
5052         break;
5053     case 0x5c: /* fdabs */
5054         gen_helper_fdabs(cpu_env, cpu_dest, cpu_src);
5055         break;
5056     case 0x19: /* fcosh */
5057         gen_helper_fcosh(cpu_env, cpu_dest, cpu_src);
5058         break;
5059     case 0x1a: /* fneg */
5060         gen_helper_fneg(cpu_env, cpu_dest, cpu_src);
5061         break;
5062     case 0x5a: /* fsneg */
5063         gen_helper_fsneg(cpu_env, cpu_dest, cpu_src);
5064         break;
5065     case 0x5e: /* fdneg */
5066         gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
5067         break;
5068     case 0x1c: /* facos */
5069         gen_helper_facos(cpu_env, cpu_dest, cpu_src);
5070         break;
5071     case 0x1d: /* fcos */
5072         gen_helper_fcos(cpu_env, cpu_dest, cpu_src);
5073         break;
5074     case 0x1e: /* fgetexp */
5075         gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src);
5076         break;
5077     case 0x1f: /* fgetman */
5078         gen_helper_fgetman(cpu_env, cpu_dest, cpu_src);
5079         break;
5080     case 0x20: /* fdiv */
5081         gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5082         break;
5083     case 0x60: /* fsdiv */
5084         gen_helper_fsdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5085         break;
5086     case 0x64: /* fddiv */
5087         gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5088         break;
5089     case 0x21: /* fmod */
5090         gen_helper_fmod(cpu_env, cpu_dest, cpu_src, cpu_dest);
5091         break;
5092     case 0x22: /* fadd */
5093         gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5094         break;
5095     case 0x62: /* fsadd */
5096         gen_helper_fsadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5097         break;
5098     case 0x66: /* fdadd */
5099         gen_helper_fdadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5100         break;
5101     case 0x23: /* fmul */
5102         gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5103         break;
5104     case 0x63: /* fsmul */
5105         gen_helper_fsmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5106         break;
5107     case 0x67: /* fdmul */
5108         gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5109         break;
5110     case 0x24: /* fsgldiv */
5111         gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5112         break;
5113     case 0x25: /* frem */
5114         gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest);
5115         break;
5116     case 0x26: /* fscale */
5117         gen_helper_fscale(cpu_env, cpu_dest, cpu_src, cpu_dest);
5118         break;
5119     case 0x27: /* fsglmul */
5120         gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5121         break;
5122     case 0x28: /* fsub */
5123         gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5124         break;
5125     case 0x68: /* fssub */
5126         gen_helper_fssub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5127         break;
5128     case 0x6c: /* fdsub */
5129         gen_helper_fdsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5130         break;
5131     case 0x30: case 0x31: case 0x32:
5132     case 0x33: case 0x34: case 0x35:
5133     case 0x36: case 0x37: {
5134             TCGv_ptr cpu_dest2 = gen_fp_ptr(REG(ext, 0));
5135             gen_helper_fsincos(cpu_env, cpu_dest, cpu_dest2, cpu_src);
5136         }
5137         break;
5138     case 0x38: /* fcmp */
5139         gen_helper_fcmp(cpu_env, cpu_src, cpu_dest);
5140         return;
5141     case 0x3a: /* ftst */
5142         gen_helper_ftst(cpu_env, cpu_src);
5143         return;
5144     default:
5145         goto undef;
5146     }
5147     gen_helper_ftst(cpu_env, cpu_dest);
5148     return;
5149 undef:
5150     /* FIXME: Is this right for offset addressing modes?  */
5151     s->pc -= 2;
5152     disas_undef_fpu(env, s, insn);
5153 }
5154 
5155 static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond)
5156 {
5157     TCGv fpsr;
5158 
5159     c->v2 = tcg_constant_i32(0);
5160     /* TODO: Raise BSUN exception.  */
5161     fpsr = tcg_temp_new();
5162     gen_load_fcr(s, fpsr, M68K_FPSR);
5163     switch (cond) {
5164     case 0:  /* False */
5165     case 16: /* Signaling False */
5166         c->v1 = c->v2;
5167         c->tcond = TCG_COND_NEVER;
5168         break;
5169     case 1:  /* EQual Z */
5170     case 17: /* Signaling EQual Z */
5171         c->v1 = tcg_temp_new();
5172         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5173         c->tcond = TCG_COND_NE;
5174         break;
5175     case 2:  /* Ordered Greater Than !(A || Z || N) */
5176     case 18: /* Greater Than !(A || Z || N) */
5177         c->v1 = tcg_temp_new();
5178         tcg_gen_andi_i32(c->v1, fpsr,
5179                          FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5180         c->tcond = TCG_COND_EQ;
5181         break;
5182     case 3:  /* Ordered Greater than or Equal Z || !(A || N) */
5183     case 19: /* Greater than or Equal Z || !(A || N) */
5184         c->v1 = tcg_temp_new();
5185         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5186         tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A));
5187         tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_Z | FPSR_CC_N);
5188         tcg_gen_or_i32(c->v1, c->v1, fpsr);
5189         tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5190         c->tcond = TCG_COND_NE;
5191         break;
5192     case 4:  /* Ordered Less Than !(!N || A || Z); */
5193     case 20: /* Less Than !(!N || A || Z); */
5194         c->v1 = tcg_temp_new();
5195         tcg_gen_xori_i32(c->v1, fpsr, FPSR_CC_N);
5196         tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_N | FPSR_CC_A | FPSR_CC_Z);
5197         c->tcond = TCG_COND_EQ;
5198         break;
5199     case 5:  /* Ordered Less than or Equal Z || (N && !A) */
5200     case 21: /* Less than or Equal Z || (N && !A) */
5201         c->v1 = tcg_temp_new();
5202         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5203         tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_A));
5204         tcg_gen_andc_i32(c->v1, fpsr, c->v1);
5205         tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_Z | FPSR_CC_N);
5206         c->tcond = TCG_COND_NE;
5207         break;
5208     case 6:  /* Ordered Greater or Less than !(A || Z) */
5209     case 22: /* Greater or Less than !(A || Z) */
5210         c->v1 = tcg_temp_new();
5211         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
5212         c->tcond = TCG_COND_EQ;
5213         break;
5214     case 7:  /* Ordered !A */
5215     case 23: /* Greater, Less or Equal !A */
5216         c->v1 = tcg_temp_new();
5217         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5218         c->tcond = TCG_COND_EQ;
5219         break;
5220     case 8:  /* Unordered A */
5221     case 24: /* Not Greater, Less or Equal A */
5222         c->v1 = tcg_temp_new();
5223         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A);
5224         c->tcond = TCG_COND_NE;
5225         break;
5226     case 9:  /* Unordered or Equal A || Z */
5227     case 25: /* Not Greater or Less then A || Z */
5228         c->v1 = tcg_temp_new();
5229         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z);
5230         c->tcond = TCG_COND_NE;
5231         break;
5232     case 10: /* Unordered or Greater Than A || !(N || Z)) */
5233     case 26: /* Not Less or Equal A || !(N || Z)) */
5234         c->v1 = tcg_temp_new();
5235         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5236         tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z));
5237         tcg_gen_andi_i32(fpsr, fpsr, FPSR_CC_A | FPSR_CC_N);
5238         tcg_gen_or_i32(c->v1, c->v1, fpsr);
5239         tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5240         c->tcond = TCG_COND_NE;
5241         break;
5242     case 11: /* Unordered or Greater or Equal A || Z || !N */
5243     case 27: /* Not Less Than A || Z || !N */
5244         c->v1 = tcg_temp_new();
5245         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5246         tcg_gen_xori_i32(c->v1, c->v1, FPSR_CC_N);
5247         c->tcond = TCG_COND_NE;
5248         break;
5249     case 12: /* Unordered or Less Than A || (N && !Z) */
5250     case 28: /* Not Greater than or Equal A || (N && !Z) */
5251         c->v1 = tcg_temp_new();
5252         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5253         tcg_gen_shli_i32(c->v1, c->v1, ctz32(FPSR_CC_N) - ctz32(FPSR_CC_Z));
5254         tcg_gen_andc_i32(c->v1, fpsr, c->v1);
5255         tcg_gen_andi_i32(c->v1, c->v1, FPSR_CC_A | FPSR_CC_N);
5256         c->tcond = TCG_COND_NE;
5257         break;
5258     case 13: /* Unordered or Less or Equal A || Z || N */
5259     case 29: /* Not Greater Than A || Z || N */
5260         c->v1 = tcg_temp_new();
5261         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_A | FPSR_CC_Z | FPSR_CC_N);
5262         c->tcond = TCG_COND_NE;
5263         break;
5264     case 14: /* Not Equal !Z */
5265     case 30: /* Signaling Not Equal !Z */
5266         c->v1 = tcg_temp_new();
5267         tcg_gen_andi_i32(c->v1, fpsr, FPSR_CC_Z);
5268         c->tcond = TCG_COND_EQ;
5269         break;
5270     case 15: /* True */
5271     case 31: /* Signaling True */
5272         c->v1 = c->v2;
5273         c->tcond = TCG_COND_ALWAYS;
5274         break;
5275     }
5276 }
5277 
5278 static void gen_fjmpcc(DisasContext *s, int cond, TCGLabel *l1)
5279 {
5280     DisasCompare c;
5281 
5282     gen_fcc_cond(&c, s, cond);
5283     update_cc_op(s);
5284     tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
5285 }
5286 
5287 DISAS_INSN(fbcc)
5288 {
5289     uint32_t offset;
5290     uint32_t base;
5291     TCGLabel *l1;
5292 
5293     base = s->pc;
5294     offset = (int16_t)read_im16(env, s);
5295     if (insn & (1 << 6)) {
5296         offset = (offset << 16) | read_im16(env, s);
5297     }
5298 
5299     l1 = gen_new_label();
5300     update_cc_op(s);
5301     gen_fjmpcc(s, insn & 0x3f, l1);
5302     gen_jmp_tb(s, 0, s->pc, s->base.pc_next);
5303     gen_set_label(l1);
5304     gen_jmp_tb(s, 1, base + offset, s->base.pc_next);
5305 }
5306 
5307 DISAS_INSN(fscc)
5308 {
5309     DisasCompare c;
5310     int cond;
5311     TCGv tmp;
5312     uint16_t ext;
5313 
5314     ext = read_im16(env, s);
5315     cond = ext & 0x3f;
5316     gen_fcc_cond(&c, s, cond);
5317 
5318     tmp = tcg_temp_new();
5319     tcg_gen_setcond_i32(c.tcond, tmp, c.v1, c.v2);
5320 
5321     tcg_gen_neg_i32(tmp, tmp);
5322     DEST_EA(env, insn, OS_BYTE, tmp, NULL);
5323 }
5324 
5325 DISAS_INSN(ftrapcc)
5326 {
5327     DisasCompare c;
5328     uint16_t ext;
5329     int cond;
5330 
5331     ext = read_im16(env, s);
5332     cond = ext & 0x3f;
5333 
5334     /* Consume and discard the immediate operand. */
5335     switch (extract32(insn, 0, 3)) {
5336     case 2: /* ftrapcc.w */
5337         (void)read_im16(env, s);
5338         break;
5339     case 3: /* ftrapcc.l */
5340         (void)read_im32(env, s);
5341         break;
5342     case 4: /* ftrapcc (no operand) */
5343         break;
5344     default:
5345         /* ftrapcc registered with only valid opmodes */
5346         g_assert_not_reached();
5347     }
5348 
5349     gen_fcc_cond(&c, s, cond);
5350     do_trapcc(s, &c);
5351 }
5352 
5353 #if defined(CONFIG_SOFTMMU)
5354 DISAS_INSN(frestore)
5355 {
5356     TCGv addr;
5357 
5358     if (IS_USER(s)) {
5359         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
5360         return;
5361     }
5362     if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
5363         SRC_EA(env, addr, OS_LONG, 0, NULL);
5364         /* FIXME: check the state frame */
5365     } else {
5366         disas_undef(env, s, insn);
5367     }
5368 }
5369 
5370 DISAS_INSN(fsave)
5371 {
5372     if (IS_USER(s)) {
5373         gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
5374         return;
5375     }
5376 
5377     if (m68k_feature(s->env, M68K_FEATURE_M68040)) {
5378         /* always write IDLE */
5379         TCGv idle = tcg_constant_i32(0x41000000);
5380         DEST_EA(env, insn, OS_LONG, idle, NULL);
5381     } else {
5382         disas_undef(env, s, insn);
5383     }
5384 }
5385 #endif
5386 
5387 static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
5388 {
5389     TCGv tmp = tcg_temp_new();
5390     if (s->env->macsr & MACSR_FI) {
5391         if (upper)
5392             tcg_gen_andi_i32(tmp, val, 0xffff0000);
5393         else
5394             tcg_gen_shli_i32(tmp, val, 16);
5395     } else if (s->env->macsr & MACSR_SU) {
5396         if (upper)
5397             tcg_gen_sari_i32(tmp, val, 16);
5398         else
5399             tcg_gen_ext16s_i32(tmp, val);
5400     } else {
5401         if (upper)
5402             tcg_gen_shri_i32(tmp, val, 16);
5403         else
5404             tcg_gen_ext16u_i32(tmp, val);
5405     }
5406     return tmp;
5407 }
5408 
5409 static void gen_mac_clear_flags(void)
5410 {
5411     tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR,
5412                      ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV));
5413 }
5414 
5415 DISAS_INSN(mac)
5416 {
5417     TCGv rx;
5418     TCGv ry;
5419     uint16_t ext;
5420     int acc;
5421     TCGv tmp;
5422     TCGv addr;
5423     TCGv loadval;
5424     int dual;
5425     TCGv saved_flags;
5426 
5427     if (!s->done_mac) {
5428         s->mactmp = tcg_temp_new_i64();
5429         s->done_mac = 1;
5430     }
5431 
5432     ext = read_im16(env, s);
5433 
5434     acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
5435     dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
5436     if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
5437         disas_undef(env, s, insn);
5438         return;
5439     }
5440     if (insn & 0x30) {
5441         /* MAC with load.  */
5442         tmp = gen_lea(env, s, insn, OS_LONG);
5443         addr = tcg_temp_new();
5444         tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
5445         /*
5446          * Load the value now to ensure correct exception behavior.
5447          * Perform writeback after reading the MAC inputs.
5448          */
5449         loadval = gen_load(s, OS_LONG, addr, 0, IS_USER(s));
5450 
5451         acc ^= 1;
5452         rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
5453         ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
5454     } else {
5455         loadval = addr = NULL_QREG;
5456         rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
5457         ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5458     }
5459 
5460     gen_mac_clear_flags();
5461 #if 0
5462     l1 = -1;
5463     /* Disabled because conditional branches clobber temporary vars.  */
5464     if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
5465         /* Skip the multiply if we know we will ignore it.  */
5466         l1 = gen_new_label();
5467         tmp = tcg_temp_new();
5468         tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8));
5469         gen_op_jmp_nz32(tmp, l1);
5470     }
5471 #endif
5472 
5473     if ((ext & 0x0800) == 0) {
5474         /* Word.  */
5475         rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
5476         ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
5477     }
5478     if (s->env->macsr & MACSR_FI) {
5479         gen_helper_macmulf(s->mactmp, cpu_env, rx, ry);
5480     } else {
5481         if (s->env->macsr & MACSR_SU)
5482             gen_helper_macmuls(s->mactmp, cpu_env, rx, ry);
5483         else
5484             gen_helper_macmulu(s->mactmp, cpu_env, rx, ry);
5485         switch ((ext >> 9) & 3) {
5486         case 1:
5487             tcg_gen_shli_i64(s->mactmp, s->mactmp, 1);
5488             break;
5489         case 3:
5490             tcg_gen_shri_i64(s->mactmp, s->mactmp, 1);
5491             break;
5492         }
5493     }
5494 
5495     if (dual) {
5496         /* Save the overflow flag from the multiply.  */
5497         saved_flags = tcg_temp_new();
5498         tcg_gen_mov_i32(saved_flags, QREG_MACSR);
5499     } else {
5500         saved_flags = NULL_QREG;
5501     }
5502 
5503 #if 0
5504     /* Disabled because conditional branches clobber temporary vars.  */
5505     if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
5506         /* Skip the accumulate if the value is already saturated.  */
5507         l1 = gen_new_label();
5508         tmp = tcg_temp_new();
5509         gen_op_and32(tmp, QREG_MACSR, tcg_constant_i32(MACSR_PAV0 << acc));
5510         gen_op_jmp_nz32(tmp, l1);
5511     }
5512 #endif
5513 
5514     if (insn & 0x100)
5515         tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
5516     else
5517         tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
5518 
5519     if (s->env->macsr & MACSR_FI)
5520         gen_helper_macsatf(cpu_env, tcg_constant_i32(acc));
5521     else if (s->env->macsr & MACSR_SU)
5522         gen_helper_macsats(cpu_env, tcg_constant_i32(acc));
5523     else
5524         gen_helper_macsatu(cpu_env, tcg_constant_i32(acc));
5525 
5526 #if 0
5527     /* Disabled because conditional branches clobber temporary vars.  */
5528     if (l1 != -1)
5529         gen_set_label(l1);
5530 #endif
5531 
5532     if (dual) {
5533         /* Dual accumulate variant.  */
5534         acc = (ext >> 2) & 3;
5535         /* Restore the overflow flag from the multiplier.  */
5536         tcg_gen_mov_i32(QREG_MACSR, saved_flags);
5537 #if 0
5538         /* Disabled because conditional branches clobber temporary vars.  */
5539         if ((s->env->macsr & MACSR_OMC) != 0) {
5540             /* Skip the accumulate if the value is already saturated.  */
5541             l1 = gen_new_label();
5542             tmp = tcg_temp_new();
5543             gen_op_and32(tmp, QREG_MACSR, tcg_constant_i32(MACSR_PAV0 << acc));
5544             gen_op_jmp_nz32(tmp, l1);
5545         }
5546 #endif
5547         if (ext & 2)
5548             tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
5549         else
5550             tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
5551         if (s->env->macsr & MACSR_FI)
5552             gen_helper_macsatf(cpu_env, tcg_constant_i32(acc));
5553         else if (s->env->macsr & MACSR_SU)
5554             gen_helper_macsats(cpu_env, tcg_constant_i32(acc));
5555         else
5556             gen_helper_macsatu(cpu_env, tcg_constant_i32(acc));
5557 #if 0
5558         /* Disabled because conditional branches clobber temporary vars.  */
5559         if (l1 != -1)
5560             gen_set_label(l1);
5561 #endif
5562     }
5563     gen_helper_mac_set_flags(cpu_env, tcg_constant_i32(acc));
5564 
5565     if (insn & 0x30) {
5566         TCGv rw;
5567         rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
5568         tcg_gen_mov_i32(rw, loadval);
5569         /*
5570          * FIXME: Should address writeback happen with the masked or
5571          * unmasked value?
5572          */
5573         switch ((insn >> 3) & 7) {
5574         case 3: /* Post-increment.  */
5575             tcg_gen_addi_i32(AREG(insn, 0), addr, 4);
5576             break;
5577         case 4: /* Pre-decrement.  */
5578             tcg_gen_mov_i32(AREG(insn, 0), addr);
5579         }
5580     }
5581 }
5582 
5583 DISAS_INSN(from_mac)
5584 {
5585     TCGv rx;
5586     TCGv_i64 acc;
5587     int accnum;
5588 
5589     rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5590     accnum = (insn >> 9) & 3;
5591     acc = MACREG(accnum);
5592     if (s->env->macsr & MACSR_FI) {
5593         gen_helper_get_macf(rx, cpu_env, acc);
5594     } else if ((s->env->macsr & MACSR_OMC) == 0) {
5595         tcg_gen_extrl_i64_i32(rx, acc);
5596     } else if (s->env->macsr & MACSR_SU) {
5597         gen_helper_get_macs(rx, acc);
5598     } else {
5599         gen_helper_get_macu(rx, acc);
5600     }
5601     if (insn & 0x40) {
5602         tcg_gen_movi_i64(acc, 0);
5603         tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
5604     }
5605 }
5606 
5607 DISAS_INSN(move_mac)
5608 {
5609     /* FIXME: This can be done without a helper.  */
5610     int src;
5611     TCGv dest;
5612     src = insn & 3;
5613     dest = tcg_constant_i32((insn >> 9) & 3);
5614     gen_helper_mac_move(cpu_env, dest, tcg_constant_i32(src));
5615     gen_mac_clear_flags();
5616     gen_helper_mac_set_flags(cpu_env, dest);
5617 }
5618 
5619 DISAS_INSN(from_macsr)
5620 {
5621     TCGv reg;
5622 
5623     reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5624     tcg_gen_mov_i32(reg, QREG_MACSR);
5625 }
5626 
5627 DISAS_INSN(from_mask)
5628 {
5629     TCGv reg;
5630     reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5631     tcg_gen_mov_i32(reg, QREG_MAC_MASK);
5632 }
5633 
5634 DISAS_INSN(from_mext)
5635 {
5636     TCGv reg;
5637     TCGv acc;
5638     reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
5639     acc = tcg_constant_i32((insn & 0x400) ? 2 : 0);
5640     if (s->env->macsr & MACSR_FI)
5641         gen_helper_get_mac_extf(reg, cpu_env, acc);
5642     else
5643         gen_helper_get_mac_exti(reg, cpu_env, acc);
5644 }
5645 
5646 DISAS_INSN(macsr_to_ccr)
5647 {
5648     TCGv tmp = tcg_temp_new();
5649 
5650     /* Note that X and C are always cleared. */
5651     tcg_gen_andi_i32(tmp, QREG_MACSR, CCF_N | CCF_Z | CCF_V);
5652     gen_helper_set_ccr(cpu_env, tmp);
5653     set_cc_op(s, CC_OP_FLAGS);
5654 }
5655 
5656 DISAS_INSN(to_mac)
5657 {
5658     TCGv_i64 acc;
5659     TCGv val;
5660     int accnum;
5661     accnum = (insn >> 9) & 3;
5662     acc = MACREG(accnum);
5663     SRC_EA(env, val, OS_LONG, 0, NULL);
5664     if (s->env->macsr & MACSR_FI) {
5665         tcg_gen_ext_i32_i64(acc, val);
5666         tcg_gen_shli_i64(acc, acc, 8);
5667     } else if (s->env->macsr & MACSR_SU) {
5668         tcg_gen_ext_i32_i64(acc, val);
5669     } else {
5670         tcg_gen_extu_i32_i64(acc, val);
5671     }
5672     tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
5673     gen_mac_clear_flags();
5674     gen_helper_mac_set_flags(cpu_env, tcg_constant_i32(accnum));
5675 }
5676 
5677 DISAS_INSN(to_macsr)
5678 {
5679     TCGv val;
5680     SRC_EA(env, val, OS_LONG, 0, NULL);
5681     gen_helper_set_macsr(cpu_env, val);
5682     gen_exit_tb(s);
5683 }
5684 
5685 DISAS_INSN(to_mask)
5686 {
5687     TCGv val;
5688     SRC_EA(env, val, OS_LONG, 0, NULL);
5689     tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000);
5690 }
5691 
5692 DISAS_INSN(to_mext)
5693 {
5694     TCGv val;
5695     TCGv acc;
5696     SRC_EA(env, val, OS_LONG, 0, NULL);
5697     acc = tcg_constant_i32((insn & 0x400) ? 2 : 0);
5698     if (s->env->macsr & MACSR_FI)
5699         gen_helper_set_mac_extf(cpu_env, val, acc);
5700     else if (s->env->macsr & MACSR_SU)
5701         gen_helper_set_mac_exts(cpu_env, val, acc);
5702     else
5703         gen_helper_set_mac_extu(cpu_env, val, acc);
5704 }
5705 
5706 static disas_proc opcode_table[65536];
5707 
5708 static void
5709 register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
5710 {
5711   int i;
5712   int from;
5713   int to;
5714 
5715   /* Sanity check.  All set bits must be included in the mask.  */
5716   if (opcode & ~mask) {
5717       fprintf(stderr,
5718               "qemu internal error: bogus opcode definition %04x/%04x\n",
5719               opcode, mask);
5720       abort();
5721   }
5722   /*
5723    * This could probably be cleverer.  For now just optimize the case where
5724    * the top bits are known.
5725    */
5726   /* Find the first zero bit in the mask.  */
5727   i = 0x8000;
5728   while ((i & mask) != 0)
5729       i >>= 1;
5730   /* Iterate over all combinations of this and lower bits.  */
5731   if (i == 0)
5732       i = 1;
5733   else
5734       i <<= 1;
5735   from = opcode & ~(i - 1);
5736   to = from + i;
5737   for (i = from; i < to; i++) {
5738       if ((i & mask) == opcode)
5739           opcode_table[i] = proc;
5740   }
5741 }
5742 
5743 /*
5744  * Register m68k opcode handlers.  Order is important.
5745  * Later insn override earlier ones.
5746  */
5747 void register_m68k_insns (CPUM68KState *env)
5748 {
5749     /*
5750      * Build the opcode table only once to avoid
5751      * multithreading issues.
5752      */
5753     if (opcode_table[0] != NULL) {
5754         return;
5755     }
5756 
5757     /*
5758      * use BASE() for instruction available
5759      * for CF_ISA_A and M68000.
5760      */
5761 #define BASE(name, opcode, mask) \
5762     register_opcode(disas_##name, 0x##opcode, 0x##mask)
5763 #define INSN(name, opcode, mask, feature) do { \
5764     if (m68k_feature(env, M68K_FEATURE_##feature)) \
5765         BASE(name, opcode, mask); \
5766     } while(0)
5767     BASE(undef,     0000, 0000);
5768     INSN(arith_im,  0080, fff8, CF_ISA_A);
5769     INSN(arith_im,  0000, ff00, M68K);
5770     INSN(chk2,      00c0, f9c0, CHK2);
5771     INSN(bitrev,    00c0, fff8, CF_ISA_APLUSC);
5772     BASE(bitop_reg, 0100, f1c0);
5773     BASE(bitop_reg, 0140, f1c0);
5774     BASE(bitop_reg, 0180, f1c0);
5775     BASE(bitop_reg, 01c0, f1c0);
5776     INSN(movep,     0108, f138, MOVEP);
5777     INSN(arith_im,  0280, fff8, CF_ISA_A);
5778     INSN(arith_im,  0200, ff00, M68K);
5779     INSN(undef,     02c0, ffc0, M68K);
5780     INSN(byterev,   02c0, fff8, CF_ISA_APLUSC);
5781     INSN(arith_im,  0480, fff8, CF_ISA_A);
5782     INSN(arith_im,  0400, ff00, M68K);
5783     INSN(undef,     04c0, ffc0, M68K);
5784     INSN(arith_im,  0600, ff00, M68K);
5785     INSN(undef,     06c0, ffc0, M68K);
5786     INSN(ff1,       04c0, fff8, CF_ISA_APLUSC);
5787     INSN(arith_im,  0680, fff8, CF_ISA_A);
5788     INSN(arith_im,  0c00, ff38, CF_ISA_A);
5789     INSN(arith_im,  0c00, ff00, M68K);
5790     BASE(bitop_im,  0800, ffc0);
5791     BASE(bitop_im,  0840, ffc0);
5792     BASE(bitop_im,  0880, ffc0);
5793     BASE(bitop_im,  08c0, ffc0);
5794     INSN(arith_im,  0a80, fff8, CF_ISA_A);
5795     INSN(arith_im,  0a00, ff00, M68K);
5796 #if defined(CONFIG_SOFTMMU)
5797     INSN(moves,     0e00, ff00, M68K);
5798 #endif
5799     INSN(cas,       0ac0, ffc0, CAS);
5800     INSN(cas,       0cc0, ffc0, CAS);
5801     INSN(cas,       0ec0, ffc0, CAS);
5802     INSN(cas2w,     0cfc, ffff, CAS);
5803     INSN(cas2l,     0efc, ffff, CAS);
5804     BASE(move,      1000, f000);
5805     BASE(move,      2000, f000);
5806     BASE(move,      3000, f000);
5807     INSN(chk,       4000, f040, M68K);
5808     INSN(strldsr,   40e7, ffff, CF_ISA_APLUSC);
5809     INSN(negx,      4080, fff8, CF_ISA_A);
5810     INSN(negx,      4000, ff00, M68K);
5811     INSN(undef,     40c0, ffc0, M68K);
5812     INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
5813     INSN(move_from_sr, 40c0, ffc0, M68K);
5814     BASE(lea,       41c0, f1c0);
5815     BASE(clr,       4200, ff00);
5816     BASE(undef,     42c0, ffc0);
5817     INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
5818     INSN(move_from_ccr, 42c0, ffc0, M68K);
5819     INSN(neg,       4480, fff8, CF_ISA_A);
5820     INSN(neg,       4400, ff00, M68K);
5821     INSN(undef,     44c0, ffc0, M68K);
5822     BASE(move_to_ccr, 44c0, ffc0);
5823     INSN(not,       4680, fff8, CF_ISA_A);
5824     INSN(not,       4600, ff00, M68K);
5825 #if defined(CONFIG_SOFTMMU)
5826     BASE(move_to_sr, 46c0, ffc0);
5827 #endif
5828     INSN(nbcd,      4800, ffc0, M68K);
5829     INSN(linkl,     4808, fff8, M68K);
5830     BASE(pea,       4840, ffc0);
5831     BASE(swap,      4840, fff8);
5832     INSN(bkpt,      4848, fff8, BKPT);
5833     INSN(movem,     48d0, fbf8, CF_ISA_A);
5834     INSN(movem,     48e8, fbf8, CF_ISA_A);
5835     INSN(movem,     4880, fb80, M68K);
5836     BASE(ext,       4880, fff8);
5837     BASE(ext,       48c0, fff8);
5838     BASE(ext,       49c0, fff8);
5839     BASE(tst,       4a00, ff00);
5840     INSN(tas,       4ac0, ffc0, CF_ISA_B);
5841     INSN(tas,       4ac0, ffc0, M68K);
5842 #if defined(CONFIG_SOFTMMU)
5843     INSN(halt,      4ac8, ffff, CF_ISA_A);
5844     INSN(halt,      4ac8, ffff, M68K);
5845 #endif
5846     INSN(pulse,     4acc, ffff, CF_ISA_A);
5847     BASE(illegal,   4afc, ffff);
5848     INSN(mull,      4c00, ffc0, CF_ISA_A);
5849     INSN(mull,      4c00, ffc0, LONG_MULDIV);
5850     INSN(divl,      4c40, ffc0, CF_ISA_A);
5851     INSN(divl,      4c40, ffc0, LONG_MULDIV);
5852     INSN(sats,      4c80, fff8, CF_ISA_B);
5853     BASE(trap,      4e40, fff0);
5854     BASE(link,      4e50, fff8);
5855     BASE(unlk,      4e58, fff8);
5856 #if defined(CONFIG_SOFTMMU)
5857     INSN(move_to_usp, 4e60, fff8, USP);
5858     INSN(move_from_usp, 4e68, fff8, USP);
5859     INSN(reset,     4e70, ffff, M68K);
5860     BASE(stop,      4e72, ffff);
5861     BASE(rte,       4e73, ffff);
5862     INSN(cf_movec,  4e7b, ffff, CF_ISA_A);
5863     INSN(m68k_movec, 4e7a, fffe, MOVEC);
5864 #endif
5865     BASE(nop,       4e71, ffff);
5866     INSN(rtd,       4e74, ffff, RTD);
5867     BASE(rts,       4e75, ffff);
5868     INSN(trapv,     4e76, ffff, M68K);
5869     INSN(rtr,       4e77, ffff, M68K);
5870     BASE(jump,      4e80, ffc0);
5871     BASE(jump,      4ec0, ffc0);
5872     INSN(addsubq,   5000, f080, M68K);
5873     BASE(addsubq,   5080, f0c0);
5874     INSN(scc,       50c0, f0f8, CF_ISA_A); /* Scc.B Dx   */
5875     INSN(scc,       50c0, f0c0, M68K);     /* Scc.B <EA> */
5876     INSN(dbcc,      50c8, f0f8, M68K);
5877     INSN(trapcc,    50fa, f0fe, TRAPCC);   /* opmode 010, 011 */
5878     INSN(trapcc,    50fc, f0ff, TRAPCC);   /* opmode 100 */
5879     INSN(trapcc,    51fa, fffe, CF_ISA_A); /* TPF (trapf) opmode 010, 011 */
5880     INSN(trapcc,    51fc, ffff, CF_ISA_A); /* TPF (trapf) opmode 100 */
5881 
5882     /* Branch instructions.  */
5883     BASE(branch,    6000, f000);
5884     /* Disable long branch instructions, then add back the ones we want.  */
5885     BASE(undef,     60ff, f0ff); /* All long branches.  */
5886     INSN(branch,    60ff, f0ff, CF_ISA_B);
5887     INSN(undef,     60ff, ffff, CF_ISA_B); /* bra.l */
5888     INSN(branch,    60ff, ffff, BRAL);
5889     INSN(branch,    60ff, f0ff, BCCL);
5890 
5891     BASE(moveq,     7000, f100);
5892     INSN(mvzs,      7100, f100, CF_ISA_B);
5893     BASE(or,        8000, f000);
5894     BASE(divw,      80c0, f0c0);
5895     INSN(sbcd_reg,  8100, f1f8, M68K);
5896     INSN(sbcd_mem,  8108, f1f8, M68K);
5897     BASE(addsub,    9000, f000);
5898     INSN(undef,     90c0, f0c0, CF_ISA_A);
5899     INSN(subx_reg,  9180, f1f8, CF_ISA_A);
5900     INSN(subx_reg,  9100, f138, M68K);
5901     INSN(subx_mem,  9108, f138, M68K);
5902     INSN(suba,      91c0, f1c0, CF_ISA_A);
5903     INSN(suba,      90c0, f0c0, M68K);
5904 
5905     BASE(undef_mac, a000, f000);
5906     INSN(mac,       a000, f100, CF_EMAC);
5907     INSN(from_mac,  a180, f9b0, CF_EMAC);
5908     INSN(move_mac,  a110, f9fc, CF_EMAC);
5909     INSN(from_macsr,a980, f9f0, CF_EMAC);
5910     INSN(from_mask, ad80, fff0, CF_EMAC);
5911     INSN(from_mext, ab80, fbf0, CF_EMAC);
5912     INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
5913     INSN(to_mac,    a100, f9c0, CF_EMAC);
5914     INSN(to_macsr,  a900, ffc0, CF_EMAC);
5915     INSN(to_mext,   ab00, fbc0, CF_EMAC);
5916     INSN(to_mask,   ad00, ffc0, CF_EMAC);
5917 
5918     INSN(mov3q,     a140, f1c0, CF_ISA_B);
5919     INSN(cmp,       b000, f1c0, CF_ISA_B); /* cmp.b */
5920     INSN(cmp,       b040, f1c0, CF_ISA_B); /* cmp.w */
5921     INSN(cmpa,      b0c0, f1c0, CF_ISA_B); /* cmpa.w */
5922     INSN(cmp,       b080, f1c0, CF_ISA_A);
5923     INSN(cmpa,      b1c0, f1c0, CF_ISA_A);
5924     INSN(cmp,       b000, f100, M68K);
5925     INSN(eor,       b100, f100, M68K);
5926     INSN(cmpm,      b108, f138, M68K);
5927     INSN(cmpa,      b0c0, f0c0, M68K);
5928     INSN(eor,       b180, f1c0, CF_ISA_A);
5929     BASE(and,       c000, f000);
5930     INSN(exg_dd,    c140, f1f8, M68K);
5931     INSN(exg_aa,    c148, f1f8, M68K);
5932     INSN(exg_da,    c188, f1f8, M68K);
5933     BASE(mulw,      c0c0, f0c0);
5934     INSN(abcd_reg,  c100, f1f8, M68K);
5935     INSN(abcd_mem,  c108, f1f8, M68K);
5936     BASE(addsub,    d000, f000);
5937     INSN(undef,     d0c0, f0c0, CF_ISA_A);
5938     INSN(addx_reg,      d180, f1f8, CF_ISA_A);
5939     INSN(addx_reg,  d100, f138, M68K);
5940     INSN(addx_mem,  d108, f138, M68K);
5941     INSN(adda,      d1c0, f1c0, CF_ISA_A);
5942     INSN(adda,      d0c0, f0c0, M68K);
5943     INSN(shift_im,  e080, f0f0, CF_ISA_A);
5944     INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
5945     INSN(shift8_im, e000, f0f0, M68K);
5946     INSN(shift16_im, e040, f0f0, M68K);
5947     INSN(shift_im,  e080, f0f0, M68K);
5948     INSN(shift8_reg, e020, f0f0, M68K);
5949     INSN(shift16_reg, e060, f0f0, M68K);
5950     INSN(shift_reg, e0a0, f0f0, M68K);
5951     INSN(shift_mem, e0c0, fcc0, M68K);
5952     INSN(rotate_im, e090, f0f0, M68K);
5953     INSN(rotate8_im, e010, f0f0, M68K);
5954     INSN(rotate16_im, e050, f0f0, M68K);
5955     INSN(rotate_reg, e0b0, f0f0, M68K);
5956     INSN(rotate8_reg, e030, f0f0, M68K);
5957     INSN(rotate16_reg, e070, f0f0, M68K);
5958     INSN(rotate_mem, e4c0, fcc0, M68K);
5959     INSN(bfext_mem, e9c0, fdc0, BITFIELD);  /* bfextu & bfexts */
5960     INSN(bfext_reg, e9c0, fdf8, BITFIELD);
5961     INSN(bfins_mem, efc0, ffc0, BITFIELD);
5962     INSN(bfins_reg, efc0, fff8, BITFIELD);
5963     INSN(bfop_mem, eac0, ffc0, BITFIELD);   /* bfchg */
5964     INSN(bfop_reg, eac0, fff8, BITFIELD);   /* bfchg */
5965     INSN(bfop_mem, ecc0, ffc0, BITFIELD);   /* bfclr */
5966     INSN(bfop_reg, ecc0, fff8, BITFIELD);   /* bfclr */
5967     INSN(bfop_mem, edc0, ffc0, BITFIELD);   /* bfffo */
5968     INSN(bfop_reg, edc0, fff8, BITFIELD);   /* bfffo */
5969     INSN(bfop_mem, eec0, ffc0, BITFIELD);   /* bfset */
5970     INSN(bfop_reg, eec0, fff8, BITFIELD);   /* bfset */
5971     INSN(bfop_mem, e8c0, ffc0, BITFIELD);   /* bftst */
5972     INSN(bfop_reg, e8c0, fff8, BITFIELD);   /* bftst */
5973     BASE(undef_fpu, f000, f000);
5974     INSN(fpu,       f200, ffc0, CF_FPU);
5975     INSN(fbcc,      f280, ffc0, CF_FPU);
5976     INSN(fpu,       f200, ffc0, FPU);
5977     INSN(fscc,      f240, ffc0, FPU);
5978     INSN(ftrapcc,   f27a, fffe, FPU);       /* opmode 010, 011 */
5979     INSN(ftrapcc,   f27c, ffff, FPU);       /* opmode 100 */
5980     INSN(fbcc,      f280, ff80, FPU);
5981 #if defined(CONFIG_SOFTMMU)
5982     INSN(frestore,  f340, ffc0, CF_FPU);
5983     INSN(fsave,     f300, ffc0, CF_FPU);
5984     INSN(frestore,  f340, ffc0, FPU);
5985     INSN(fsave,     f300, ffc0, FPU);
5986     INSN(intouch,   f340, ffc0, CF_ISA_A);
5987     INSN(cpushl,    f428, ff38, CF_ISA_A);
5988     INSN(cpush,     f420, ff20, M68040);
5989     INSN(cinv,      f400, ff20, M68040);
5990     INSN(pflush,    f500, ffe0, M68040);
5991     INSN(ptest,     f548, ffd8, M68040);
5992     INSN(wddata,    fb00, ff00, CF_ISA_A);
5993     INSN(wdebug,    fbc0, ffc0, CF_ISA_A);
5994 #endif
5995     INSN(move16_mem, f600, ffe0, M68040);
5996     INSN(move16_reg, f620, fff8, M68040);
5997 #undef INSN
5998 }
5999 
6000 static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
6001 {
6002     DisasContext *dc = container_of(dcbase, DisasContext, base);
6003     CPUM68KState *env = cpu->env_ptr;
6004 
6005     dc->env = env;
6006     dc->pc = dc->base.pc_first;
6007     /* This value will always be filled in properly before m68k_tr_tb_stop. */
6008     dc->pc_prev = 0xdeadbeef;
6009     dc->cc_op = CC_OP_DYNAMIC;
6010     dc->cc_op_synced = 1;
6011     dc->done_mac = 0;
6012     dc->writeback_mask = 0;
6013 
6014     dc->ss_active = (M68K_SR_TRACE(env->sr) == M68K_SR_TRACE_ANY_INS);
6015     /* If architectural single step active, limit to 1 */
6016     if (dc->ss_active) {
6017         dc->base.max_insns = 1;
6018     }
6019 }
6020 
6021 static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
6022 {
6023 }
6024 
6025 static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
6026 {
6027     DisasContext *dc = container_of(dcbase, DisasContext, base);
6028     tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
6029 }
6030 
6031 static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
6032 {
6033     DisasContext *dc = container_of(dcbase, DisasContext, base);
6034     CPUM68KState *env = cpu->env_ptr;
6035     uint16_t insn = read_im16(env, dc);
6036 
6037     opcode_table[insn](env, dc, insn);
6038     do_writebacks(dc);
6039 
6040     dc->pc_prev = dc->base.pc_next;
6041     dc->base.pc_next = dc->pc;
6042 
6043     if (dc->base.is_jmp == DISAS_NEXT) {
6044         /*
6045          * Stop translation when the next insn might touch a new page.
6046          * This ensures that prefetch aborts at the right place.
6047          *
6048          * We cannot determine the size of the next insn without
6049          * completely decoding it.  However, the maximum insn size
6050          * is 32 bytes, so end if we do not have that much remaining.
6051          * This may produce several small TBs at the end of each page,
6052          * but they will all be linked with goto_tb.
6053          *
6054          * ??? ColdFire maximum is 4 bytes; MC68000's maximum is also
6055          * smaller than MC68020's.
6056          */
6057         target_ulong start_page_offset
6058             = dc->pc - (dc->base.pc_first & TARGET_PAGE_MASK);
6059 
6060         if (start_page_offset >= TARGET_PAGE_SIZE - 32) {
6061             dc->base.is_jmp = DISAS_TOO_MANY;
6062         }
6063     }
6064 }
6065 
6066 static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
6067 {
6068     DisasContext *dc = container_of(dcbase, DisasContext, base);
6069 
6070     switch (dc->base.is_jmp) {
6071     case DISAS_NORETURN:
6072         break;
6073     case DISAS_TOO_MANY:
6074         update_cc_op(dc);
6075         gen_jmp_tb(dc, 0, dc->pc, dc->pc_prev);
6076         break;
6077     case DISAS_JUMP:
6078         /* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
6079         if (dc->ss_active) {
6080             gen_raise_exception_format2(dc, EXCP_TRACE, dc->pc_prev);
6081         } else {
6082             tcg_gen_lookup_and_goto_ptr();
6083         }
6084         break;
6085     case DISAS_EXIT:
6086         /*
6087          * We updated CC_OP and PC in gen_exit_tb, but also modified
6088          * other state that may require returning to the main loop.
6089          */
6090         if (dc->ss_active) {
6091             gen_raise_exception_format2(dc, EXCP_TRACE, dc->pc_prev);
6092         } else {
6093             tcg_gen_exit_tb(NULL, 0);
6094         }
6095         break;
6096     default:
6097         g_assert_not_reached();
6098     }
6099 }
6100 
6101 static void m68k_tr_disas_log(const DisasContextBase *dcbase,
6102                               CPUState *cpu, FILE *logfile)
6103 {
6104     fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
6105     target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
6106 }
6107 
6108 static const TranslatorOps m68k_tr_ops = {
6109     .init_disas_context = m68k_tr_init_disas_context,
6110     .tb_start           = m68k_tr_tb_start,
6111     .insn_start         = m68k_tr_insn_start,
6112     .translate_insn     = m68k_tr_translate_insn,
6113     .tb_stop            = m68k_tr_tb_stop,
6114     .disas_log          = m68k_tr_disas_log,
6115 };
6116 
6117 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int *max_insns,
6118                            target_ulong pc, void *host_pc)
6119 {
6120     DisasContext dc;
6121     translator_loop(cpu, tb, max_insns, pc, host_pc, &m68k_tr_ops, &dc.base);
6122 }
6123 
6124 static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low)
6125 {
6126     floatx80 a = { .high = high, .low = low };
6127     union {
6128         float64 f64;
6129         double d;
6130     } u;
6131 
6132     u.f64 = floatx80_to_float64(a, &env->fp_status);
6133     return u.d;
6134 }
6135 
6136 void m68k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
6137 {
6138     M68kCPU *cpu = M68K_CPU(cs);
6139     CPUM68KState *env = &cpu->env;
6140     int i;
6141     uint16_t sr;
6142     for (i = 0; i < 8; i++) {
6143         qemu_fprintf(f, "D%d = %08x   A%d = %08x   "
6144                      "F%d = %04x %016"PRIx64"  (%12g)\n",
6145                      i, env->dregs[i], i, env->aregs[i],
6146                      i, env->fregs[i].l.upper, env->fregs[i].l.lower,
6147                      floatx80_to_double(env, env->fregs[i].l.upper,
6148                                         env->fregs[i].l.lower));
6149     }
6150     qemu_fprintf(f, "PC = %08x   ", env->pc);
6151     sr = env->sr | cpu_m68k_get_ccr(env);
6152     qemu_fprintf(f, "SR = %04x T:%x I:%x %c%c %c%c%c%c%c\n",
6153                  sr, (sr & SR_T) >> SR_T_SHIFT, (sr & SR_I) >> SR_I_SHIFT,
6154                  (sr & SR_S) ? 'S' : 'U', (sr & SR_M) ? '%' : 'I',
6155                  (sr & CCF_X) ? 'X' : '-', (sr & CCF_N) ? 'N' : '-',
6156                  (sr & CCF_Z) ? 'Z' : '-', (sr & CCF_V) ? 'V' : '-',
6157                  (sr & CCF_C) ? 'C' : '-');
6158     qemu_fprintf(f, "FPSR = %08x %c%c%c%c ", env->fpsr,
6159                  (env->fpsr & FPSR_CC_A) ? 'A' : '-',
6160                  (env->fpsr & FPSR_CC_I) ? 'I' : '-',
6161                  (env->fpsr & FPSR_CC_Z) ? 'Z' : '-',
6162                  (env->fpsr & FPSR_CC_N) ? 'N' : '-');
6163     qemu_fprintf(f, "\n                                "
6164                  "FPCR =     %04x ", env->fpcr);
6165     switch (env->fpcr & FPCR_PREC_MASK) {
6166     case FPCR_PREC_X:
6167         qemu_fprintf(f, "X ");
6168         break;
6169     case FPCR_PREC_S:
6170         qemu_fprintf(f, "S ");
6171         break;
6172     case FPCR_PREC_D:
6173         qemu_fprintf(f, "D ");
6174         break;
6175     }
6176     switch (env->fpcr & FPCR_RND_MASK) {
6177     case FPCR_RND_N:
6178         qemu_fprintf(f, "RN ");
6179         break;
6180     case FPCR_RND_Z:
6181         qemu_fprintf(f, "RZ ");
6182         break;
6183     case FPCR_RND_M:
6184         qemu_fprintf(f, "RM ");
6185         break;
6186     case FPCR_RND_P:
6187         qemu_fprintf(f, "RP ");
6188         break;
6189     }
6190     qemu_fprintf(f, "\n");
6191 #ifdef CONFIG_SOFTMMU
6192     qemu_fprintf(f, "%sA7(MSP) = %08x %sA7(USP) = %08x %sA7(ISP) = %08x\n",
6193                  env->current_sp == M68K_SSP ? "->" : "  ", env->sp[M68K_SSP],
6194                  env->current_sp == M68K_USP ? "->" : "  ", env->sp[M68K_USP],
6195                  env->current_sp == M68K_ISP ? "->" : "  ", env->sp[M68K_ISP]);
6196     qemu_fprintf(f, "VBR = 0x%08x\n", env->vbr);
6197     qemu_fprintf(f, "SFC = %x DFC %x\n", env->sfc, env->dfc);
6198     qemu_fprintf(f, "SSW %08x TCR %08x URP %08x SRP %08x\n",
6199                  env->mmu.ssw, env->mmu.tcr, env->mmu.urp, env->mmu.srp);
6200     qemu_fprintf(f, "DTTR0/1: %08x/%08x ITTR0/1: %08x/%08x\n",
6201                  env->mmu.ttr[M68K_DTTR0], env->mmu.ttr[M68K_DTTR1],
6202                  env->mmu.ttr[M68K_ITTR0], env->mmu.ttr[M68K_ITTR1]);
6203     qemu_fprintf(f, "MMUSR %08x, fault at %08x\n",
6204                  env->mmu.mmusr, env->mmu.ar);
6205 #endif
6206 }
6207