kvm: qemu: report paravirt features on cpuid
[kvm-userspace.git] / qemu / target-m68k / translate.c
blob39816f4b2a1746fe2e4e06794b34affc748f51e0
1 /*
2 * m68k translation
4 * Copyright (c) 2005-2007 CodeSourcery
5 * Written by Paul Brook
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.
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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "config.h"
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "disas.h"
31 #include "tcg-op.h"
32 #include "m68k-qreg.h"
34 //#define DEBUG_DISPATCH 1
36 static inline void qemu_assert(int cond, const char *msg)
38 if (!cond) {
39 fprintf (stderr, "badness: %s\n", msg);
40 abort();
44 /* internal defines */
45 typedef struct DisasContext {
46 CPUM68KState *env;
47 target_ulong insn_pc; /* Start of the current instruction. */
48 target_ulong pc;
49 int is_jmp;
50 int cc_op;
51 int user;
52 uint32_t fpcr;
53 struct TranslationBlock *tb;
54 int singlestep_enabled;
55 int is_mem;
56 } DisasContext;
58 #define DISAS_JUMP_NEXT 4
60 #if defined(CONFIG_USER_ONLY)
61 #define IS_USER(s) 1
62 #else
63 #define IS_USER(s) s->user
64 #endif
66 /* XXX: move that elsewhere */
67 /* ??? Fix exceptions. */
68 static void *gen_throws_exception;
69 #define gen_last_qop NULL
71 extern FILE *logfile;
72 extern int loglevel;
74 #if defined(CONFIG_USER_ONLY)
75 #define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
76 #define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
77 #else
78 #define gen_st(s, name, addr, val) do { \
79 if (IS_USER(s)) \
80 gen_op_st##name##_user(addr, val); \
81 else \
82 gen_op_st##name##_kernel(addr, val); \
83 } while (0)
84 #define gen_ld(s, name, val, addr) do { \
85 if (IS_USER(s)) \
86 gen_op_ld##name##_user(val, addr); \
87 else \
88 gen_op_ld##name##_kernel(val, addr); \
89 } while (0)
90 #endif
92 #include "op-hacks.h"
94 #define OS_BYTE 0
95 #define OS_WORD 1
96 #define OS_LONG 2
97 #define OS_SINGLE 4
98 #define OS_DOUBLE 5
100 #define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
101 #define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
102 #define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
104 typedef void (*disas_proc)(DisasContext *, uint16_t);
106 #ifdef DEBUG_DISPATCH
107 #define DISAS_INSN(name) \
108 static void real_disas_##name (DisasContext *s, uint16_t insn); \
109 static void disas_##name (DisasContext *s, uint16_t insn) { \
110 if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \
111 real_disas_##name(s, insn); } \
112 static void real_disas_##name (DisasContext *s, uint16_t insn)
113 #else
114 #define DISAS_INSN(name) \
115 static void disas_##name (DisasContext *s, uint16_t insn)
116 #endif
118 /* Generate a load from the specified address. Narrow values are
119 sign extended to full register width. */
120 static inline int gen_load(DisasContext * s, int opsize, int addr, int sign)
122 int tmp;
123 s->is_mem = 1;
124 switch(opsize) {
125 case OS_BYTE:
126 tmp = gen_new_qreg(QMODE_I32);
127 if (sign)
128 gen_ld(s, 8s32, tmp, addr);
129 else
130 gen_ld(s, 8u32, tmp, addr);
131 break;
132 case OS_WORD:
133 tmp = gen_new_qreg(QMODE_I32);
134 if (sign)
135 gen_ld(s, 16s32, tmp, addr);
136 else
137 gen_ld(s, 16u32, tmp, addr);
138 break;
139 case OS_LONG:
140 tmp = gen_new_qreg(QMODE_I32);
141 gen_ld(s, 32, tmp, addr);
142 break;
143 case OS_SINGLE:
144 tmp = gen_new_qreg(QMODE_F32);
145 gen_ld(s, f32, tmp, addr);
146 break;
147 case OS_DOUBLE:
148 tmp = gen_new_qreg(QMODE_F64);
149 gen_ld(s, f64, tmp, addr);
150 break;
151 default:
152 qemu_assert(0, "bad load size");
154 gen_throws_exception = gen_last_qop;
155 return tmp;
158 /* Generate a store. */
159 static inline void gen_store(DisasContext *s, int opsize, int addr, int val)
161 s->is_mem = 1;
162 switch(opsize) {
163 case OS_BYTE:
164 gen_st(s, 8, addr, val);
165 break;
166 case OS_WORD:
167 gen_st(s, 16, addr, val);
168 break;
169 case OS_LONG:
170 gen_st(s, 32, addr, val);
171 break;
172 case OS_SINGLE:
173 gen_st(s, f32, addr, val);
174 break;
175 case OS_DOUBLE:
176 gen_st(s, f64, addr, val);
177 break;
178 default:
179 qemu_assert(0, "bad store size");
181 gen_throws_exception = gen_last_qop;
184 /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
185 otherwise generate a store. */
186 static int gen_ldst(DisasContext *s, int opsize, int addr, int val)
188 if (val > 0) {
189 gen_store(s, opsize, addr, val);
190 return 0;
191 } else {
192 return gen_load(s, opsize, addr, val != 0);
196 /* Read a 32-bit immediate constant. */
197 static inline uint32_t read_im32(DisasContext *s)
199 uint32_t im;
200 im = ((uint32_t)lduw_code(s->pc)) << 16;
201 s->pc += 2;
202 im |= lduw_code(s->pc);
203 s->pc += 2;
204 return im;
207 /* Calculate and address index. */
208 static int gen_addr_index(uint16_t ext, int tmp)
210 int add;
211 int scale;
213 add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
214 if ((ext & 0x800) == 0) {
215 gen_op_ext16s32(tmp, add);
216 add = tmp;
218 scale = (ext >> 9) & 3;
219 if (scale != 0) {
220 gen_op_shl32(tmp, add, gen_im32(scale));
221 add = tmp;
223 return add;
226 /* Handle a base + index + displacement effective addresss. A base of
227 -1 means pc-relative. */
228 static int gen_lea_indexed(DisasContext *s, int opsize, int base)
230 uint32_t offset;
231 uint16_t ext;
232 int add;
233 int tmp;
234 uint32_t bd, od;
236 offset = s->pc;
237 ext = lduw_code(s->pc);
238 s->pc += 2;
240 if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
241 return -1;
243 if (ext & 0x100) {
244 /* full extension word format */
245 if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
246 return -1;
248 if ((ext & 0x30) > 0x10) {
249 /* base displacement */
250 if ((ext & 0x30) == 0x20) {
251 bd = (int16_t)lduw_code(s->pc);
252 s->pc += 2;
253 } else {
254 bd = read_im32(s);
256 } else {
257 bd = 0;
259 tmp = gen_new_qreg(QMODE_I32);
260 if ((ext & 0x44) == 0) {
261 /* pre-index */
262 add = gen_addr_index(ext, tmp);
263 } else {
264 add = QREG_NULL;
266 if ((ext & 0x80) == 0) {
267 /* base not suppressed */
268 if (base == -1) {
269 base = gen_im32(offset + bd);
270 bd = 0;
272 if (add) {
273 gen_op_add32(tmp, add, base);
274 add = tmp;
275 } else {
276 add = base;
279 if (add) {
280 if (bd != 0) {
281 gen_op_add32(tmp, add, gen_im32(bd));
282 add = tmp;
284 } else {
285 add = gen_im32(bd);
287 if ((ext & 3) != 0) {
288 /* memory indirect */
289 base = gen_load(s, OS_LONG, add, 0);
290 if ((ext & 0x44) == 4) {
291 add = gen_addr_index(ext, tmp);
292 gen_op_add32(tmp, add, base);
293 add = tmp;
294 } else {
295 add = base;
297 if ((ext & 3) > 1) {
298 /* outer displacement */
299 if ((ext & 3) == 2) {
300 od = (int16_t)lduw_code(s->pc);
301 s->pc += 2;
302 } else {
303 od = read_im32(s);
305 } else {
306 od = 0;
308 if (od != 0) {
309 gen_op_add32(tmp, add, gen_im32(od));
310 add = tmp;
313 } else {
314 /* brief extension word format */
315 tmp = gen_new_qreg(QMODE_I32);
316 add = gen_addr_index(ext, tmp);
317 if (base != -1) {
318 gen_op_add32(tmp, add, base);
319 if ((int8_t)ext)
320 gen_op_add32(tmp, tmp, gen_im32((int8_t)ext));
321 } else {
322 gen_op_add32(tmp, add, gen_im32(offset + (int8_t)ext));
324 add = tmp;
326 return add;
329 /* Update the CPU env CC_OP state. */
330 static inline void gen_flush_cc_op(DisasContext *s)
332 if (s->cc_op != CC_OP_DYNAMIC)
333 gen_op_mov32(QREG_CC_OP, gen_im32(s->cc_op));
336 /* Evaluate all the CC flags. */
337 static inline void gen_flush_flags(DisasContext *s)
339 if (s->cc_op == CC_OP_FLAGS)
340 return;
341 gen_flush_cc_op(s);
342 gen_op_flush_flags();
343 s->cc_op = CC_OP_FLAGS;
346 static inline int opsize_bytes(int opsize)
348 switch (opsize) {
349 case OS_BYTE: return 1;
350 case OS_WORD: return 2;
351 case OS_LONG: return 4;
352 case OS_SINGLE: return 4;
353 case OS_DOUBLE: return 8;
354 default:
355 qemu_assert(0, "bad operand size");
359 /* Assign value to a register. If the width is less than the register width
360 only the low part of the register is set. */
361 static void gen_partset_reg(int opsize, int reg, int val)
363 int tmp;
364 switch (opsize) {
365 case OS_BYTE:
366 gen_op_and32(reg, reg, gen_im32(0xffffff00));
367 tmp = gen_new_qreg(QMODE_I32);
368 gen_op_and32(tmp, val, gen_im32(0xff));
369 gen_op_or32(reg, reg, tmp);
370 break;
371 case OS_WORD:
372 gen_op_and32(reg, reg, gen_im32(0xffff0000));
373 tmp = gen_new_qreg(QMODE_I32);
374 gen_op_and32(tmp, val, gen_im32(0xffff));
375 gen_op_or32(reg, reg, tmp);
376 break;
377 case OS_LONG:
378 gen_op_mov32(reg, val);
379 break;
380 case OS_SINGLE:
381 gen_op_pack_32_f32(reg, val);
382 break;
383 default:
384 qemu_assert(0, "Bad operand size");
385 break;
389 /* Sign or zero extend a value. */
390 static inline int gen_extend(int val, int opsize, int sign)
392 int tmp;
394 switch (opsize) {
395 case OS_BYTE:
396 tmp = gen_new_qreg(QMODE_I32);
397 if (sign)
398 gen_op_ext8s32(tmp, val);
399 else
400 gen_op_ext8u32(tmp, val);
401 break;
402 case OS_WORD:
403 tmp = gen_new_qreg(QMODE_I32);
404 if (sign)
405 gen_op_ext16s32(tmp, val);
406 else
407 gen_op_ext16u32(tmp, val);
408 break;
409 case OS_LONG:
410 tmp = val;
411 break;
412 case OS_SINGLE:
413 tmp = gen_new_qreg(QMODE_F32);
414 gen_op_pack_f32_32(tmp, val);
415 break;
416 default:
417 qemu_assert(0, "Bad operand size");
419 return tmp;
422 /* Generate code for an "effective address". Does not adjust the base
423 register for autoincrememnt addressing modes. */
424 static int gen_lea(DisasContext *s, uint16_t insn, int opsize)
426 int reg;
427 int tmp;
428 uint16_t ext;
429 uint32_t offset;
431 reg = insn & 7;
432 switch ((insn >> 3) & 7) {
433 case 0: /* Data register direct. */
434 case 1: /* Address register direct. */
435 return -1;
436 case 2: /* Indirect register */
437 case 3: /* Indirect postincrement. */
438 reg += QREG_A0;
439 return reg;
440 case 4: /* Indirect predecrememnt. */
441 reg += QREG_A0;
442 tmp = gen_new_qreg(QMODE_I32);
443 gen_op_sub32(tmp, reg, gen_im32(opsize_bytes(opsize)));
444 return tmp;
445 case 5: /* Indirect displacement. */
446 reg += QREG_A0;
447 tmp = gen_new_qreg(QMODE_I32);
448 ext = lduw_code(s->pc);
449 s->pc += 2;
450 gen_op_add32(tmp, reg, gen_im32((int16_t)ext));
451 return tmp;
452 case 6: /* Indirect index + displacement. */
453 reg += QREG_A0;
454 return gen_lea_indexed(s, opsize, reg);
455 case 7: /* Other */
456 switch (reg) {
457 case 0: /* Absolute short. */
458 offset = ldsw_code(s->pc);
459 s->pc += 2;
460 return gen_im32(offset);
461 case 1: /* Absolute long. */
462 offset = read_im32(s);
463 return gen_im32(offset);
464 case 2: /* pc displacement */
465 tmp = gen_new_qreg(QMODE_I32);
466 offset = s->pc;
467 offset += ldsw_code(s->pc);
468 s->pc += 2;
469 return gen_im32(offset);
470 case 3: /* pc index+displacement. */
471 return gen_lea_indexed(s, opsize, -1);
472 case 4: /* Immediate. */
473 default:
474 return -1;
477 /* Should never happen. */
478 return -1;
481 /* Helper function for gen_ea. Reuse the computed address between the
482 for read/write operands. */
483 static inline int gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
484 int val, int *addrp)
486 int tmp;
488 if (addrp && val > 0) {
489 tmp = *addrp;
490 } else {
491 tmp = gen_lea(s, insn, opsize);
492 if (tmp == -1)
493 return -1;
494 if (addrp)
495 *addrp = tmp;
497 return gen_ldst(s, opsize, tmp, val);
500 /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
501 a write otherwise it is a read (0 == sign extend, -1 == zero extend).
502 ADDRP is non-null for readwrite operands. */
503 static int gen_ea(DisasContext *s, uint16_t insn, int opsize, int val,
504 int *addrp)
506 int reg;
507 int result;
508 uint32_t offset;
510 reg = insn & 7;
511 switch ((insn >> 3) & 7) {
512 case 0: /* Data register direct. */
513 reg += QREG_D0;
514 if (val > 0) {
515 gen_partset_reg(opsize, reg, val);
516 return 0;
517 } else {
518 return gen_extend(reg, opsize, val);
520 case 1: /* Address register direct. */
521 reg += QREG_A0;
522 if (val > 0) {
523 gen_op_mov32(reg, val);
524 return 0;
525 } else {
526 return gen_extend(reg, opsize, val);
528 case 2: /* Indirect register */
529 reg += QREG_A0;
530 return gen_ldst(s, opsize, reg, val);
531 case 3: /* Indirect postincrement. */
532 reg += QREG_A0;
533 result = gen_ldst(s, opsize, reg, val);
534 /* ??? This is not exception safe. The instruction may still
535 fault after this point. */
536 if (val > 0 || !addrp)
537 gen_op_add32(reg, reg, gen_im32(opsize_bytes(opsize)));
538 return result;
539 case 4: /* Indirect predecrememnt. */
541 int tmp;
542 if (addrp && val > 0) {
543 tmp = *addrp;
544 } else {
545 tmp = gen_lea(s, insn, opsize);
546 if (tmp == -1)
547 return -1;
548 if (addrp)
549 *addrp = tmp;
551 result = gen_ldst(s, opsize, tmp, val);
552 /* ??? This is not exception safe. The instruction may still
553 fault after this point. */
554 if (val > 0 || !addrp) {
555 reg += QREG_A0;
556 gen_op_mov32(reg, tmp);
559 return result;
560 case 5: /* Indirect displacement. */
561 case 6: /* Indirect index + displacement. */
562 return gen_ea_once(s, insn, opsize, val, addrp);
563 case 7: /* Other */
564 switch (reg) {
565 case 0: /* Absolute short. */
566 case 1: /* Absolute long. */
567 case 2: /* pc displacement */
568 case 3: /* pc index+displacement. */
569 return gen_ea_once(s, insn, opsize, val, addrp);
570 case 4: /* Immediate. */
571 /* Sign extend values for consistency. */
572 switch (opsize) {
573 case OS_BYTE:
574 if (val)
575 offset = ldsb_code(s->pc + 1);
576 else
577 offset = ldub_code(s->pc + 1);
578 s->pc += 2;
579 break;
580 case OS_WORD:
581 if (val)
582 offset = ldsw_code(s->pc);
583 else
584 offset = lduw_code(s->pc);
585 s->pc += 2;
586 break;
587 case OS_LONG:
588 offset = read_im32(s);
589 break;
590 default:
591 qemu_assert(0, "Bad immediate operand");
593 return gen_im32(offset);
594 default:
595 return -1;
598 /* Should never happen. */
599 return -1;
602 static void gen_logic_cc(DisasContext *s, int val)
604 gen_op_logic_cc(val);
605 s->cc_op = CC_OP_LOGIC;
608 static void gen_jmpcc(DisasContext *s, int cond, int l1)
610 int tmp;
612 gen_flush_flags(s);
613 switch (cond) {
614 case 0: /* T */
615 gen_op_jmp_im(l1);
616 break;
617 case 1: /* F */
618 break;
619 case 2: /* HI (!C && !Z) */
620 tmp = gen_new_qreg(QMODE_I32);
621 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
622 gen_op_jmp_z32(tmp, l1);
623 break;
624 case 3: /* LS (C || Z) */
625 tmp = gen_new_qreg(QMODE_I32);
626 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C | CCF_Z));
627 gen_op_jmp_nz32(tmp, l1);
628 break;
629 case 4: /* CC (!C) */
630 tmp = gen_new_qreg(QMODE_I32);
631 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
632 gen_op_jmp_z32(tmp, l1);
633 break;
634 case 5: /* CS (C) */
635 tmp = gen_new_qreg(QMODE_I32);
636 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_C));
637 gen_op_jmp_nz32(tmp, l1);
638 break;
639 case 6: /* NE (!Z) */
640 tmp = gen_new_qreg(QMODE_I32);
641 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
642 gen_op_jmp_z32(tmp, l1);
643 break;
644 case 7: /* EQ (Z) */
645 tmp = gen_new_qreg(QMODE_I32);
646 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
647 gen_op_jmp_nz32(tmp, l1);
648 break;
649 case 8: /* VC (!V) */
650 tmp = gen_new_qreg(QMODE_I32);
651 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
652 gen_op_jmp_z32(tmp, l1);
653 break;
654 case 9: /* VS (V) */
655 tmp = gen_new_qreg(QMODE_I32);
656 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
657 gen_op_jmp_nz32(tmp, l1);
658 break;
659 case 10: /* PL (!N) */
660 tmp = gen_new_qreg(QMODE_I32);
661 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
662 gen_op_jmp_z32(tmp, l1);
663 break;
664 case 11: /* MI (N) */
665 tmp = gen_new_qreg(QMODE_I32);
666 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_N));
667 gen_op_jmp_nz32(tmp, l1);
668 break;
669 case 12: /* GE (!(N ^ V)) */
670 tmp = gen_new_qreg(QMODE_I32);
671 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
672 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
673 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
674 gen_op_jmp_z32(tmp, l1);
675 break;
676 case 13: /* LT (N ^ V) */
677 tmp = gen_new_qreg(QMODE_I32);
678 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
679 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
680 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
681 gen_op_jmp_nz32(tmp, l1);
682 break;
683 case 14: /* GT (!(Z || (N ^ V))) */
685 int l2;
686 l2 = gen_new_label();
687 tmp = gen_new_qreg(QMODE_I32);
688 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
689 gen_op_jmp_nz32(tmp, l2);
690 tmp = gen_new_qreg(QMODE_I32);
691 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
692 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
693 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
694 gen_op_jmp_nz32(tmp, l2);
695 gen_op_jmp_im(l1);
696 gen_set_label(l2);
698 break;
699 case 15: /* LE (Z || (N ^ V)) */
700 tmp = gen_new_qreg(QMODE_I32);
701 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_Z));
702 gen_op_jmp_nz32(tmp, l1);
703 tmp = gen_new_qreg(QMODE_I32);
704 gen_op_shr32(tmp, QREG_CC_DEST, gen_im32(2));
705 gen_op_xor32(tmp, tmp, QREG_CC_DEST);
706 gen_op_and32(tmp, tmp, gen_im32(CCF_V));
707 gen_op_jmp_nz32(tmp, l1);
708 break;
709 default:
710 /* Should ever happen. */
711 abort();
715 DISAS_INSN(scc)
717 int l1;
718 int cond;
719 int reg;
721 l1 = gen_new_label();
722 cond = (insn >> 8) & 0xf;
723 reg = DREG(insn, 0);
724 gen_op_and32(reg, reg, gen_im32(0xffffff00));
725 gen_jmpcc(s, cond ^ 1, l1);
726 gen_op_or32(reg, reg, gen_im32(0xff));
727 gen_set_label(l1);
730 /* Force a TB lookup after an instruction that changes the CPU state. */
731 static void gen_lookup_tb(DisasContext *s)
733 gen_flush_cc_op(s);
734 gen_op_mov32(QREG_PC, gen_im32(s->pc));
735 s->is_jmp = DISAS_UPDATE;
738 /* Generate a jump to to the address in qreg DEST. */
739 static void gen_jmp(DisasContext *s, int dest)
741 gen_flush_cc_op(s);
742 gen_op_mov32(QREG_PC, dest);
743 s->is_jmp = DISAS_JUMP;
746 static void gen_exception(DisasContext *s, uint32_t where, int nr)
748 gen_flush_cc_op(s);
749 gen_jmp(s, gen_im32(where));
750 gen_op_raise_exception(nr);
753 static inline void gen_addr_fault(DisasContext *s)
755 gen_exception(s, s->insn_pc, EXCP_ADDRESS);
758 #define SRC_EA(result, opsize, val, addrp) do { \
759 result = gen_ea(s, insn, opsize, val, addrp); \
760 if (result == -1) { \
761 gen_addr_fault(s); \
762 return; \
764 } while (0)
766 #define DEST_EA(insn, opsize, val, addrp) do { \
767 int ea_result = gen_ea(s, insn, opsize, val, addrp); \
768 if (ea_result == -1) { \
769 gen_addr_fault(s); \
770 return; \
772 } while (0)
774 /* Generate a jump to an immediate address. */
775 static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
777 TranslationBlock *tb;
779 tb = s->tb;
780 if (__builtin_expect (s->singlestep_enabled, 0)) {
781 gen_exception(s, dest, EXCP_DEBUG);
782 } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
783 (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
784 tcg_gen_goto_tb(n);
785 gen_op_mov32(QREG_PC, gen_im32(dest));
786 tcg_gen_exit_tb((long)tb + n);
787 } else {
788 gen_jmp(s, gen_im32(dest));
789 tcg_gen_exit_tb(0);
791 s->is_jmp = DISAS_TB_JUMP;
794 DISAS_INSN(undef_mac)
796 gen_exception(s, s->pc - 2, EXCP_LINEA);
799 DISAS_INSN(undef_fpu)
801 gen_exception(s, s->pc - 2, EXCP_LINEF);
804 DISAS_INSN(undef)
806 gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
807 cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
808 insn, s->pc - 2);
811 DISAS_INSN(mulw)
813 int reg;
814 int tmp;
815 int src;
816 int sign;
818 sign = (insn & 0x100) != 0;
819 reg = DREG(insn, 9);
820 tmp = gen_new_qreg(QMODE_I32);
821 if (sign)
822 gen_op_ext16s32(tmp, reg);
823 else
824 gen_op_ext16u32(tmp, reg);
825 SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
826 gen_op_mul32(tmp, tmp, src);
827 gen_op_mov32(reg, tmp);
828 /* Unlike m68k, coldfire always clears the overflow bit. */
829 gen_logic_cc(s, tmp);
832 DISAS_INSN(divw)
834 int reg;
835 int tmp;
836 int src;
837 int sign;
839 sign = (insn & 0x100) != 0;
840 reg = DREG(insn, 9);
841 if (sign) {
842 gen_op_ext16s32(QREG_DIV1, reg);
843 } else {
844 gen_op_ext16u32(QREG_DIV1, reg);
846 SRC_EA(src, OS_WORD, sign ? -1 : 0, NULL);
847 gen_op_mov32(QREG_DIV2, src);
848 if (sign) {
849 gen_op_divs(1);
850 } else {
851 gen_op_divu(1);
854 tmp = gen_new_qreg(QMODE_I32);
855 src = gen_new_qreg(QMODE_I32);
856 gen_op_ext16u32(tmp, QREG_DIV1);
857 gen_op_shl32(src, QREG_DIV2, gen_im32(16));
858 gen_op_or32(reg, tmp, src);
859 gen_op_flags_set();
860 s->cc_op = CC_OP_FLAGS;
863 DISAS_INSN(divl)
865 int num;
866 int den;
867 int reg;
868 uint16_t ext;
870 ext = lduw_code(s->pc);
871 s->pc += 2;
872 if (ext & 0x87f8) {
873 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
874 return;
876 num = DREG(ext, 12);
877 reg = DREG(ext, 0);
878 gen_op_mov32(QREG_DIV1, num);
879 SRC_EA(den, OS_LONG, 0, NULL);
880 gen_op_mov32(QREG_DIV2, den);
881 if (ext & 0x0800) {
882 gen_op_divs(2);
883 } else {
884 gen_op_divu(2);
886 if (num == reg) {
887 /* div */
888 gen_op_mov32 (reg, QREG_DIV1);
889 } else {
890 /* rem */
891 gen_op_mov32 (reg, QREG_DIV2);
893 gen_op_flags_set();
894 s->cc_op = CC_OP_FLAGS;
897 DISAS_INSN(addsub)
899 int reg;
900 int dest;
901 int src;
902 int tmp;
903 int addr;
904 int add;
906 add = (insn & 0x4000) != 0;
907 reg = DREG(insn, 9);
908 dest = gen_new_qreg(QMODE_I32);
909 if (insn & 0x100) {
910 SRC_EA(tmp, OS_LONG, 0, &addr);
911 src = reg;
912 } else {
913 tmp = reg;
914 SRC_EA(src, OS_LONG, 0, NULL);
916 if (add) {
917 gen_op_add32(dest, tmp, src);
918 gen_op_update_xflag_lt(dest, src);
919 s->cc_op = CC_OP_ADD;
920 } else {
921 gen_op_update_xflag_lt(tmp, src);
922 gen_op_sub32(dest, tmp, src);
923 s->cc_op = CC_OP_SUB;
925 gen_op_update_cc_add(dest, src);
926 if (insn & 0x100) {
927 DEST_EA(insn, OS_LONG, dest, &addr);
928 } else {
929 gen_op_mov32(reg, dest);
934 /* Reverse the order of the bits in REG. */
935 DISAS_INSN(bitrev)
937 int val;
938 int tmp1;
939 int tmp2;
940 int reg;
942 val = gen_new_qreg(QMODE_I32);
943 tmp1 = gen_new_qreg(QMODE_I32);
944 tmp2 = gen_new_qreg(QMODE_I32);
945 reg = DREG(insn, 0);
946 gen_op_mov32(val, reg);
947 /* Reverse bits within each nibble. */
948 gen_op_shl32(tmp1, val, gen_im32(3));
949 gen_op_and32(tmp1, tmp1, gen_im32(0x88888888));
950 gen_op_shl32(tmp2, val, gen_im32(1));
951 gen_op_and32(tmp2, tmp2, gen_im32(0x44444444));
952 gen_op_or32(tmp1, tmp1, tmp2);
953 gen_op_shr32(tmp2, val, gen_im32(1));
954 gen_op_and32(tmp2, tmp2, gen_im32(0x22222222));
955 gen_op_or32(tmp1, tmp1, tmp2);
956 gen_op_shr32(tmp2, val, gen_im32(3));
957 gen_op_and32(tmp2, tmp2, gen_im32(0x11111111));
958 gen_op_or32(tmp1, tmp1, tmp2);
959 /* Reverse nibbles withing bytes. */
960 gen_op_shl32(val, tmp1, gen_im32(4));
961 gen_op_and32(val, val, gen_im32(0xf0f0f0f0));
962 gen_op_shr32(tmp2, tmp1, gen_im32(4));
963 gen_op_and32(tmp2, tmp2, gen_im32(0x0f0f0f0f));
964 gen_op_or32(val, val, tmp2);
965 /* Reverse bytes. */
966 gen_op_bswap32(reg, val);
967 gen_op_mov32(reg, val);
970 DISAS_INSN(bitop_reg)
972 int opsize;
973 int op;
974 int src1;
975 int src2;
976 int tmp;
977 int addr;
978 int dest;
980 if ((insn & 0x38) != 0)
981 opsize = OS_BYTE;
982 else
983 opsize = OS_LONG;
984 op = (insn >> 6) & 3;
985 SRC_EA(src1, opsize, 0, op ? &addr: NULL);
986 src2 = DREG(insn, 9);
987 dest = gen_new_qreg(QMODE_I32);
989 gen_flush_flags(s);
990 tmp = gen_new_qreg(QMODE_I32);
991 if (opsize == OS_BYTE)
992 gen_op_and32(tmp, src2, gen_im32(7));
993 else
994 gen_op_and32(tmp, src2, gen_im32(31));
995 src2 = tmp;
996 tmp = gen_new_qreg(QMODE_I32);
997 gen_op_shl32(tmp, gen_im32(1), src2);
999 gen_op_btest(src1, tmp);
1000 switch (op) {
1001 case 1: /* bchg */
1002 gen_op_xor32(dest, src1, tmp);
1003 break;
1004 case 2: /* bclr */
1005 gen_op_not32(tmp, tmp);
1006 gen_op_and32(dest, src1, tmp);
1007 break;
1008 case 3: /* bset */
1009 gen_op_or32(dest, src1, tmp);
1010 break;
1011 default: /* btst */
1012 break;
1014 if (op)
1015 DEST_EA(insn, opsize, dest, &addr);
1018 DISAS_INSN(sats)
1020 int reg;
1021 int tmp;
1022 int l1;
1024 reg = DREG(insn, 0);
1025 tmp = gen_new_qreg(QMODE_I32);
1026 gen_flush_flags(s);
1027 gen_op_and32(tmp, QREG_CC_DEST, gen_im32(CCF_V));
1028 l1 = gen_new_label();
1029 gen_op_jmp_z32(tmp, l1);
1030 tmp = gen_new_qreg(QMODE_I32);
1031 gen_op_shr32(tmp, reg, gen_im32(31));
1032 gen_op_xor32(tmp, tmp, gen_im32(0x80000000));
1033 gen_op_mov32(reg, tmp);
1034 gen_set_label(l1);
1035 gen_logic_cc(s, tmp);
1038 static void gen_push(DisasContext *s, int val)
1040 int tmp;
1042 tmp = gen_new_qreg(QMODE_I32);
1043 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1044 gen_store(s, OS_LONG, tmp, val);
1045 gen_op_mov32(QREG_SP, tmp);
1048 DISAS_INSN(movem)
1050 int addr;
1051 int i;
1052 uint16_t mask;
1053 int reg;
1054 int tmp;
1055 int is_load;
1057 mask = lduw_code(s->pc);
1058 s->pc += 2;
1059 tmp = gen_lea(s, insn, OS_LONG);
1060 if (tmp == -1) {
1061 gen_addr_fault(s);
1062 return;
1064 addr = gen_new_qreg(QMODE_I32);
1065 gen_op_mov32(addr, tmp);
1066 is_load = ((insn & 0x0400) != 0);
1067 for (i = 0; i < 16; i++, mask >>= 1) {
1068 if (mask & 1) {
1069 if (i < 8)
1070 reg = DREG(i, 0);
1071 else
1072 reg = AREG(i, 0);
1073 if (is_load) {
1074 tmp = gen_load(s, OS_LONG, addr, 0);
1075 gen_op_mov32(reg, tmp);
1076 } else {
1077 gen_store(s, OS_LONG, addr, reg);
1079 if (mask != 1)
1080 gen_op_add32(addr, addr, gen_im32(4));
1085 DISAS_INSN(bitop_im)
1087 int opsize;
1088 int op;
1089 int src1;
1090 uint32_t mask;
1091 int bitnum;
1092 int tmp;
1093 int addr;
1094 int dest;
1096 if ((insn & 0x38) != 0)
1097 opsize = OS_BYTE;
1098 else
1099 opsize = OS_LONG;
1100 op = (insn >> 6) & 3;
1102 bitnum = lduw_code(s->pc);
1103 s->pc += 2;
1104 if (bitnum & 0xff00) {
1105 disas_undef(s, insn);
1106 return;
1109 SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1111 gen_flush_flags(s);
1112 tmp = gen_new_qreg(QMODE_I32);
1113 if (opsize == OS_BYTE)
1114 bitnum &= 7;
1115 else
1116 bitnum &= 31;
1117 mask = 1 << bitnum;
1119 gen_op_btest(src1, gen_im32(mask));
1120 if (op)
1121 dest = gen_new_qreg(QMODE_I32);
1122 else
1123 dest = -1;
1125 switch (op) {
1126 case 1: /* bchg */
1127 gen_op_xor32(dest, src1, gen_im32(mask));
1128 break;
1129 case 2: /* bclr */
1130 gen_op_and32(dest, src1, gen_im32(~mask));
1131 break;
1132 case 3: /* bset */
1133 gen_op_or32(dest, src1, gen_im32(mask));
1134 break;
1135 default: /* btst */
1136 break;
1138 if (op)
1139 DEST_EA(insn, opsize, dest, &addr);
1142 DISAS_INSN(arith_im)
1144 int op;
1145 int src1;
1146 int dest;
1147 int src2;
1148 int addr;
1150 op = (insn >> 9) & 7;
1151 SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
1152 src2 = gen_im32(read_im32(s));
1153 dest = gen_new_qreg(QMODE_I32);
1154 switch (op) {
1155 case 0: /* ori */
1156 gen_op_or32(dest, src1, src2);
1157 gen_logic_cc(s, dest);
1158 break;
1159 case 1: /* andi */
1160 gen_op_and32(dest, src1, src2);
1161 gen_logic_cc(s, dest);
1162 break;
1163 case 2: /* subi */
1164 gen_op_mov32(dest, src1);
1165 gen_op_update_xflag_lt(dest, src2);
1166 gen_op_sub32(dest, dest, src2);
1167 gen_op_update_cc_add(dest, src2);
1168 s->cc_op = CC_OP_SUB;
1169 break;
1170 case 3: /* addi */
1171 gen_op_mov32(dest, src1);
1172 gen_op_add32(dest, dest, src2);
1173 gen_op_update_cc_add(dest, src2);
1174 gen_op_update_xflag_lt(dest, src2);
1175 s->cc_op = CC_OP_ADD;
1176 break;
1177 case 5: /* eori */
1178 gen_op_xor32(dest, src1, src2);
1179 gen_logic_cc(s, dest);
1180 break;
1181 case 6: /* cmpi */
1182 gen_op_mov32(dest, src1);
1183 gen_op_sub32(dest, dest, src2);
1184 gen_op_update_cc_add(dest, src2);
1185 s->cc_op = CC_OP_SUB;
1186 break;
1187 default:
1188 abort();
1190 if (op != 6) {
1191 DEST_EA(insn, OS_LONG, dest, &addr);
1195 DISAS_INSN(byterev)
1197 int reg;
1199 reg = DREG(insn, 0);
1200 gen_op_bswap32(reg, reg);
1203 DISAS_INSN(move)
1205 int src;
1206 int dest;
1207 int op;
1208 int opsize;
1210 switch (insn >> 12) {
1211 case 1: /* move.b */
1212 opsize = OS_BYTE;
1213 break;
1214 case 2: /* move.l */
1215 opsize = OS_LONG;
1216 break;
1217 case 3: /* move.w */
1218 opsize = OS_WORD;
1219 break;
1220 default:
1221 abort();
1223 SRC_EA(src, opsize, -1, NULL);
1224 op = (insn >> 6) & 7;
1225 if (op == 1) {
1226 /* movea */
1227 /* The value will already have been sign extended. */
1228 dest = AREG(insn, 9);
1229 gen_op_mov32(dest, src);
1230 } else {
1231 /* normal move */
1232 uint16_t dest_ea;
1233 dest_ea = ((insn >> 9) & 7) | (op << 3);
1234 DEST_EA(dest_ea, opsize, src, NULL);
1235 /* This will be correct because loads sign extend. */
1236 gen_logic_cc(s, src);
1240 DISAS_INSN(negx)
1242 int reg;
1243 int dest;
1244 int tmp;
1246 gen_flush_flags(s);
1247 reg = DREG(insn, 0);
1248 dest = gen_new_qreg(QMODE_I32);
1249 gen_op_mov32 (dest, gen_im32(0));
1250 gen_op_subx_cc(dest, reg);
1251 /* !Z is sticky. */
1252 tmp = gen_new_qreg(QMODE_I32);
1253 gen_op_mov32 (tmp, QREG_CC_DEST);
1254 gen_op_update_cc_add(dest, reg);
1255 gen_op_mov32(reg, dest);
1256 s->cc_op = CC_OP_DYNAMIC;
1257 gen_flush_flags(s);
1258 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1259 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1260 s->cc_op = CC_OP_FLAGS;
1263 DISAS_INSN(lea)
1265 int reg;
1266 int tmp;
1268 reg = AREG(insn, 9);
1269 tmp = gen_lea(s, insn, OS_LONG);
1270 if (tmp == -1) {
1271 gen_addr_fault(s);
1272 return;
1274 gen_op_mov32(reg, tmp);
1277 DISAS_INSN(clr)
1279 int opsize;
1281 switch ((insn >> 6) & 3) {
1282 case 0: /* clr.b */
1283 opsize = OS_BYTE;
1284 break;
1285 case 1: /* clr.w */
1286 opsize = OS_WORD;
1287 break;
1288 case 2: /* clr.l */
1289 opsize = OS_LONG;
1290 break;
1291 default:
1292 abort();
1294 DEST_EA(insn, opsize, gen_im32(0), NULL);
1295 gen_logic_cc(s, gen_im32(0));
1298 static int gen_get_ccr(DisasContext *s)
1300 int dest;
1302 gen_flush_flags(s);
1303 dest = gen_new_qreg(QMODE_I32);
1304 gen_op_get_xflag(dest);
1305 gen_op_shl32(dest, dest, gen_im32(4));
1306 gen_op_or32(dest, dest, QREG_CC_DEST);
1307 return dest;
1310 DISAS_INSN(move_from_ccr)
1312 int reg;
1313 int ccr;
1315 ccr = gen_get_ccr(s);
1316 reg = DREG(insn, 0);
1317 gen_partset_reg(OS_WORD, reg, ccr);
1320 DISAS_INSN(neg)
1322 int reg;
1323 int src1;
1325 reg = DREG(insn, 0);
1326 src1 = gen_new_qreg(QMODE_I32);
1327 gen_op_mov32(src1, reg);
1328 gen_op_neg32(reg, src1);
1329 s->cc_op = CC_OP_SUB;
1330 gen_op_update_cc_add(reg, src1);
1331 gen_op_update_xflag_lt(gen_im32(0), src1);
1332 s->cc_op = CC_OP_SUB;
1335 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
1337 gen_op_logic_cc(gen_im32(val & 0xf));
1338 gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
1339 if (!ccr_only) {
1340 gen_op_set_sr(gen_im32(val & 0xff00));
1344 static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1346 int src1;
1347 int reg;
1349 s->cc_op = CC_OP_FLAGS;
1350 if ((insn & 0x38) == 0)
1352 src1 = gen_new_qreg(QMODE_I32);
1353 reg = DREG(insn, 0);
1354 gen_op_and32(src1, reg, gen_im32(0xf));
1355 gen_op_logic_cc(src1);
1356 gen_op_shr32(src1, reg, gen_im32(4));
1357 gen_op_and32(src1, src1, gen_im32(1));
1358 gen_op_update_xflag_tst(src1);
1359 if (!ccr_only) {
1360 gen_op_set_sr(reg);
1363 else if ((insn & 0x3f) == 0x3c)
1365 uint16_t val;
1366 val = lduw_code(s->pc);
1367 s->pc += 2;
1368 gen_set_sr_im(s, val, ccr_only);
1370 else
1371 disas_undef(s, insn);
1374 DISAS_INSN(move_to_ccr)
1376 gen_set_sr(s, insn, 1);
1379 DISAS_INSN(not)
1381 int reg;
1383 reg = DREG(insn, 0);
1384 gen_op_not32(reg, reg);
1385 gen_logic_cc(s, reg);
1388 DISAS_INSN(swap)
1390 int dest;
1391 int src1;
1392 int src2;
1393 int reg;
1395 dest = gen_new_qreg(QMODE_I32);
1396 src1 = gen_new_qreg(QMODE_I32);
1397 src2 = gen_new_qreg(QMODE_I32);
1398 reg = DREG(insn, 0);
1399 gen_op_shl32(src1, reg, gen_im32(16));
1400 gen_op_shr32(src2, reg, gen_im32(16));
1401 gen_op_or32(dest, src1, src2);
1402 gen_op_mov32(reg, dest);
1403 gen_logic_cc(s, dest);
1406 DISAS_INSN(pea)
1408 int tmp;
1410 tmp = gen_lea(s, insn, OS_LONG);
1411 if (tmp == -1) {
1412 gen_addr_fault(s);
1413 return;
1415 gen_push(s, tmp);
1418 DISAS_INSN(ext)
1420 int reg;
1421 int op;
1422 int tmp;
1424 reg = DREG(insn, 0);
1425 op = (insn >> 6) & 7;
1426 tmp = gen_new_qreg(QMODE_I32);
1427 if (op == 3)
1428 gen_op_ext16s32(tmp, reg);
1429 else
1430 gen_op_ext8s32(tmp, reg);
1431 if (op == 2)
1432 gen_partset_reg(OS_WORD, reg, tmp);
1433 else
1434 gen_op_mov32(reg, tmp);
1435 gen_logic_cc(s, tmp);
1438 DISAS_INSN(tst)
1440 int opsize;
1441 int tmp;
1443 switch ((insn >> 6) & 3) {
1444 case 0: /* tst.b */
1445 opsize = OS_BYTE;
1446 break;
1447 case 1: /* tst.w */
1448 opsize = OS_WORD;
1449 break;
1450 case 2: /* tst.l */
1451 opsize = OS_LONG;
1452 break;
1453 default:
1454 abort();
1456 SRC_EA(tmp, opsize, -1, NULL);
1457 gen_logic_cc(s, tmp);
1460 DISAS_INSN(pulse)
1462 /* Implemented as a NOP. */
1465 DISAS_INSN(illegal)
1467 gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1470 /* ??? This should be atomic. */
1471 DISAS_INSN(tas)
1473 int dest;
1474 int src1;
1475 int addr;
1477 dest = gen_new_qreg(QMODE_I32);
1478 SRC_EA(src1, OS_BYTE, -1, &addr);
1479 gen_logic_cc(s, src1);
1480 gen_op_or32(dest, src1, gen_im32(0x80));
1481 DEST_EA(insn, OS_BYTE, dest, &addr);
1484 DISAS_INSN(mull)
1486 uint16_t ext;
1487 int reg;
1488 int src1;
1489 int dest;
1491 /* The upper 32 bits of the product are discarded, so
1492 muls.l and mulu.l are functionally equivalent. */
1493 ext = lduw_code(s->pc);
1494 s->pc += 2;
1495 if (ext & 0x87ff) {
1496 gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1497 return;
1499 reg = DREG(ext, 12);
1500 SRC_EA(src1, OS_LONG, 0, NULL);
1501 dest = gen_new_qreg(QMODE_I32);
1502 gen_op_mul32(dest, src1, reg);
1503 gen_op_mov32(reg, dest);
1504 /* Unlike m68k, coldfire always clears the overflow bit. */
1505 gen_logic_cc(s, dest);
1508 DISAS_INSN(link)
1510 int16_t offset;
1511 int reg;
1512 int tmp;
1514 offset = ldsw_code(s->pc);
1515 s->pc += 2;
1516 reg = AREG(insn, 0);
1517 tmp = gen_new_qreg(QMODE_I32);
1518 gen_op_sub32(tmp, QREG_SP, gen_im32(4));
1519 gen_store(s, OS_LONG, tmp, reg);
1520 if (reg != QREG_SP)
1521 gen_op_mov32(reg, tmp);
1522 gen_op_add32(QREG_SP, tmp, gen_im32(offset));
1525 DISAS_INSN(unlk)
1527 int src;
1528 int reg;
1529 int tmp;
1531 src = gen_new_qreg(QMODE_I32);
1532 reg = AREG(insn, 0);
1533 gen_op_mov32(src, reg);
1534 tmp = gen_load(s, OS_LONG, src, 0);
1535 gen_op_mov32(reg, tmp);
1536 gen_op_add32(QREG_SP, src, gen_im32(4));
1539 DISAS_INSN(nop)
1543 DISAS_INSN(rts)
1545 int tmp;
1547 tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1548 gen_op_add32(QREG_SP, QREG_SP, gen_im32(4));
1549 gen_jmp(s, tmp);
1552 DISAS_INSN(jump)
1554 int tmp;
1556 /* Load the target address first to ensure correct exception
1557 behavior. */
1558 tmp = gen_lea(s, insn, OS_LONG);
1559 if (tmp == -1) {
1560 gen_addr_fault(s);
1561 return;
1563 if ((insn & 0x40) == 0) {
1564 /* jsr */
1565 gen_push(s, gen_im32(s->pc));
1567 gen_jmp(s, tmp);
1570 DISAS_INSN(addsubq)
1572 int src1;
1573 int src2;
1574 int dest;
1575 int val;
1576 int addr;
1578 SRC_EA(src1, OS_LONG, 0, &addr);
1579 val = (insn >> 9) & 7;
1580 if (val == 0)
1581 val = 8;
1582 src2 = gen_im32(val);
1583 dest = gen_new_qreg(QMODE_I32);
1584 gen_op_mov32(dest, src1);
1585 if ((insn & 0x38) == 0x08) {
1586 /* Don't update condition codes if the destination is an
1587 address register. */
1588 if (insn & 0x0100) {
1589 gen_op_sub32(dest, dest, src2);
1590 } else {
1591 gen_op_add32(dest, dest, src2);
1593 } else {
1594 if (insn & 0x0100) {
1595 gen_op_update_xflag_lt(dest, src2);
1596 gen_op_sub32(dest, dest, src2);
1597 s->cc_op = CC_OP_SUB;
1598 } else {
1599 gen_op_add32(dest, dest, src2);
1600 gen_op_update_xflag_lt(dest, src2);
1601 s->cc_op = CC_OP_ADD;
1603 gen_op_update_cc_add(dest, src2);
1605 DEST_EA(insn, OS_LONG, dest, &addr);
1608 DISAS_INSN(tpf)
1610 switch (insn & 7) {
1611 case 2: /* One extension word. */
1612 s->pc += 2;
1613 break;
1614 case 3: /* Two extension words. */
1615 s->pc += 4;
1616 break;
1617 case 4: /* No extension words. */
1618 break;
1619 default:
1620 disas_undef(s, insn);
1624 DISAS_INSN(branch)
1626 int32_t offset;
1627 uint32_t base;
1628 int op;
1629 int l1;
1631 base = s->pc;
1632 op = (insn >> 8) & 0xf;
1633 offset = (int8_t)insn;
1634 if (offset == 0) {
1635 offset = ldsw_code(s->pc);
1636 s->pc += 2;
1637 } else if (offset == -1) {
1638 offset = read_im32(s);
1640 if (op == 1) {
1641 /* bsr */
1642 gen_push(s, gen_im32(s->pc));
1644 gen_flush_cc_op(s);
1645 if (op > 1) {
1646 /* Bcc */
1647 l1 = gen_new_label();
1648 gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1649 gen_jmp_tb(s, 1, base + offset);
1650 gen_set_label(l1);
1651 gen_jmp_tb(s, 0, s->pc);
1652 } else {
1653 /* Unconditional branch. */
1654 gen_jmp_tb(s, 0, base + offset);
1658 DISAS_INSN(moveq)
1660 int tmp;
1662 tmp = gen_im32((int8_t)insn);
1663 gen_op_mov32(DREG(insn, 9), tmp);
1664 gen_logic_cc(s, tmp);
1667 DISAS_INSN(mvzs)
1669 int opsize;
1670 int src;
1671 int reg;
1673 if (insn & 0x40)
1674 opsize = OS_WORD;
1675 else
1676 opsize = OS_BYTE;
1677 SRC_EA(src, opsize, (insn & 0x80) ? 0 : -1, NULL);
1678 reg = DREG(insn, 9);
1679 gen_op_mov32(reg, src);
1680 gen_logic_cc(s, src);
1683 DISAS_INSN(or)
1685 int reg;
1686 int dest;
1687 int src;
1688 int addr;
1690 reg = DREG(insn, 9);
1691 dest = gen_new_qreg(QMODE_I32);
1692 if (insn & 0x100) {
1693 SRC_EA(src, OS_LONG, 0, &addr);
1694 gen_op_or32(dest, src, reg);
1695 DEST_EA(insn, OS_LONG, dest, &addr);
1696 } else {
1697 SRC_EA(src, OS_LONG, 0, NULL);
1698 gen_op_or32(dest, src, reg);
1699 gen_op_mov32(reg, dest);
1701 gen_logic_cc(s, dest);
1704 DISAS_INSN(suba)
1706 int src;
1707 int reg;
1709 SRC_EA(src, OS_LONG, 0, NULL);
1710 reg = AREG(insn, 9);
1711 gen_op_sub32(reg, reg, src);
1714 DISAS_INSN(subx)
1716 int reg;
1717 int src;
1718 int dest;
1719 int tmp;
1721 gen_flush_flags(s);
1722 reg = DREG(insn, 9);
1723 src = DREG(insn, 0);
1724 dest = gen_new_qreg(QMODE_I32);
1725 gen_op_mov32 (dest, reg);
1726 gen_op_subx_cc(dest, src);
1727 /* !Z is sticky. */
1728 tmp = gen_new_qreg(QMODE_I32);
1729 gen_op_mov32 (tmp, QREG_CC_DEST);
1730 gen_op_update_cc_add(dest, src);
1731 gen_op_mov32(reg, dest);
1732 s->cc_op = CC_OP_DYNAMIC;
1733 gen_flush_flags(s);
1734 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1735 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1736 s->cc_op = CC_OP_FLAGS;
1739 DISAS_INSN(mov3q)
1741 int src;
1742 int val;
1744 val = (insn >> 9) & 7;
1745 if (val == 0)
1746 val = -1;
1747 src = gen_im32(val);
1748 gen_logic_cc(s, src);
1749 DEST_EA(insn, OS_LONG, src, NULL);
1752 DISAS_INSN(cmp)
1754 int op;
1755 int src;
1756 int reg;
1757 int dest;
1758 int opsize;
1760 op = (insn >> 6) & 3;
1761 switch (op) {
1762 case 0: /* cmp.b */
1763 opsize = OS_BYTE;
1764 s->cc_op = CC_OP_CMPB;
1765 break;
1766 case 1: /* cmp.w */
1767 opsize = OS_WORD;
1768 s->cc_op = CC_OP_CMPW;
1769 break;
1770 case 2: /* cmp.l */
1771 opsize = OS_LONG;
1772 s->cc_op = CC_OP_SUB;
1773 break;
1774 default:
1775 abort();
1777 SRC_EA(src, opsize, -1, NULL);
1778 reg = DREG(insn, 9);
1779 dest = gen_new_qreg(QMODE_I32);
1780 gen_op_sub32(dest, reg, src);
1781 gen_op_update_cc_add(dest, src);
1784 DISAS_INSN(cmpa)
1786 int opsize;
1787 int src;
1788 int reg;
1789 int dest;
1791 if (insn & 0x100) {
1792 opsize = OS_LONG;
1793 } else {
1794 opsize = OS_WORD;
1796 SRC_EA(src, opsize, -1, NULL);
1797 reg = AREG(insn, 9);
1798 dest = gen_new_qreg(QMODE_I32);
1799 gen_op_sub32(dest, reg, src);
1800 gen_op_update_cc_add(dest, src);
1801 s->cc_op = CC_OP_SUB;
1804 DISAS_INSN(eor)
1806 int src;
1807 int reg;
1808 int dest;
1809 int addr;
1811 SRC_EA(src, OS_LONG, 0, &addr);
1812 reg = DREG(insn, 9);
1813 dest = gen_new_qreg(QMODE_I32);
1814 gen_op_xor32(dest, src, reg);
1815 gen_logic_cc(s, dest);
1816 DEST_EA(insn, OS_LONG, dest, &addr);
1819 DISAS_INSN(and)
1821 int src;
1822 int reg;
1823 int dest;
1824 int addr;
1826 reg = DREG(insn, 9);
1827 dest = gen_new_qreg(QMODE_I32);
1828 if (insn & 0x100) {
1829 SRC_EA(src, OS_LONG, 0, &addr);
1830 gen_op_and32(dest, src, reg);
1831 DEST_EA(insn, OS_LONG, dest, &addr);
1832 } else {
1833 SRC_EA(src, OS_LONG, 0, NULL);
1834 gen_op_and32(dest, src, reg);
1835 gen_op_mov32(reg, dest);
1837 gen_logic_cc(s, dest);
1840 DISAS_INSN(adda)
1842 int src;
1843 int reg;
1845 SRC_EA(src, OS_LONG, 0, NULL);
1846 reg = AREG(insn, 9);
1847 gen_op_add32(reg, reg, src);
1850 DISAS_INSN(addx)
1852 int reg;
1853 int src;
1854 int dest;
1855 int tmp;
1857 gen_flush_flags(s);
1858 reg = DREG(insn, 9);
1859 src = DREG(insn, 0);
1860 dest = gen_new_qreg(QMODE_I32);
1861 gen_op_mov32 (dest, reg);
1862 gen_op_addx_cc(dest, src);
1863 /* !Z is sticky. */
1864 tmp = gen_new_qreg(QMODE_I32);
1865 gen_op_mov32 (tmp, QREG_CC_DEST);
1866 gen_op_update_cc_add(dest, src);
1867 gen_op_mov32(reg, dest);
1868 s->cc_op = CC_OP_DYNAMIC;
1869 gen_flush_flags(s);
1870 gen_op_or32(tmp, tmp, gen_im32(~CCF_Z));
1871 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1872 s->cc_op = CC_OP_FLAGS;
1875 DISAS_INSN(shift_im)
1877 int reg;
1878 int tmp;
1880 reg = DREG(insn, 0);
1881 tmp = (insn >> 9) & 7;
1882 if (tmp == 0)
1883 tmp = 8;
1884 if (insn & 0x100) {
1885 gen_op_shl_im_cc(reg, tmp);
1886 s->cc_op = CC_OP_SHL;
1887 } else {
1888 if (insn & 8) {
1889 gen_op_shr_im_cc(reg, tmp);
1890 s->cc_op = CC_OP_SHR;
1891 } else {
1892 gen_op_sar_im_cc(reg, tmp);
1893 s->cc_op = CC_OP_SAR;
1898 DISAS_INSN(shift_reg)
1900 int reg;
1901 int src;
1902 int tmp;
1904 reg = DREG(insn, 0);
1905 src = DREG(insn, 9);
1906 tmp = gen_new_qreg(QMODE_I32);
1907 gen_op_and32(tmp, src, gen_im32(63));
1908 if (insn & 0x100) {
1909 gen_op_shl_cc(reg, tmp);
1910 s->cc_op = CC_OP_SHL;
1911 } else {
1912 if (insn & 8) {
1913 gen_op_shr_cc(reg, tmp);
1914 s->cc_op = CC_OP_SHR;
1915 } else {
1916 gen_op_sar_cc(reg, tmp);
1917 s->cc_op = CC_OP_SAR;
1922 DISAS_INSN(ff1)
1924 int reg;
1925 reg = DREG(insn, 0);
1926 gen_logic_cc(s, reg);
1927 gen_op_ff1(reg, reg);
1930 static int gen_get_sr(DisasContext *s)
1932 int ccr;
1933 int sr;
1935 ccr = gen_get_ccr(s);
1936 sr = gen_new_qreg(QMODE_I32);
1937 gen_op_and32(sr, QREG_SR, gen_im32(0xffe0));
1938 gen_op_or32(sr, sr, ccr);
1939 return sr;
1942 DISAS_INSN(strldsr)
1944 uint16_t ext;
1945 uint32_t addr;
1947 addr = s->pc - 2;
1948 ext = lduw_code(s->pc);
1949 s->pc += 2;
1950 if (ext != 0x46FC) {
1951 gen_exception(s, addr, EXCP_UNSUPPORTED);
1952 return;
1954 ext = lduw_code(s->pc);
1955 s->pc += 2;
1956 if (IS_USER(s) || (ext & SR_S) == 0) {
1957 gen_exception(s, addr, EXCP_PRIVILEGE);
1958 return;
1960 gen_push(s, gen_get_sr(s));
1961 gen_set_sr_im(s, ext, 0);
1964 DISAS_INSN(move_from_sr)
1966 int reg;
1967 int sr;
1969 if (IS_USER(s)) {
1970 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1971 return;
1973 sr = gen_get_sr(s);
1974 reg = DREG(insn, 0);
1975 gen_partset_reg(OS_WORD, reg, sr);
1978 DISAS_INSN(move_to_sr)
1980 if (IS_USER(s)) {
1981 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1982 return;
1984 gen_set_sr(s, insn, 0);
1985 gen_lookup_tb(s);
1988 DISAS_INSN(move_from_usp)
1990 if (IS_USER(s)) {
1991 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1992 return;
1994 /* TODO: Implement USP. */
1995 gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1998 DISAS_INSN(move_to_usp)
2000 if (IS_USER(s)) {
2001 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2002 return;
2004 /* TODO: Implement USP. */
2005 gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
2008 DISAS_INSN(halt)
2010 gen_jmp(s, gen_im32(s->pc));
2011 gen_op_halt();
2014 DISAS_INSN(stop)
2016 uint16_t ext;
2018 if (IS_USER(s)) {
2019 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2020 return;
2023 ext = lduw_code(s->pc);
2024 s->pc += 2;
2026 gen_set_sr_im(s, ext, 0);
2027 gen_jmp(s, gen_im32(s->pc));
2028 gen_op_stop();
2031 DISAS_INSN(rte)
2033 if (IS_USER(s)) {
2034 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2035 return;
2037 gen_exception(s, s->pc - 2, EXCP_RTE);
2040 DISAS_INSN(movec)
2042 uint16_t ext;
2043 int reg;
2045 if (IS_USER(s)) {
2046 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2047 return;
2050 ext = lduw_code(s->pc);
2051 s->pc += 2;
2053 if (ext & 0x8000) {
2054 reg = AREG(ext, 12);
2055 } else {
2056 reg = DREG(ext, 12);
2058 gen_op_movec(gen_im32(ext & 0xfff), reg);
2059 gen_lookup_tb(s);
2062 DISAS_INSN(intouch)
2064 if (IS_USER(s)) {
2065 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2066 return;
2068 /* ICache fetch. Implement as no-op. */
2071 DISAS_INSN(cpushl)
2073 if (IS_USER(s)) {
2074 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2075 return;
2077 /* Cache push/invalidate. Implement as no-op. */
2080 DISAS_INSN(wddata)
2082 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2085 DISAS_INSN(wdebug)
2087 if (IS_USER(s)) {
2088 gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2089 return;
2091 /* TODO: Implement wdebug. */
2092 qemu_assert(0, "WDEBUG not implemented");
2095 DISAS_INSN(trap)
2097 gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
2100 /* ??? FP exceptions are not implemented. Most exceptions are deferred until
2101 immediately before the next FP instruction is executed. */
2102 DISAS_INSN(fpu)
2104 uint16_t ext;
2105 int opmode;
2106 int src;
2107 int dest;
2108 int res;
2109 int round;
2110 int opsize;
2112 ext = lduw_code(s->pc);
2113 s->pc += 2;
2114 opmode = ext & 0x7f;
2115 switch ((ext >> 13) & 7) {
2116 case 0: case 2:
2117 break;
2118 case 1:
2119 goto undef;
2120 case 3: /* fmove out */
2121 src = FREG(ext, 7);
2122 /* fmove */
2123 /* ??? TODO: Proper behavior on overflow. */
2124 switch ((ext >> 10) & 7) {
2125 case 0:
2126 opsize = OS_LONG;
2127 res = gen_new_qreg(QMODE_I32);
2128 gen_op_f64_to_i32(res, src);
2129 break;
2130 case 1:
2131 opsize = OS_SINGLE;
2132 res = gen_new_qreg(QMODE_F32);
2133 gen_op_f64_to_f32(res, src);
2134 break;
2135 case 4:
2136 opsize = OS_WORD;
2137 res = gen_new_qreg(QMODE_I32);
2138 gen_op_f64_to_i32(res, src);
2139 break;
2140 case 5:
2141 opsize = OS_DOUBLE;
2142 res = src;
2143 break;
2144 case 6:
2145 opsize = OS_BYTE;
2146 res = gen_new_qreg(QMODE_I32);
2147 gen_op_f64_to_i32(res, src);
2148 break;
2149 default:
2150 goto undef;
2152 DEST_EA(insn, opsize, res, NULL);
2153 return;
2154 case 4: /* fmove to control register. */
2155 switch ((ext >> 10) & 7) {
2156 case 4: /* FPCR */
2157 /* Not implemented. Ignore writes. */
2158 break;
2159 case 1: /* FPIAR */
2160 case 2: /* FPSR */
2161 default:
2162 cpu_abort(NULL, "Unimplemented: fmove to control %d",
2163 (ext >> 10) & 7);
2165 break;
2166 case 5: /* fmove from control register. */
2167 switch ((ext >> 10) & 7) {
2168 case 4: /* FPCR */
2169 /* Not implemented. Always return zero. */
2170 res = gen_im32(0);
2171 break;
2172 case 1: /* FPIAR */
2173 case 2: /* FPSR */
2174 default:
2175 cpu_abort(NULL, "Unimplemented: fmove from control %d",
2176 (ext >> 10) & 7);
2177 goto undef;
2179 DEST_EA(insn, OS_LONG, res, NULL);
2180 break;
2181 case 6: /* fmovem */
2182 case 7:
2184 int addr;
2185 uint16_t mask;
2186 if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2187 goto undef;
2188 src = gen_lea(s, insn, OS_LONG);
2189 if (src == -1) {
2190 gen_addr_fault(s);
2191 return;
2193 addr = gen_new_qreg(QMODE_I32);
2194 gen_op_mov32(addr, src);
2195 mask = 0x80;
2196 dest = QREG_F0;
2197 while (mask) {
2198 if (ext & mask) {
2199 s->is_mem = 1;
2200 if (ext & (1 << 13)) {
2201 /* store */
2202 gen_st(s, f64, addr, dest);
2203 } else {
2204 /* load */
2205 gen_ld(s, f64, dest, addr);
2207 if (ext & (mask - 1))
2208 gen_op_add32(addr, addr, gen_im32(8));
2210 mask >>= 1;
2211 dest++;
2214 return;
2216 if (ext & (1 << 14)) {
2217 int tmp;
2219 /* Source effective address. */
2220 switch ((ext >> 10) & 7) {
2221 case 0: opsize = OS_LONG; break;
2222 case 1: opsize = OS_SINGLE; break;
2223 case 4: opsize = OS_WORD; break;
2224 case 5: opsize = OS_DOUBLE; break;
2225 case 6: opsize = OS_BYTE; break;
2226 default:
2227 goto undef;
2229 SRC_EA(tmp, opsize, -1, NULL);
2230 if (opsize == OS_DOUBLE) {
2231 src = tmp;
2232 } else {
2233 src = gen_new_qreg(QMODE_F64);
2234 switch (opsize) {
2235 case OS_LONG:
2236 case OS_WORD:
2237 case OS_BYTE:
2238 gen_op_i32_to_f64(src, tmp);
2239 break;
2240 case OS_SINGLE:
2241 gen_op_f32_to_f64(src, tmp);
2242 break;
2245 } else {
2246 /* Source register. */
2247 src = FREG(ext, 10);
2249 dest = FREG(ext, 7);
2250 res = gen_new_qreg(QMODE_F64);
2251 if (opmode != 0x3a)
2252 gen_op_movf64(res, dest);
2253 round = 1;
2254 switch (opmode) {
2255 case 0: case 0x40: case 0x44: /* fmove */
2256 gen_op_movf64(res, src);
2257 break;
2258 case 1: /* fint */
2259 gen_op_iround_f64(res, src);
2260 round = 0;
2261 break;
2262 case 3: /* fintrz */
2263 gen_op_itrunc_f64(res, src);
2264 round = 0;
2265 break;
2266 case 4: case 0x41: case 0x45: /* fsqrt */
2267 gen_op_sqrtf64(res, src);
2268 break;
2269 case 0x18: case 0x58: case 0x5c: /* fabs */
2270 gen_op_absf64(res, src);
2271 break;
2272 case 0x1a: case 0x5a: case 0x5e: /* fneg */
2273 gen_op_chsf64(res, src);
2274 break;
2275 case 0x20: case 0x60: case 0x64: /* fdiv */
2276 gen_op_divf64(res, res, src);
2277 break;
2278 case 0x22: case 0x62: case 0x66: /* fadd */
2279 gen_op_addf64(res, res, src);
2280 break;
2281 case 0x23: case 0x63: case 0x67: /* fmul */
2282 gen_op_mulf64(res, res, src);
2283 break;
2284 case 0x28: case 0x68: case 0x6c: /* fsub */
2285 gen_op_subf64(res, res, src);
2286 break;
2287 case 0x38: /* fcmp */
2288 gen_op_sub_cmpf64(res, res, src);
2289 dest = 0;
2290 round = 0;
2291 break;
2292 case 0x3a: /* ftst */
2293 gen_op_movf64(res, src);
2294 dest = 0;
2295 round = 0;
2296 break;
2297 default:
2298 goto undef;
2300 if (round) {
2301 if (opmode & 0x40) {
2302 if ((opmode & 0x4) != 0)
2303 round = 0;
2304 } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2305 round = 0;
2308 if (round) {
2309 int tmp;
2311 tmp = gen_new_qreg(QMODE_F32);
2312 gen_op_f64_to_f32(tmp, res);
2313 gen_op_f32_to_f64(res, tmp);
2315 gen_op_fp_result(res);
2316 if (dest) {
2317 gen_op_movf64(dest, res);
2319 return;
2320 undef:
2321 s->pc -= 2;
2322 disas_undef_fpu(s, insn);
2325 DISAS_INSN(fbcc)
2327 uint32_t offset;
2328 uint32_t addr;
2329 int flag;
2330 int zero;
2331 int l1;
2333 addr = s->pc;
2334 offset = ldsw_code(s->pc);
2335 s->pc += 2;
2336 if (insn & (1 << 6)) {
2337 offset = (offset << 16) | lduw_code(s->pc);
2338 s->pc += 2;
2341 l1 = gen_new_label();
2342 /* TODO: Raise BSUN exception. */
2343 flag = gen_new_qreg(QMODE_I32);
2344 zero = gen_new_qreg(QMODE_F64);
2345 gen_op_zerof64(zero);
2346 gen_op_compare_quietf64(flag, QREG_FP_RESULT, zero);
2347 /* Jump to l1 if condition is true. */
2348 switch (insn & 0xf) {
2349 case 0: /* f */
2350 break;
2351 case 1: /* eq (=0) */
2352 gen_op_jmp_z32(flag, l1);
2353 break;
2354 case 2: /* ogt (=1) */
2355 gen_op_sub32(flag, flag, gen_im32(1));
2356 gen_op_jmp_z32(flag, l1);
2357 break;
2358 case 3: /* oge (=0 or =1) */
2359 gen_op_jmp_z32(flag, l1);
2360 gen_op_sub32(flag, flag, gen_im32(1));
2361 gen_op_jmp_z32(flag, l1);
2362 break;
2363 case 4: /* olt (=-1) */
2364 gen_op_jmp_s32(flag, l1);
2365 break;
2366 case 5: /* ole (=-1 or =0) */
2367 gen_op_jmp_s32(flag, l1);
2368 gen_op_jmp_z32(flag, l1);
2369 break;
2370 case 6: /* ogl (=-1 or =1) */
2371 gen_op_jmp_s32(flag, l1);
2372 gen_op_sub32(flag, flag, gen_im32(1));
2373 gen_op_jmp_z32(flag, l1);
2374 break;
2375 case 7: /* or (=2) */
2376 gen_op_sub32(flag, flag, gen_im32(2));
2377 gen_op_jmp_z32(flag, l1);
2378 break;
2379 case 8: /* un (<2) */
2380 gen_op_sub32(flag, flag, gen_im32(2));
2381 gen_op_jmp_s32(flag, l1);
2382 break;
2383 case 9: /* ueq (=0 or =2) */
2384 gen_op_jmp_z32(flag, l1);
2385 gen_op_sub32(flag, flag, gen_im32(2));
2386 gen_op_jmp_z32(flag, l1);
2387 break;
2388 case 10: /* ugt (>0) */
2389 /* ??? Add jmp_gtu. */
2390 gen_op_sub32(flag, flag, gen_im32(1));
2391 gen_op_jmp_ns32(flag, l1);
2392 break;
2393 case 11: /* uge (>=0) */
2394 gen_op_jmp_ns32(flag, l1);
2395 break;
2396 case 12: /* ult (=-1 or =2) */
2397 gen_op_jmp_s32(flag, l1);
2398 gen_op_sub32(flag, flag, gen_im32(2));
2399 gen_op_jmp_z32(flag, l1);
2400 break;
2401 case 13: /* ule (!=1) */
2402 gen_op_sub32(flag, flag, gen_im32(1));
2403 gen_op_jmp_nz32(flag, l1);
2404 break;
2405 case 14: /* ne (!=0) */
2406 gen_op_jmp_nz32(flag, l1);
2407 break;
2408 case 15: /* t */
2409 gen_op_mov32(flag, gen_im32(1));
2410 break;
2412 gen_jmp_tb(s, 0, s->pc);
2413 gen_set_label(l1);
2414 gen_jmp_tb(s, 1, addr + offset);
2417 DISAS_INSN(frestore)
2419 /* TODO: Implement frestore. */
2420 qemu_assert(0, "FRESTORE not implemented");
2423 DISAS_INSN(fsave)
2425 /* TODO: Implement fsave. */
2426 qemu_assert(0, "FSAVE not implemented");
2429 static inline int gen_mac_extract_word(DisasContext *s, int val, int upper)
2431 int tmp = gen_new_qreg(QMODE_I32);
2432 if (s->env->macsr & MACSR_FI) {
2433 if (upper)
2434 gen_op_and32(tmp, val, gen_im32(0xffff0000));
2435 else
2436 gen_op_shl32(tmp, val, gen_im32(16));
2437 } else if (s->env->macsr & MACSR_SU) {
2438 if (upper)
2439 gen_op_sar32(tmp, val, gen_im32(16));
2440 else
2441 gen_op_ext16s32(tmp, val);
2442 } else {
2443 if (upper)
2444 gen_op_shr32(tmp, val, gen_im32(16));
2445 else
2446 gen_op_ext16u32(tmp, val);
2448 return tmp;
2451 DISAS_INSN(mac)
2453 int rx;
2454 int ry;
2455 uint16_t ext;
2456 int acc;
2457 int l1;
2458 int tmp;
2459 int addr;
2460 int loadval;
2461 int dual;
2462 int saved_flags = -1;
2464 ext = lduw_code(s->pc);
2465 s->pc += 2;
2467 acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
2468 dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
2469 if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
2470 disas_undef(s, insn);
2471 return;
2473 if (insn & 0x30) {
2474 /* MAC with load. */
2475 tmp = gen_lea(s, insn, OS_LONG);
2476 addr = gen_new_qreg(QMODE_I32);
2477 gen_op_and32(addr, tmp, QREG_MAC_MASK);
2478 /* Load the value now to ensure correct exception behavior.
2479 Perform writeback after reading the MAC inputs. */
2480 loadval = gen_load(s, OS_LONG, addr, 0);
2482 acc ^= 1;
2483 rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
2484 ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
2485 } else {
2486 loadval = addr = -1;
2487 rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2488 ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2491 gen_op_mac_clear_flags();
2492 l1 = -1;
2493 if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
2494 /* Skip the multiply if we know we will ignore it. */
2495 l1 = gen_new_label();
2496 tmp = gen_new_qreg(QMODE_I32);
2497 gen_op_and32(tmp, QREG_MACSR, gen_im32(1 << (acc + 8)));
2498 gen_op_jmp_nz32(tmp, l1);
2501 if ((ext & 0x0800) == 0) {
2502 /* Word. */
2503 rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
2504 ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
2506 if (s->env->macsr & MACSR_FI) {
2507 gen_op_macmulf(rx, ry);
2508 } else {
2509 if (s->env->macsr & MACSR_SU)
2510 gen_op_macmuls(rx, ry);
2511 else
2512 gen_op_macmulu(rx, ry);
2513 switch ((ext >> 9) & 3) {
2514 case 1:
2515 gen_op_macshl();
2516 break;
2517 case 3:
2518 gen_op_macshr();
2519 break;
2523 if (dual) {
2524 /* Save the overflow flag from the multiply. */
2525 saved_flags = gen_new_qreg(QMODE_I32);
2526 gen_op_mov32(saved_flags, QREG_MACSR);
2529 if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
2530 /* Skip the accumulate if the value is already saturated. */
2531 l1 = gen_new_label();
2532 tmp = gen_new_qreg(QMODE_I32);
2533 gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2534 gen_op_jmp_nz32(tmp, l1);
2537 if (insn & 0x100)
2538 gen_op_macsub(acc);
2539 else
2540 gen_op_macadd(acc);
2542 if (s->env->macsr & MACSR_FI)
2543 gen_op_macsatf(acc);
2544 else if (s->env->macsr & MACSR_SU)
2545 gen_op_macsats(acc);
2546 else
2547 gen_op_macsatu(acc);
2549 if (l1 != -1)
2550 gen_set_label(l1);
2552 if (dual) {
2553 /* Dual accumulate variant. */
2554 acc = (ext >> 2) & 3;
2555 /* Restore the overflow flag from the multiplier. */
2556 gen_op_mov32(QREG_MACSR, saved_flags);
2557 if ((s->env->macsr & MACSR_OMC) != 0) {
2558 /* Skip the accumulate if the value is already saturated. */
2559 l1 = gen_new_label();
2560 tmp = gen_new_qreg(QMODE_I32);
2561 gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2562 gen_op_jmp_nz32(tmp, l1);
2564 if (ext & 2)
2565 gen_op_macsub(acc);
2566 else
2567 gen_op_macadd(acc);
2568 if (s->env->macsr & MACSR_FI)
2569 gen_op_macsatf(acc);
2570 else if (s->env->macsr & MACSR_SU)
2571 gen_op_macsats(acc);
2572 else
2573 gen_op_macsatu(acc);
2574 if (l1 != -1)
2575 gen_set_label(l1);
2577 gen_op_mac_set_flags(acc);
2579 if (insn & 0x30) {
2580 int rw;
2581 rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2582 gen_op_mov32(rw, loadval);
2583 /* FIXME: Should address writeback happen with the masked or
2584 unmasked value? */
2585 switch ((insn >> 3) & 7) {
2586 case 3: /* Post-increment. */
2587 gen_op_add32(AREG(insn, 0), addr, gen_im32(4));
2588 break;
2589 case 4: /* Pre-decrement. */
2590 gen_op_mov32(AREG(insn, 0), addr);
2595 DISAS_INSN(from_mac)
2597 int rx;
2598 int acc;
2600 rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2601 acc = (insn >> 9) & 3;
2602 if (s->env->macsr & MACSR_FI) {
2603 gen_op_get_macf(rx, acc);
2604 } else if ((s->env->macsr & MACSR_OMC) == 0) {
2605 gen_op_get_maci(rx, acc);
2606 } else if (s->env->macsr & MACSR_SU) {
2607 gen_op_get_macs(rx, acc);
2608 } else {
2609 gen_op_get_macu(rx, acc);
2611 if (insn & 0x40)
2612 gen_op_clear_mac(acc);
2615 DISAS_INSN(move_mac)
2617 int src;
2618 int dest;
2619 src = insn & 3;
2620 dest = (insn >> 9) & 3;
2621 gen_op_move_mac(dest, src);
2622 gen_op_mac_clear_flags();
2623 gen_op_mac_set_flags(dest);
2626 DISAS_INSN(from_macsr)
2628 int reg;
2630 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2631 gen_op_mov32(reg, QREG_MACSR);
2634 DISAS_INSN(from_mask)
2636 int reg;
2637 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2638 gen_op_mov32(reg, QREG_MAC_MASK);
2641 DISAS_INSN(from_mext)
2643 int reg;
2644 int acc;
2645 reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2646 acc = (insn & 0x400) ? 2 : 0;
2647 if (s->env->macsr & MACSR_FI)
2648 gen_op_get_mac_extf(reg, acc);
2649 else
2650 gen_op_get_mac_exti(reg, acc);
2653 DISAS_INSN(macsr_to_ccr)
2655 gen_op_mov32(QREG_CC_X, gen_im32(0));
2656 gen_op_and32(QREG_CC_DEST, QREG_MACSR, gen_im32(0xf));
2657 s->cc_op = CC_OP_FLAGS;
2660 DISAS_INSN(to_mac)
2662 int acc;
2663 int val;
2664 acc = (insn >>9) & 3;
2665 SRC_EA(val, OS_LONG, 0, NULL);
2666 if (s->env->macsr & MACSR_FI) {
2667 gen_op_set_macf(val, acc);
2668 } else if (s->env->macsr & MACSR_SU) {
2669 gen_op_set_macs(val, acc);
2670 } else {
2671 gen_op_set_macu(val, acc);
2673 gen_op_mac_clear_flags();
2674 gen_op_mac_set_flags(acc);
2677 DISAS_INSN(to_macsr)
2679 int val;
2680 SRC_EA(val, OS_LONG, 0, NULL);
2681 gen_op_set_macsr(val);
2682 gen_lookup_tb(s);
2685 DISAS_INSN(to_mask)
2687 int val;
2688 SRC_EA(val, OS_LONG, 0, NULL);
2689 gen_op_or32(QREG_MAC_MASK, val, gen_im32(0xffff0000));
2692 DISAS_INSN(to_mext)
2694 int val;
2695 int acc;
2696 SRC_EA(val, OS_LONG, 0, NULL);
2697 acc = (insn & 0x400) ? 2 : 0;
2698 if (s->env->macsr & MACSR_FI)
2699 gen_op_set_mac_extf(val, acc);
2700 else if (s->env->macsr & MACSR_SU)
2701 gen_op_set_mac_exts(val, acc);
2702 else
2703 gen_op_set_mac_extu(val, acc);
2706 static disas_proc opcode_table[65536];
2708 static void
2709 register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2711 int i;
2712 int from;
2713 int to;
2715 /* Sanity check. All set bits must be included in the mask. */
2716 if (opcode & ~mask) {
2717 fprintf(stderr,
2718 "qemu internal error: bogus opcode definition %04x/%04x\n",
2719 opcode, mask);
2720 abort();
2722 /* This could probably be cleverer. For now just optimize the case where
2723 the top bits are known. */
2724 /* Find the first zero bit in the mask. */
2725 i = 0x8000;
2726 while ((i & mask) != 0)
2727 i >>= 1;
2728 /* Iterate over all combinations of this and lower bits. */
2729 if (i == 0)
2730 i = 1;
2731 else
2732 i <<= 1;
2733 from = opcode & ~(i - 1);
2734 to = from + i;
2735 for (i = from; i < to; i++) {
2736 if ((i & mask) == opcode)
2737 opcode_table[i] = proc;
2741 /* Register m68k opcode handlers. Order is important.
2742 Later insn override earlier ones. */
2743 void register_m68k_insns (CPUM68KState *env)
2745 #define INSN(name, opcode, mask, feature) do { \
2746 if (m68k_feature(env, M68K_FEATURE_##feature)) \
2747 register_opcode(disas_##name, 0x##opcode, 0x##mask); \
2748 } while(0)
2749 INSN(undef, 0000, 0000, CF_ISA_A);
2750 INSN(arith_im, 0080, fff8, CF_ISA_A);
2751 INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC);
2752 INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
2753 INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
2754 INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
2755 INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
2756 INSN(arith_im, 0280, fff8, CF_ISA_A);
2757 INSN(byterev, 02c0, fff8, CF_ISA_APLUSC);
2758 INSN(arith_im, 0480, fff8, CF_ISA_A);
2759 INSN(ff1, 04c0, fff8, CF_ISA_APLUSC);
2760 INSN(arith_im, 0680, fff8, CF_ISA_A);
2761 INSN(bitop_im, 0800, ffc0, CF_ISA_A);
2762 INSN(bitop_im, 0840, ffc0, CF_ISA_A);
2763 INSN(bitop_im, 0880, ffc0, CF_ISA_A);
2764 INSN(bitop_im, 08c0, ffc0, CF_ISA_A);
2765 INSN(arith_im, 0a80, fff8, CF_ISA_A);
2766 INSN(arith_im, 0c00, ff38, CF_ISA_A);
2767 INSN(move, 1000, f000, CF_ISA_A);
2768 INSN(move, 2000, f000, CF_ISA_A);
2769 INSN(move, 3000, f000, CF_ISA_A);
2770 INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC);
2771 INSN(negx, 4080, fff8, CF_ISA_A);
2772 INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
2773 INSN(lea, 41c0, f1c0, CF_ISA_A);
2774 INSN(clr, 4200, ff00, CF_ISA_A);
2775 INSN(undef, 42c0, ffc0, CF_ISA_A);
2776 INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
2777 INSN(neg, 4480, fff8, CF_ISA_A);
2778 INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
2779 INSN(not, 4680, fff8, CF_ISA_A);
2780 INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
2781 INSN(pea, 4840, ffc0, CF_ISA_A);
2782 INSN(swap, 4840, fff8, CF_ISA_A);
2783 INSN(movem, 48c0, fbc0, CF_ISA_A);
2784 INSN(ext, 4880, fff8, CF_ISA_A);
2785 INSN(ext, 48c0, fff8, CF_ISA_A);
2786 INSN(ext, 49c0, fff8, CF_ISA_A);
2787 INSN(tst, 4a00, ff00, CF_ISA_A);
2788 INSN(tas, 4ac0, ffc0, CF_ISA_B);
2789 INSN(halt, 4ac8, ffff, CF_ISA_A);
2790 INSN(pulse, 4acc, ffff, CF_ISA_A);
2791 INSN(illegal, 4afc, ffff, CF_ISA_A);
2792 INSN(mull, 4c00, ffc0, CF_ISA_A);
2793 INSN(divl, 4c40, ffc0, CF_ISA_A);
2794 INSN(sats, 4c80, fff8, CF_ISA_B);
2795 INSN(trap, 4e40, fff0, CF_ISA_A);
2796 INSN(link, 4e50, fff8, CF_ISA_A);
2797 INSN(unlk, 4e58, fff8, CF_ISA_A);
2798 INSN(move_to_usp, 4e60, fff8, USP);
2799 INSN(move_from_usp, 4e68, fff8, USP);
2800 INSN(nop, 4e71, ffff, CF_ISA_A);
2801 INSN(stop, 4e72, ffff, CF_ISA_A);
2802 INSN(rte, 4e73, ffff, CF_ISA_A);
2803 INSN(rts, 4e75, ffff, CF_ISA_A);
2804 INSN(movec, 4e7b, ffff, CF_ISA_A);
2805 INSN(jump, 4e80, ffc0, CF_ISA_A);
2806 INSN(jump, 4ec0, ffc0, CF_ISA_A);
2807 INSN(addsubq, 5180, f1c0, CF_ISA_A);
2808 INSN(scc, 50c0, f0f8, CF_ISA_A);
2809 INSN(addsubq, 5080, f1c0, CF_ISA_A);
2810 INSN(tpf, 51f8, fff8, CF_ISA_A);
2812 /* Branch instructions. */
2813 INSN(branch, 6000, f000, CF_ISA_A);
2814 /* Disable long branch instructions, then add back the ones we want. */
2815 INSN(undef, 60ff, f0ff, CF_ISA_A); /* All long branches. */
2816 INSN(branch, 60ff, f0ff, CF_ISA_B);
2817 INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */
2818 INSN(branch, 60ff, ffff, BRAL);
2820 INSN(moveq, 7000, f100, CF_ISA_A);
2821 INSN(mvzs, 7100, f100, CF_ISA_B);
2822 INSN(or, 8000, f000, CF_ISA_A);
2823 INSN(divw, 80c0, f0c0, CF_ISA_A);
2824 INSN(addsub, 9000, f000, CF_ISA_A);
2825 INSN(subx, 9180, f1f8, CF_ISA_A);
2826 INSN(suba, 91c0, f1c0, CF_ISA_A);
2828 INSN(undef_mac, a000, f000, CF_ISA_A);
2829 INSN(mac, a000, f100, CF_EMAC);
2830 INSN(from_mac, a180, f9b0, CF_EMAC);
2831 INSN(move_mac, a110, f9fc, CF_EMAC);
2832 INSN(from_macsr,a980, f9f0, CF_EMAC);
2833 INSN(from_mask, ad80, fff0, CF_EMAC);
2834 INSN(from_mext, ab80, fbf0, CF_EMAC);
2835 INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
2836 INSN(to_mac, a100, f9c0, CF_EMAC);
2837 INSN(to_macsr, a900, ffc0, CF_EMAC);
2838 INSN(to_mext, ab00, fbc0, CF_EMAC);
2839 INSN(to_mask, ad00, ffc0, CF_EMAC);
2841 INSN(mov3q, a140, f1c0, CF_ISA_B);
2842 INSN(cmp, b000, f1c0, CF_ISA_B); /* cmp.b */
2843 INSN(cmp, b040, f1c0, CF_ISA_B); /* cmp.w */
2844 INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */
2845 INSN(cmp, b080, f1c0, CF_ISA_A);
2846 INSN(cmpa, b1c0, f1c0, CF_ISA_A);
2847 INSN(eor, b180, f1c0, CF_ISA_A);
2848 INSN(and, c000, f000, CF_ISA_A);
2849 INSN(mulw, c0c0, f0c0, CF_ISA_A);
2850 INSN(addsub, d000, f000, CF_ISA_A);
2851 INSN(addx, d180, f1f8, CF_ISA_A);
2852 INSN(adda, d1c0, f1c0, CF_ISA_A);
2853 INSN(shift_im, e080, f0f0, CF_ISA_A);
2854 INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
2855 INSN(undef_fpu, f000, f000, CF_ISA_A);
2856 INSN(fpu, f200, ffc0, CF_FPU);
2857 INSN(fbcc, f280, ffc0, CF_FPU);
2858 INSN(frestore, f340, ffc0, CF_FPU);
2859 INSN(fsave, f340, ffc0, CF_FPU);
2860 INSN(intouch, f340, ffc0, CF_ISA_A);
2861 INSN(cpushl, f428, ff38, CF_ISA_A);
2862 INSN(wddata, fb00, ff00, CF_ISA_A);
2863 INSN(wdebug, fbc0, ffc0, CF_ISA_A);
2864 #undef INSN
2867 /* ??? Some of this implementation is not exception safe. We should always
2868 write back the result to memory before setting the condition codes. */
2869 static void disas_m68k_insn(CPUState * env, DisasContext *s)
2871 uint16_t insn;
2873 insn = lduw_code(s->pc);
2874 s->pc += 2;
2876 opcode_table[insn](s, insn);
2879 #if 0
2880 /* Save the result of a floating point operation. */
2881 static void expand_op_fp_result(qOP *qop)
2883 gen_op_movf64(QREG_FP_RESULT, qop->args[0]);
2886 /* Dummy op to indicate that the flags have been set. */
2887 static void expand_op_flags_set(qOP *qop)
2891 /* Convert the confition codes into CC_OP_FLAGS format. */
2892 static void expand_op_flush_flags(qOP *qop)
2894 int cc_opreg;
2896 if (qop->args[0] == CC_OP_DYNAMIC)
2897 cc_opreg = QREG_CC_OP;
2898 else
2899 cc_opreg = gen_im32(qop->args[0]);
2900 gen_op_helper32(QREG_NULL, cc_opreg, HELPER_flush_flags);
2903 /* Set CC_DEST after a logical or direct flag setting operation. */
2904 static void expand_op_logic_cc(qOP *qop)
2906 gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2909 /* Set CC_SRC and CC_DEST after an arithmetic operation. */
2910 static void expand_op_update_cc_add(qOP *qop)
2912 gen_op_mov32(QREG_CC_DEST, qop->args[0]);
2913 gen_op_mov32(QREG_CC_SRC, qop->args[1]);
2916 /* Update the X flag. */
2917 static void expand_op_update_xflag(qOP *qop)
2919 int arg0;
2920 int arg1;
2922 arg0 = qop->args[0];
2923 arg1 = qop->args[1];
2924 if (arg1 == QREG_NULL) {
2925 /* CC_X = arg0. */
2926 gen_op_mov32(QREG_CC_X, arg0);
2927 } else {
2928 /* CC_X = arg0 < (unsigned)arg1. */
2929 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
2933 /* Set arg0 to the contents of the X flag. */
2934 static void expand_op_get_xflag(qOP *qop)
2936 gen_op_mov32(qop->args[0], QREG_CC_X);
2939 /* Expand a shift by immediate. The ISA only allows shifts by 1-8, so we
2940 already know the shift is within range. */
2941 static inline void expand_shift_im(qOP *qop, int right, int arith)
2943 int val;
2944 int reg;
2945 int tmp;
2946 int im;
2948 reg = qop->args[0];
2949 im = qop->args[1];
2950 tmp = gen_im32(im);
2951 val = gen_new_qreg(QMODE_I32);
2952 gen_op_mov32(val, reg);
2953 gen_op_mov32(QREG_CC_DEST, val);
2954 gen_op_mov32(QREG_CC_SRC, tmp);
2955 if (right) {
2956 if (arith) {
2957 gen_op_sar32(reg, val, tmp);
2958 } else {
2959 gen_op_shr32(reg, val, tmp);
2961 if (im == 1)
2962 tmp = QREG_NULL;
2963 else
2964 tmp = gen_im32(im - 1);
2965 } else {
2966 gen_op_shl32(reg, val, tmp);
2967 tmp = gen_im32(32 - im);
2969 if (tmp != QREG_NULL)
2970 gen_op_shr32(val, val, tmp);
2971 gen_op_and32(QREG_CC_X, val, gen_im32(1));
2974 static void expand_op_shl_im_cc(qOP *qop)
2976 expand_shift_im(qop, 0, 0);
2979 static void expand_op_shr_im_cc(qOP *qop)
2981 expand_shift_im(qop, 1, 0);
2984 static void expand_op_sar_im_cc(qOP *qop)
2986 expand_shift_im(qop, 1, 1);
2989 /* Expand a shift by register. */
2990 /* ??? This gives incorrect answers for shifts by 0 or >= 32 */
2991 static inline void expand_shift_reg(qOP *qop, int right, int arith)
2993 int val;
2994 int reg;
2995 int shift;
2996 int tmp;
2998 reg = qop->args[0];
2999 shift = qop->args[1];
3000 val = gen_new_qreg(QMODE_I32);
3001 gen_op_mov32(val, reg);
3002 gen_op_mov32(QREG_CC_DEST, val);
3003 gen_op_mov32(QREG_CC_SRC, shift);
3004 tmp = gen_new_qreg(QMODE_I32);
3005 if (right) {
3006 if (arith) {
3007 gen_op_sar32(reg, val, shift);
3008 } else {
3009 gen_op_shr32(reg, val, shift);
3011 gen_op_sub32(tmp, shift, gen_im32(1));
3012 } else {
3013 gen_op_shl32(reg, val, shift);
3014 gen_op_sub32(tmp, gen_im32(31), shift);
3016 gen_op_shl32(val, val, tmp);
3017 gen_op_and32(QREG_CC_X, val, gen_im32(1));
3020 static void expand_op_shl_cc(qOP *qop)
3022 expand_shift_reg(qop, 0, 0);
3025 static void expand_op_shr_cc(qOP *qop)
3027 expand_shift_reg(qop, 1, 0);
3030 static void expand_op_sar_cc(qOP *qop)
3032 expand_shift_reg(qop, 1, 1);
3035 /* Set the Z flag to (arg0 & arg1) == 0. */
3036 static void expand_op_btest(qOP *qop)
3038 int tmp;
3039 int l1;
3041 l1 = gen_new_label();
3042 tmp = gen_new_qreg(QMODE_I32);
3043 gen_op_and32(tmp, qop->args[0], qop->args[1]);
3044 gen_op_and32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(~(uint32_t)CCF_Z));
3045 gen_op_jmp_nz32(tmp, l1);
3046 gen_op_or32(QREG_CC_DEST, QREG_CC_DEST, gen_im32(CCF_Z));
3047 gen_op_label(l1);
3050 /* arg0 += arg1 + CC_X */
3051 static void expand_op_addx_cc(qOP *qop)
3053 int arg0 = qop->args[0];
3054 int arg1 = qop->args[1];
3055 int l1, l2;
3057 gen_op_add32 (arg0, arg0, arg1);
3058 l1 = gen_new_label();
3059 l2 = gen_new_label();
3060 gen_op_jmp_z32(QREG_CC_X, l1);
3061 gen_op_add32(arg0, arg0, gen_im32(1));
3062 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
3063 gen_op_set_leu32(QREG_CC_X, arg0, arg1);
3064 gen_op_jmp_im(l2);
3065 gen_set_label(l1);
3066 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
3067 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
3068 gen_set_label(l2);
3071 /* arg0 -= arg1 + CC_X */
3072 static void expand_op_subx_cc(qOP *qop)
3074 int arg0 = qop->args[0];
3075 int arg1 = qop->args[1];
3076 int l1, l2;
3078 l1 = gen_new_label();
3079 l2 = gen_new_label();
3080 gen_op_jmp_z32(QREG_CC_X, l1);
3081 gen_op_set_leu32(QREG_CC_X, arg0, arg1);
3082 gen_op_sub32(arg0, arg0, gen_im32(1));
3083 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
3084 gen_op_jmp_im(l2);
3085 gen_set_label(l1);
3086 gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
3087 gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
3088 gen_set_label(l2);
3089 gen_op_sub32 (arg0, arg0, arg1);
3092 /* Expand target specific ops to generic qops. */
3093 static void expand_target_qops(void)
3095 qOP *qop;
3096 qOP *next;
3097 int c;
3099 /* Copy the list of qops, expanding target specific ops as we go. */
3100 qop = gen_first_qop;
3101 gen_first_qop = NULL;
3102 gen_last_qop = NULL;
3103 for (; qop; qop = next) {
3104 c = qop->opcode;
3105 next = qop->next;
3106 if (c < FIRST_TARGET_OP) {
3107 qop->prev = gen_last_qop;
3108 qop->next = NULL;
3109 if (gen_last_qop)
3110 gen_last_qop->next = qop;
3111 else
3112 gen_first_qop = qop;
3113 gen_last_qop = qop;
3114 continue;
3116 switch (c) {
3117 #define DEF(name, nargs, barrier) \
3118 case INDEX_op_##name: \
3119 expand_op_##name(qop); \
3120 break;
3121 #include "qop-target.def"
3122 #undef DEF
3123 default:
3124 cpu_abort(NULL, "Unexpanded target qop");
3129 /* ??? Implement this. */
3130 static void
3131 optimize_flags(void)
3134 #endif
3136 /* generate intermediate code for basic block 'tb'. */
3137 static inline int
3138 gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3139 int search_pc)
3141 DisasContext dc1, *dc = &dc1;
3142 uint16_t *gen_opc_end;
3143 int j, lj;
3144 target_ulong pc_start;
3145 int pc_offset;
3146 int last_cc_op;
3148 /* generate intermediate code */
3149 pc_start = tb->pc;
3151 dc->tb = tb;
3153 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3155 dc->env = env;
3156 dc->is_jmp = DISAS_NEXT;
3157 dc->pc = pc_start;
3158 dc->cc_op = CC_OP_DYNAMIC;
3159 dc->singlestep_enabled = env->singlestep_enabled;
3160 dc->fpcr = env->fpcr;
3161 dc->user = (env->sr & SR_S) == 0;
3162 dc->is_mem = 0;
3163 lj = -1;
3164 do {
3165 free_qreg = 0;
3166 pc_offset = dc->pc - pc_start;
3167 gen_throws_exception = NULL;
3168 if (env->nb_breakpoints > 0) {
3169 for(j = 0; j < env->nb_breakpoints; j++) {
3170 if (env->breakpoints[j] == dc->pc) {
3171 gen_exception(dc, dc->pc, EXCP_DEBUG);
3172 dc->is_jmp = DISAS_JUMP;
3173 break;
3176 if (dc->is_jmp)
3177 break;
3179 if (search_pc) {
3180 j = gen_opc_ptr - gen_opc_buf;
3181 if (lj < j) {
3182 lj++;
3183 while (lj < j)
3184 gen_opc_instr_start[lj++] = 0;
3186 gen_opc_pc[lj] = dc->pc;
3187 gen_opc_instr_start[lj] = 1;
3189 last_cc_op = dc->cc_op;
3190 dc->insn_pc = dc->pc;
3191 disas_m68k_insn(env, dc);
3193 /* Terminate the TB on memory ops if watchpoints are present. */
3194 /* FIXME: This should be replacd by the deterministic execution
3195 * IRQ raising bits. */
3196 if (dc->is_mem && env->nb_watchpoints)
3197 break;
3198 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3199 !env->singlestep_enabled &&
3200 (pc_offset) < (TARGET_PAGE_SIZE - 32));
3202 if (__builtin_expect(env->singlestep_enabled, 0)) {
3203 /* Make sure the pc is updated, and raise a debug exception. */
3204 if (!dc->is_jmp) {
3205 gen_flush_cc_op(dc);
3206 gen_op_mov32(QREG_PC, gen_im32((long)dc->pc));
3208 gen_op_raise_exception(EXCP_DEBUG);
3209 } else {
3210 switch(dc->is_jmp) {
3211 case DISAS_NEXT:
3212 gen_flush_cc_op(dc);
3213 gen_jmp_tb(dc, 0, dc->pc);
3214 break;
3215 default:
3216 case DISAS_JUMP:
3217 case DISAS_UPDATE:
3218 gen_flush_cc_op(dc);
3219 /* indicate that the hash table must be used to find the next TB */
3220 tcg_gen_exit_tb(0);
3221 break;
3222 case DISAS_TB_JUMP:
3223 /* nothing more to generate */
3224 break;
3227 *gen_opc_ptr = INDEX_op_end;
3229 #ifdef DEBUG_DISAS
3230 if (loglevel & CPU_LOG_TB_IN_ASM) {
3231 fprintf(logfile, "----------------\n");
3232 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3233 target_disas(logfile, pc_start, dc->pc - pc_start, 0);
3234 fprintf(logfile, "\n");
3236 #endif
3237 if (search_pc) {
3238 j = gen_opc_ptr - gen_opc_buf;
3239 lj++;
3240 while (lj <= j)
3241 gen_opc_instr_start[lj++] = 0;
3242 } else {
3243 tb->size = dc->pc - pc_start;
3246 //optimize_flags();
3247 //expand_target_qops();
3248 return 0;
3251 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
3253 return gen_intermediate_code_internal(env, tb, 0);
3256 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
3258 return gen_intermediate_code_internal(env, tb, 1);
3261 void cpu_dump_state(CPUState *env, FILE *f,
3262 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3263 int flags)
3265 int i;
3266 uint16_t sr;
3267 CPU_DoubleU u;
3268 for (i = 0; i < 8; i++)
3270 u.d = env->fregs[i];
3271 cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
3272 i, env->dregs[i], i, env->aregs[i],
3273 i, u.l.upper, u.l.lower, *(double *)&u.d);
3275 cpu_fprintf (f, "PC = %08x ", env->pc);
3276 sr = env->sr;
3277 cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
3278 (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
3279 (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
3280 cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);