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