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