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