]>
git.proxmox.com Git - qemu.git/blob - target-m68k/translate.c
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
31 #include "m68k-qreg.h"
33 //#define DEBUG_DISPATCH 1
35 static inline void qemu_assert(int cond
, const char *msg
)
38 fprintf (stderr
, "badness: %s\n", msg
);
43 /* internal defines */
44 typedef struct DisasContext
{
50 struct TranslationBlock
*tb
;
51 int singlestep_enabled
;
54 #define DISAS_JUMP_NEXT 4
56 #if defined(CONFIG_USER_ONLY)
59 #define IS_USER(s) s->user
62 /* XXX: move that elsewhere */
63 /* ??? Fix exceptions. */
64 static void *gen_throws_exception
;
65 #define gen_last_qop NULL
67 static uint16_t *gen_opc_ptr
;
68 static uint32_t *gen_opparam_ptr
;
73 #define DEF(s, n, copy_size) INDEX_op_ ## s,
81 #if defined(CONFIG_USER_ONLY)
82 #define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
83 #define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
85 #define gen_st(s, name, addr, val) do { \
87 gen_op_st##name##_user(addr, val); \
89 gen_op_st##name##_kernel(addr, val); \
91 #define gen_ld(s, name, val, addr) do { \
93 gen_op_ld##name##_user(val, addr); \
95 gen_op_ld##name##_kernel(val, addr); \
107 #define DREG(insn, pos) (((insn >> pos) & 7) + QREG_D0)
108 #define AREG(insn, pos) (((insn >> pos) & 7) + QREG_A0)
109 #define FREG(insn, pos) (((insn >> pos) & 7) + QREG_F0)
111 typedef void (*disas_proc
)(DisasContext
*, uint16_t);
113 #ifdef DEBUG_DISPATCH
114 #define DISAS_INSN(name) \
115 static void real_disas_##name (DisasContext *s, uint16_t insn); \
116 static void disas_##name (DisasContext *s, uint16_t insn) { \
117 if (logfile) fprintf(logfile, "Dispatch " #name "\n"); \
118 real_disas_##name(s, insn); } \
119 static void real_disas_##name (DisasContext *s, uint16_t insn)
121 #define DISAS_INSN(name) \
122 static void disas_##name (DisasContext *s, uint16_t insn)
125 /* Generate a load from the specified address. Narrow values are
126 sign extended to full register width. */
127 static inline int gen_load(DisasContext
* s
, int opsize
, int addr
, int sign
)
132 tmp
= gen_new_qreg(QMODE_I32
);
134 gen_ld(s
, 8s32
, tmp
, addr
);
136 gen_ld(s
, 8u32, tmp
, addr
);
139 tmp
= gen_new_qreg(QMODE_I32
);
141 gen_ld(s
, 16s32
, tmp
, addr
);
143 gen_ld(s
, 16u32, tmp
, addr
);
146 tmp
= gen_new_qreg(QMODE_I32
);
147 gen_ld(s
, 32, tmp
, addr
);
150 tmp
= gen_new_qreg(QMODE_F32
);
151 gen_ld(s
, f32
, tmp
, addr
);
154 tmp
= gen_new_qreg(QMODE_F64
);
155 gen_ld(s
, f64
, tmp
, addr
);
158 qemu_assert(0, "bad load size");
160 gen_throws_exception
= gen_last_qop
;
164 /* Generate a store. */
165 static inline void gen_store(DisasContext
*s
, int opsize
, int addr
, int val
)
169 gen_st(s
, 8, addr
, val
);
172 gen_st(s
, 16, addr
, val
);
175 gen_st(s
, 32, addr
, val
);
178 gen_st(s
, f32
, addr
, val
);
181 gen_st(s
, f64
, addr
, val
);
184 qemu_assert(0, "bad store size");
186 gen_throws_exception
= gen_last_qop
;
189 /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
190 otherwise generate a store. */
191 static int gen_ldst(DisasContext
*s
, int opsize
, int addr
, int val
)
194 gen_store(s
, opsize
, addr
, val
);
197 return gen_load(s
, opsize
, addr
, val
!= 0);
201 /* Handle a base + index + displacement effective addresss. A base of
202 -1 means pc-relative. */
203 static int gen_lea_indexed(DisasContext
*s
, int opsize
, int base
)
212 ext
= lduw_code(s
->pc
);
214 tmp
= ((ext
>> 12) & 7) + ((ext
& 0x8000) ? QREG_A0
: QREG_D0
);
215 /* ??? Check W/L bit. */
216 scale
= (ext
>> 9) & 3;
220 add
= gen_new_qreg(QMODE_I32
);
221 gen_op_shl32(add
, tmp
, gen_im32(scale
));
223 tmp
= gen_new_qreg(QMODE_I32
);
225 gen_op_add32(tmp
, base
, gen_im32((int8_t)ext
));
226 gen_op_add32(tmp
, tmp
, add
);
228 gen_op_add32(tmp
, add
, gen_im32(offset
+ (int8_t)ext
));
233 /* Read a 32-bit immediate constant. */
234 static inline uint32_t read_im32(DisasContext
*s
)
237 im
= ((uint32_t)lduw_code(s
->pc
)) << 16;
239 im
|= lduw_code(s
->pc
);
245 /* Update the CPU env CC_OP state. */
246 static inline void gen_flush_cc_op(DisasContext
*s
)
248 if (s
->cc_op
!= CC_OP_DYNAMIC
)
249 gen_op_mov32(QREG_CC_OP
, gen_im32(s
->cc_op
));
252 /* Evaluate all the CC flags. */
253 static inline void gen_flush_flags(DisasContext
*s
)
255 if (s
->cc_op
== CC_OP_FLAGS
)
257 gen_op_flush_flags(s
->cc_op
);
258 s
->cc_op
= CC_OP_FLAGS
;
261 static inline int opsize_bytes(int opsize
)
264 case OS_BYTE
: return 1;
265 case OS_WORD
: return 2;
266 case OS_LONG
: return 4;
267 case OS_SINGLE
: return 4;
268 case OS_DOUBLE
: return 8;
270 qemu_assert(0, "bad operand size");
274 /* Assign value to a register. If the width is less than the register width
275 only the low part of the register is set. */
276 static void gen_partset_reg(int opsize
, int reg
, int val
)
281 gen_op_and32(reg
, reg
, gen_im32(0xffffff00));
282 tmp
= gen_new_qreg(QMODE_I32
);
283 gen_op_and32(tmp
, val
, gen_im32(0xff));
284 gen_op_or32(reg
, reg
, tmp
);
287 gen_op_and32(reg
, reg
, gen_im32(0xffff0000));
288 tmp
= gen_new_qreg(QMODE_I32
);
289 gen_op_and32(tmp
, val
, gen_im32(0xffff));
290 gen_op_or32(reg
, reg
, tmp
);
293 gen_op_mov32(reg
, val
);
296 gen_op_pack_32_f32(reg
, val
);
299 qemu_assert(0, "Bad operand size");
304 /* Sign or zero extend a value. */
305 static inline int gen_extend(int val
, int opsize
, int sign
)
311 tmp
= gen_new_qreg(QMODE_I32
);
313 gen_op_ext8s32(tmp
, val
);
315 gen_op_ext8u32(tmp
, val
);
318 tmp
= gen_new_qreg(QMODE_I32
);
320 gen_op_ext16s32(tmp
, val
);
322 gen_op_ext16u32(tmp
, val
);
328 tmp
= gen_new_qreg(QMODE_F32
);
329 gen_op_pack_f32_32(tmp
, val
);
332 qemu_assert(0, "Bad operand size");
337 /* Generate code for an "effective address". Does not adjust the base
338 register for autoincrememnt addressing modes. */
339 static int gen_lea(DisasContext
*s
, uint16_t insn
, int opsize
)
347 switch ((insn
>> 3) & 7) {
348 case 0: /* Data register direct. */
349 case 1: /* Address register direct. */
350 /* ??? generate bad addressing mode fault. */
351 qemu_assert(0, "invalid addressing mode");
352 case 2: /* Indirect register */
353 case 3: /* Indirect postincrement. */
356 case 4: /* Indirect predecrememnt. */
358 tmp
= gen_new_qreg(QMODE_I32
);
359 gen_op_sub32(tmp
, reg
, gen_im32(opsize_bytes(opsize
)));
361 case 5: /* Indirect displacement. */
363 tmp
= gen_new_qreg(QMODE_I32
);
364 ext
= lduw_code(s
->pc
);
366 gen_op_add32(tmp
, reg
, gen_im32((int16_t)ext
));
368 case 6: /* Indirect index + displacement. */
370 return gen_lea_indexed(s
, opsize
, reg
);
373 case 0: /* Absolute short. */
374 offset
= ldsw_code(s
->pc
);
376 return gen_im32(offset
);
377 case 1: /* Absolute long. */
378 offset
= read_im32(s
);
379 return gen_im32(offset
);
380 case 2: /* pc displacement */
381 tmp
= gen_new_qreg(QMODE_I32
);
383 offset
+= ldsw_code(s
->pc
);
385 return gen_im32(offset
);
386 case 3: /* pc index+displacement. */
387 return gen_lea_indexed(s
, opsize
, -1);
388 case 4: /* Immediate. */
390 /* ??? generate bad addressing mode fault. */
391 qemu_assert(0, "invalid addressing mode");
394 /* Should never happen. */
398 /* Helper function for gen_ea. Reuse the computed address between the
399 for read/write operands. */
400 static inline int gen_ea_once(DisasContext
*s
, uint16_t insn
, int opsize
,
405 if (addrp
&& val
> 0) {
408 tmp
= gen_lea(s
, insn
, opsize
);
412 return gen_ldst(s
, opsize
, tmp
, val
);
415 /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
416 a write otherwise it is a read (0 == sign extend, -1 == zero extend).
417 ADDRP is non-null for readwrite operands. */
418 static int gen_ea(DisasContext
*s
, uint16_t insn
, int opsize
, int val
,
426 switch ((insn
>> 3) & 7) {
427 case 0: /* Data register direct. */
430 gen_partset_reg(opsize
, reg
, val
);
433 return gen_extend(reg
, opsize
, val
);
435 case 1: /* Address register direct. */
438 gen_op_mov32(reg
, val
);
441 return gen_extend(reg
, opsize
, val
);
443 case 2: /* Indirect register */
445 return gen_ldst(s
, opsize
, reg
, val
);
446 case 3: /* Indirect postincrement. */
448 result
= gen_ldst(s
, opsize
, reg
, val
);
449 /* ??? This is not exception safe. The instruction may still
450 fault after this point. */
451 if (val
> 0 || !addrp
)
452 gen_op_add32(reg
, reg
, gen_im32(opsize_bytes(opsize
)));
454 case 4: /* Indirect predecrememnt. */
457 if (addrp
&& val
> 0) {
460 tmp
= gen_lea(s
, insn
, opsize
);
464 result
= gen_ldst(s
, opsize
, tmp
, val
);
465 /* ??? This is not exception safe. The instruction may still
466 fault after this point. */
467 if (val
> 0 || !addrp
) {
469 gen_op_mov32(reg
, tmp
);
473 case 5: /* Indirect displacement. */
474 case 6: /* Indirect index + displacement. */
475 return gen_ea_once(s
, insn
, opsize
, val
, addrp
);
478 case 0: /* Absolute short. */
479 case 1: /* Absolute long. */
480 case 2: /* pc displacement */
481 case 3: /* pc index+displacement. */
482 return gen_ea_once(s
, insn
, opsize
, val
, addrp
);
483 case 4: /* Immediate. */
484 /* Sign extend values for consistency. */
488 offset
= ldsb_code(s
->pc
+ 1);
490 offset
= ldub_code(s
->pc
+ 1);
495 offset
= ldsw_code(s
->pc
);
497 offset
= lduw_code(s
->pc
);
501 offset
= read_im32(s
);
504 qemu_assert(0, "Bad immediate operand");
506 return gen_im32(offset
);
508 qemu_assert(0, "invalid addressing mode");
511 /* Should never happen. */
515 static void gen_logic_cc(DisasContext
*s
, int val
)
517 gen_op_logic_cc(val
);
518 s
->cc_op
= CC_OP_LOGIC
;
521 static void gen_jmpcc(DisasContext
*s
, int cond
, int l1
)
532 case 2: /* HI (!C && !Z) */
533 tmp
= gen_new_qreg(QMODE_I32
);
534 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_C
| CCF_Z
));
535 gen_op_jmp_z32(tmp
, l1
);
537 case 3: /* LS (C || Z) */
538 tmp
= gen_new_qreg(QMODE_I32
);
539 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_C
| CCF_Z
));
540 gen_op_jmp_nz32(tmp
, l1
);
542 case 4: /* CC (!C) */
543 tmp
= gen_new_qreg(QMODE_I32
);
544 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_C
));
545 gen_op_jmp_z32(tmp
, l1
);
548 tmp
= gen_new_qreg(QMODE_I32
);
549 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_C
));
550 gen_op_jmp_nz32(tmp
, l1
);
552 case 6: /* NE (!Z) */
553 tmp
= gen_new_qreg(QMODE_I32
);
554 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_Z
));
555 gen_op_jmp_z32(tmp
, l1
);
558 tmp
= gen_new_qreg(QMODE_I32
);
559 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_Z
));
560 gen_op_jmp_nz32(tmp
, l1
);
562 case 8: /* VC (!V) */
563 tmp
= gen_new_qreg(QMODE_I32
);
564 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_V
));
565 gen_op_jmp_z32(tmp
, l1
);
568 tmp
= gen_new_qreg(QMODE_I32
);
569 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_V
));
570 gen_op_jmp_nz32(tmp
, l1
);
572 case 10: /* PL (!N) */
573 tmp
= gen_new_qreg(QMODE_I32
);
574 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_N
));
575 gen_op_jmp_z32(tmp
, l1
);
577 case 11: /* MI (N) */
578 tmp
= gen_new_qreg(QMODE_I32
);
579 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_N
));
580 gen_op_jmp_nz32(tmp
, l1
);
582 case 12: /* GE (!(N ^ V)) */
583 tmp
= gen_new_qreg(QMODE_I32
);
584 gen_op_shr32(tmp
, QREG_CC_DEST
, gen_im32(2));
585 gen_op_xor32(tmp
, tmp
, QREG_CC_DEST
);
586 gen_op_and32(tmp
, tmp
, gen_im32(CCF_V
));
587 gen_op_jmp_z32(tmp
, l1
);
589 case 13: /* LT (N ^ V) */
590 tmp
= gen_new_qreg(QMODE_I32
);
591 gen_op_shr32(tmp
, QREG_CC_DEST
, gen_im32(2));
592 gen_op_xor32(tmp
, tmp
, QREG_CC_DEST
);
593 gen_op_and32(tmp
, tmp
, gen_im32(CCF_V
));
594 gen_op_jmp_nz32(tmp
, l1
);
596 case 14: /* GT (!(Z || (N ^ V))) */
599 l2
= gen_new_label();
600 tmp
= gen_new_qreg(QMODE_I32
);
601 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_Z
));
602 gen_op_jmp_nz32(tmp
, l2
);
603 tmp
= gen_new_qreg(QMODE_I32
);
604 gen_op_shr32(tmp
, QREG_CC_DEST
, gen_im32(2));
605 gen_op_xor32(tmp
, tmp
, QREG_CC_DEST
);
606 gen_op_and32(tmp
, tmp
, gen_im32(CCF_V
));
607 gen_op_jmp_nz32(tmp
, l2
);
612 case 15: /* LE (Z || (N ^ V)) */
613 tmp
= gen_new_qreg(QMODE_I32
);
614 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_Z
));
615 gen_op_jmp_nz32(tmp
, l1
);
616 tmp
= gen_new_qreg(QMODE_I32
);
617 gen_op_shr32(tmp
, QREG_CC_DEST
, gen_im32(2));
618 gen_op_xor32(tmp
, tmp
, QREG_CC_DEST
);
619 gen_op_and32(tmp
, tmp
, gen_im32(CCF_V
));
620 gen_op_jmp_nz32(tmp
, l1
);
623 /* Should ever happen. */
634 l1
= gen_new_label();
635 cond
= (insn
>> 8) & 0xf;
637 gen_op_and32(reg
, reg
, gen_im32(0xffffff00));
638 gen_jmpcc(s
, cond
^ 1, l1
);
639 gen_op_or32(reg
, reg
, gen_im32(0xff));
643 /* Force a TB lookup after an instruction that changes the CPU state. */
644 static void gen_lookup_tb(DisasContext
*s
)
647 gen_op_mov32(QREG_PC
, gen_im32(s
->pc
));
648 s
->is_jmp
= DISAS_UPDATE
;
651 /* Generate a jump to to the address in qreg DEST. */
652 static void gen_jmp(DisasContext
*s
, int dest
)
655 gen_op_mov32(QREG_PC
, dest
);
656 s
->is_jmp
= DISAS_JUMP
;
659 static void gen_exception(DisasContext
*s
, uint32_t where
, int nr
)
662 gen_jmp(s
, gen_im32(where
));
663 gen_op_raise_exception(nr
);
666 /* Generate a jump to an immediate address. */
667 static void gen_jmp_tb(DisasContext
*s
, int n
, uint32_t dest
)
669 TranslationBlock
*tb
;
672 if (__builtin_expect (s
->singlestep_enabled
, 0)) {
673 gen_exception(s
, dest
, EXCP_DEBUG
);
674 } else if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
) ||
675 (s
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
676 gen_op_goto_tb(0, n
, (long)tb
);
677 gen_op_mov32(QREG_PC
, gen_im32(dest
));
678 gen_op_mov32(QREG_T0
, gen_im32((long)tb
+ n
));
681 gen_jmp(s
, gen_im32(dest
));
682 gen_op_mov32(QREG_T0
, gen_im32(0));
685 s
->is_jmp
= DISAS_TB_JUMP
;
688 DISAS_INSN(undef_mac
)
690 gen_exception(s
, s
->pc
- 2, EXCP_LINEA
);
693 DISAS_INSN(undef_fpu
)
695 gen_exception(s
, s
->pc
- 2, EXCP_LINEF
);
700 gen_exception(s
, s
->pc
- 2, EXCP_UNSUPPORTED
);
701 cpu_abort(cpu_single_env
, "Illegal instruction: %04x @ %08x",
712 sign
= (insn
& 0x100) != 0;
714 tmp
= gen_new_qreg(QMODE_I32
);
716 gen_op_ext16s32(tmp
, reg
);
718 gen_op_ext16u32(tmp
, reg
);
719 src
= gen_ea(s
, insn
, OS_WORD
, sign
? -1 : 0, NULL
);
720 gen_op_mul32(tmp
, tmp
, src
);
721 gen_op_mov32(reg
, tmp
);
722 /* Unlike m68k, coldfire always clears the overflow bit. */
723 gen_logic_cc(s
, tmp
);
733 sign
= (insn
& 0x100) != 0;
736 gen_op_ext16s32(QREG_DIV1
, reg
);
738 gen_op_ext16u32(QREG_DIV1
, reg
);
740 src
= gen_ea(s
, insn
, OS_WORD
, sign
? -1 : 0, NULL
);
741 gen_op_mov32(QREG_DIV2
, src
);
748 tmp
= gen_new_qreg(QMODE_I32
);
749 src
= gen_new_qreg(QMODE_I32
);
750 gen_op_ext16u32(tmp
, QREG_DIV1
);
751 gen_op_shl32(src
, QREG_DIV2
, gen_im32(16));
752 gen_op_or32(reg
, tmp
, src
);
754 s
->cc_op
= CC_OP_FLAGS
;
764 ext
= lduw_code(s
->pc
);
767 gen_exception(s
, s
->pc
- 4, EXCP_UNSUPPORTED
);
772 gen_op_mov32(QREG_DIV1
, num
);
773 den
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
774 gen_op_mov32(QREG_DIV2
, den
);
782 gen_op_mov32 (reg
, QREG_DIV1
);
785 gen_op_mov32 (reg
, QREG_DIV2
);
788 s
->cc_op
= CC_OP_FLAGS
;
800 add
= (insn
& 0x4000) != 0;
802 dest
= gen_new_qreg(QMODE_I32
);
804 tmp
= gen_ea(s
, insn
, OS_LONG
, 0, &addr
);
808 src
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
811 gen_op_add32(dest
, tmp
, src
);
812 gen_op_update_xflag_lt(dest
, src
);
813 s
->cc_op
= CC_OP_ADD
;
815 gen_op_update_xflag_lt(tmp
, src
);
816 gen_op_sub32(dest
, tmp
, src
);
817 s
->cc_op
= CC_OP_SUB
;
819 gen_op_update_cc_add(dest
, src
);
821 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
823 gen_op_mov32(reg
, dest
);
828 /* Reverse the order of the bits in REG. */
836 val
= gen_new_qreg(QMODE_I32
);
837 tmp1
= gen_new_qreg(QMODE_I32
);
838 tmp2
= gen_new_qreg(QMODE_I32
);
840 gen_op_mov32(val
, reg
);
841 /* Reverse bits within each nibble. */
842 gen_op_shl32(tmp1
, val
, gen_im32(3));
843 gen_op_and32(tmp1
, tmp1
, gen_im32(0x88888888));
844 gen_op_shl32(tmp2
, val
, gen_im32(1));
845 gen_op_and32(tmp2
, tmp2
, gen_im32(0x44444444));
846 gen_op_or32(tmp1
, tmp1
, tmp2
);
847 gen_op_shr32(tmp2
, val
, gen_im32(1));
848 gen_op_and32(tmp2
, tmp2
, gen_im32(0x22222222));
849 gen_op_or32(tmp1
, tmp1
, tmp2
);
850 gen_op_shr32(tmp2
, val
, gen_im32(3));
851 gen_op_and32(tmp2
, tmp2
, gen_im32(0x11111111));
852 gen_op_or32(tmp1
, tmp1
, tmp2
);
853 /* Reverse nibbles withing bytes. */
854 gen_op_shl32(val
, tmp1
, gen_im32(4));
855 gen_op_and32(val
, val
, gen_im32(0xf0f0f0f0));
856 gen_op_shr32(tmp2
, tmp1
, gen_im32(4));
857 gen_op_and32(tmp2
, tmp2
, gen_im32(0x0f0f0f0f));
858 gen_op_or32(val
, val
, tmp2
);
860 gen_op_bswap32(reg
, val
);
861 gen_op_mov32(reg
, val
);
864 DISAS_INSN(bitop_reg
)
874 if ((insn
& 0x38) != 0)
878 op
= (insn
>> 6) & 3;
879 src1
= gen_ea(s
, insn
, opsize
, 0, op
? &addr
: NULL
);
880 src2
= DREG(insn
, 9);
881 dest
= gen_new_qreg(QMODE_I32
);
884 tmp
= gen_new_qreg(QMODE_I32
);
885 if (opsize
== OS_BYTE
)
886 gen_op_and32(tmp
, src2
, gen_im32(7));
888 gen_op_and32(tmp
, src2
, gen_im32(31));
890 tmp
= gen_new_qreg(QMODE_I32
);
891 gen_op_shl32(tmp
, gen_im32(1), src2
);
893 gen_op_btest(src1
, tmp
);
896 gen_op_xor32(dest
, src1
, tmp
);
899 gen_op_not32(tmp
, tmp
);
900 gen_op_and32(dest
, src1
, tmp
);
903 gen_op_or32(dest
, src1
, tmp
);
909 gen_ea(s
, insn
, opsize
, dest
, &addr
);
919 tmp
= gen_new_qreg(QMODE_I32
);
921 gen_op_and32(tmp
, QREG_CC_DEST
, gen_im32(CCF_V
));
922 l1
= gen_new_label();
923 gen_op_jmp_z32(tmp
, l1
);
924 tmp
= gen_new_qreg(QMODE_I32
);
925 gen_op_shr32(tmp
, reg
, gen_im32(31));
926 gen_op_xor32(tmp
, tmp
, gen_im32(0x80000000));
927 gen_op_mov32(reg
, tmp
);
929 gen_logic_cc(s
, tmp
);
932 static void gen_push(DisasContext
*s
, int val
)
936 tmp
= gen_new_qreg(QMODE_I32
);
937 gen_op_sub32(tmp
, QREG_SP
, gen_im32(4));
938 gen_store(s
, OS_LONG
, tmp
, val
);
939 gen_op_mov32(QREG_SP
, tmp
);
951 mask
= lduw_code(s
->pc
);
953 tmp
= gen_lea(s
, insn
, OS_LONG
);
954 addr
= gen_new_qreg(QMODE_I32
);
955 gen_op_mov32(addr
, tmp
);
956 is_load
= ((insn
& 0x0400) != 0);
957 for (i
= 0; i
< 16; i
++, mask
>>= 1) {
964 tmp
= gen_load(s
, OS_LONG
, addr
, 0);
965 gen_op_mov32(reg
, tmp
);
967 gen_store(s
, OS_LONG
, addr
, reg
);
970 gen_op_add32(addr
, addr
, gen_im32(4));
986 if ((insn
& 0x38) != 0)
990 op
= (insn
>> 6) & 3;
992 bitnum
= lduw_code(s
->pc
);
994 if (bitnum
& 0xff00) {
995 disas_undef(s
, insn
);
999 src1
= gen_ea(s
, insn
, opsize
, 0, op
? &addr
: NULL
);
1002 tmp
= gen_new_qreg(QMODE_I32
);
1003 if (opsize
== OS_BYTE
)
1009 gen_op_btest(src1
, gen_im32(mask
));
1011 dest
= gen_new_qreg(QMODE_I32
);
1017 gen_op_xor32(dest
, src1
, gen_im32(mask
));
1020 gen_op_and32(dest
, src1
, gen_im32(~mask
));
1023 gen_op_or32(dest
, src1
, gen_im32(mask
));
1029 gen_ea(s
, insn
, opsize
, dest
, &addr
);
1032 DISAS_INSN(arith_im
)
1040 op
= (insn
>> 9) & 7;
1041 src1
= gen_ea(s
, insn
, OS_LONG
, 0, (op
== 6) ? NULL
: &addr
);
1042 src2
= gen_im32(read_im32(s
));
1043 dest
= gen_new_qreg(QMODE_I32
);
1046 gen_op_or32(dest
, src1
, src2
);
1047 gen_logic_cc(s
, dest
);
1050 gen_op_and32(dest
, src1
, src2
);
1051 gen_logic_cc(s
, dest
);
1054 gen_op_mov32(dest
, src1
);
1055 gen_op_update_xflag_lt(dest
, src2
);
1056 gen_op_sub32(dest
, dest
, src2
);
1057 gen_op_update_cc_add(dest
, src2
);
1058 s
->cc_op
= CC_OP_SUB
;
1061 gen_op_mov32(dest
, src1
);
1062 gen_op_add32(dest
, dest
, src2
);
1063 gen_op_update_cc_add(dest
, src2
);
1064 gen_op_update_xflag_lt(dest
, src2
);
1065 s
->cc_op
= CC_OP_ADD
;
1068 gen_op_xor32(dest
, src1
, src2
);
1069 gen_logic_cc(s
, dest
);
1072 gen_op_mov32(dest
, src1
);
1073 gen_op_sub32(dest
, dest
, src2
);
1074 gen_op_update_cc_add(dest
, src2
);
1075 s
->cc_op
= CC_OP_SUB
;
1081 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
1089 reg
= DREG(insn
, 0);
1090 gen_op_bswap32(reg
, reg
);
1100 switch (insn
>> 12) {
1101 case 1: /* move.b */
1104 case 2: /* move.l */
1107 case 3: /* move.w */
1113 src
= gen_ea(s
, insn
, opsize
, -1, NULL
);
1114 op
= (insn
>> 6) & 7;
1117 /* The value will already have been sign extended. */
1118 dest
= AREG(insn
, 9);
1119 gen_op_mov32(dest
, src
);
1123 dest_ea
= ((insn
>> 9) & 7) | (op
<< 3);
1124 gen_ea(s
, dest_ea
, opsize
, src
, NULL
);
1125 /* This will be correct because loads sign extend. */
1126 gen_logic_cc(s
, src
);
1137 reg
= DREG(insn
, 0);
1138 dest
= gen_new_qreg(QMODE_I32
);
1139 gen_op_mov32 (dest
, gen_im32(0));
1140 gen_op_subx_cc(dest
, reg
);
1142 tmp
= gen_new_qreg(QMODE_I32
);
1143 gen_op_mov32 (tmp
, QREG_CC_DEST
);
1144 gen_op_update_cc_add(dest
, reg
);
1145 gen_op_mov32(reg
, dest
);
1146 s
->cc_op
= CC_OP_DYNAMIC
;
1148 gen_op_or32(tmp
, tmp
, gen_im32(~CCF_Z
));
1149 gen_op_and32(QREG_CC_DEST
, QREG_CC_DEST
, tmp
);
1150 s
->cc_op
= CC_OP_FLAGS
;
1158 reg
= AREG(insn
, 9);
1159 tmp
= gen_lea(s
, insn
, OS_LONG
);
1160 gen_op_mov32(reg
, tmp
);
1167 switch ((insn
>> 6) & 3) {
1180 gen_ea (s
, insn
, opsize
, gen_im32(0), NULL
);
1181 gen_logic_cc(s
, gen_im32(0));
1184 static int gen_get_ccr(DisasContext
*s
)
1189 dest
= gen_new_qreg(QMODE_I32
);
1190 gen_op_get_xflag(dest
);
1191 gen_op_shl32(dest
, dest
, gen_im32(4));
1192 gen_op_or32(dest
, dest
, QREG_CC_DEST
);
1196 DISAS_INSN(move_from_ccr
)
1201 ccr
= gen_get_ccr(s
);
1202 reg
= DREG(insn
, 0);
1203 gen_partset_reg(OS_WORD
, reg
, ccr
);
1211 reg
= DREG(insn
, 0);
1212 src1
= gen_new_qreg(QMODE_I32
);
1213 gen_op_mov32(src1
, reg
);
1214 gen_op_neg32(reg
, src1
);
1215 s
->cc_op
= CC_OP_SUB
;
1216 gen_op_update_cc_add(reg
, src1
);
1217 gen_op_update_xflag_lt(gen_im32(0), src1
);
1218 s
->cc_op
= CC_OP_SUB
;
1221 static void gen_set_sr_im(DisasContext
*s
, uint16_t val
, int ccr_only
)
1223 gen_op_logic_cc(gen_im32(val
& 0xf));
1224 gen_op_update_xflag_tst(gen_im32((val
& 0x10) >> 4));
1226 gen_op_mov32(QREG_SR
, gen_im32(val
& 0xff00));
1230 static void gen_set_sr(DisasContext
*s
, uint16_t insn
, int ccr_only
)
1235 s
->cc_op
= CC_OP_FLAGS
;
1236 if ((insn
& 0x38) == 0)
1238 src1
= gen_new_qreg(QMODE_I32
);
1239 reg
= DREG(insn
, 0);
1240 gen_op_and32(src1
, reg
, gen_im32(0xf));
1241 gen_op_logic_cc(src1
);
1242 gen_op_shr32(src1
, reg
, gen_im32(4));
1243 gen_op_and32(src1
, src1
, gen_im32(1));
1244 gen_op_update_xflag_tst(src1
);
1246 gen_op_and32(QREG_SR
, reg
, gen_im32(0xff00));
1249 else if ((insn
& 0x3f) == 0x3c)
1252 val
= lduw_code(s
->pc
);
1254 gen_set_sr_im(s
, val
, ccr_only
);
1257 disas_undef(s
, insn
);
1260 DISAS_INSN(move_to_ccr
)
1262 gen_set_sr(s
, insn
, 1);
1269 reg
= DREG(insn
, 0);
1270 gen_op_not32(reg
, reg
);
1271 gen_logic_cc(s
, reg
);
1281 dest
= gen_new_qreg(QMODE_I32
);
1282 src1
= gen_new_qreg(QMODE_I32
);
1283 src2
= gen_new_qreg(QMODE_I32
);
1284 reg
= DREG(insn
, 0);
1285 gen_op_shl32(src1
, reg
, gen_im32(16));
1286 gen_op_shr32(src2
, reg
, gen_im32(16));
1287 gen_op_or32(dest
, src1
, src2
);
1288 gen_op_mov32(reg
, dest
);
1289 gen_logic_cc(s
, dest
);
1296 tmp
= gen_lea(s
, insn
, OS_LONG
);
1306 reg
= DREG(insn
, 0);
1307 op
= (insn
>> 6) & 7;
1308 tmp
= gen_new_qreg(QMODE_I32
);
1310 gen_op_ext16s32(tmp
, reg
);
1312 gen_op_ext8s32(tmp
, reg
);
1314 gen_partset_reg(OS_WORD
, reg
, tmp
);
1316 gen_op_mov32(reg
, tmp
);
1317 gen_logic_cc(s
, tmp
);
1325 switch ((insn
>> 6) & 3) {
1338 tmp
= gen_ea(s
, insn
, opsize
, -1, NULL
);
1339 gen_logic_cc(s
, tmp
);
1344 /* Implemented as a NOP. */
1349 gen_exception(s
, s
->pc
- 2, EXCP_ILLEGAL
);
1352 /* ??? This should be atomic. */
1359 dest
= gen_new_qreg(QMODE_I32
);
1360 src1
= gen_ea(s
, insn
, OS_BYTE
, -1, &addr
);
1361 gen_logic_cc(s
, src1
);
1362 gen_op_or32(dest
, src1
, gen_im32(0x80));
1363 gen_ea(s
, insn
, OS_BYTE
, dest
, &addr
);
1373 /* The upper 32 bits of the product are discarded, so
1374 muls.l and mulu.l are functionally equivalent. */
1375 ext
= lduw_code(s
->pc
);
1378 gen_exception(s
, s
->pc
- 4, EXCP_UNSUPPORTED
);
1381 reg
= DREG(ext
, 12);
1382 src1
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
1383 dest
= gen_new_qreg(QMODE_I32
);
1384 gen_op_mul32(dest
, src1
, reg
);
1385 gen_op_mov32(reg
, dest
);
1386 /* Unlike m68k, coldfire always clears the overflow bit. */
1387 gen_logic_cc(s
, dest
);
1396 offset
= ldsw_code(s
->pc
);
1398 reg
= AREG(insn
, 0);
1399 tmp
= gen_new_qreg(QMODE_I32
);
1400 gen_op_sub32(tmp
, QREG_SP
, gen_im32(4));
1401 gen_store(s
, OS_LONG
, tmp
, reg
);
1403 gen_op_mov32(reg
, tmp
);
1404 gen_op_add32(QREG_SP
, tmp
, gen_im32(offset
));
1413 src
= gen_new_qreg(QMODE_I32
);
1414 reg
= AREG(insn
, 0);
1415 gen_op_mov32(src
, reg
);
1416 tmp
= gen_load(s
, OS_LONG
, src
, 0);
1417 gen_op_mov32(reg
, tmp
);
1418 gen_op_add32(QREG_SP
, src
, gen_im32(4));
1429 tmp
= gen_load(s
, OS_LONG
, QREG_SP
, 0);
1430 gen_op_add32(QREG_SP
, QREG_SP
, gen_im32(4));
1438 /* Load the target address first to ensure correct exception
1440 tmp
= gen_lea(s
, insn
, OS_LONG
);
1441 if ((insn
& 0x40) == 0) {
1443 gen_push(s
, gen_im32(s
->pc
));
1456 src1
= gen_ea(s
, insn
, OS_LONG
, 0, &addr
);
1457 val
= (insn
>> 9) & 7;
1460 src2
= gen_im32(val
);
1461 dest
= gen_new_qreg(QMODE_I32
);
1462 gen_op_mov32(dest
, src1
);
1463 if ((insn
& 0x38) == 0x08) {
1464 /* Don't update condition codes if the destination is an
1465 address register. */
1466 if (insn
& 0x0100) {
1467 gen_op_sub32(dest
, dest
, src2
);
1469 gen_op_add32(dest
, dest
, src2
);
1472 if (insn
& 0x0100) {
1473 gen_op_update_xflag_lt(dest
, src2
);
1474 gen_op_sub32(dest
, dest
, src2
);
1475 s
->cc_op
= CC_OP_SUB
;
1477 gen_op_add32(dest
, dest
, src2
);
1478 gen_op_update_xflag_lt(dest
, src2
);
1479 s
->cc_op
= CC_OP_ADD
;
1481 gen_op_update_cc_add(dest
, src2
);
1483 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
1489 case 2: /* One extension word. */
1492 case 3: /* Two extension words. */
1495 case 4: /* No extension words. */
1498 disas_undef(s
, insn
);
1510 op
= (insn
>> 8) & 0xf;
1511 offset
= (int8_t)insn
;
1513 offset
= ldsw_code(s
->pc
);
1515 } else if (offset
== -1) {
1516 offset
= read_im32(s
);
1520 gen_push(s
, gen_im32(s
->pc
));
1525 l1
= gen_new_label();
1526 gen_jmpcc(s
, ((insn
>> 8) & 0xf) ^ 1, l1
);
1527 gen_jmp_tb(s
, 1, base
+ offset
);
1529 gen_jmp_tb(s
, 0, s
->pc
);
1531 /* Unconditional branch. */
1532 gen_jmp_tb(s
, 0, base
+ offset
);
1540 tmp
= gen_im32((int8_t)insn
);
1541 gen_op_mov32(DREG(insn
, 9), tmp
);
1542 gen_logic_cc(s
, tmp
);
1555 src
= gen_ea(s
, insn
, opsize
, (insn
& 0x80) ? 0 : -1, NULL
);
1556 reg
= DREG(insn
, 9);
1557 gen_op_mov32(reg
, src
);
1558 gen_logic_cc(s
, src
);
1568 reg
= DREG(insn
, 9);
1569 dest
= gen_new_qreg(QMODE_I32
);
1571 src
= gen_ea(s
, insn
, OS_LONG
, 0, &addr
);
1572 gen_op_or32(dest
, src
, reg
);
1573 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
1575 src
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
1576 gen_op_or32(dest
, src
, reg
);
1577 gen_op_mov32(reg
, dest
);
1579 gen_logic_cc(s
, dest
);
1587 src
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
1588 reg
= AREG(insn
, 9);
1589 gen_op_sub32(reg
, reg
, src
);
1600 reg
= DREG(insn
, 9);
1601 src
= DREG(insn
, 0);
1602 dest
= gen_new_qreg(QMODE_I32
);
1603 gen_op_mov32 (dest
, reg
);
1604 gen_op_subx_cc(dest
, src
);
1606 tmp
= gen_new_qreg(QMODE_I32
);
1607 gen_op_mov32 (tmp
, QREG_CC_DEST
);
1608 gen_op_update_cc_add(dest
, src
);
1609 gen_op_mov32(reg
, dest
);
1610 s
->cc_op
= CC_OP_DYNAMIC
;
1612 gen_op_or32(tmp
, tmp
, gen_im32(~CCF_Z
));
1613 gen_op_and32(QREG_CC_DEST
, QREG_CC_DEST
, tmp
);
1614 s
->cc_op
= CC_OP_FLAGS
;
1622 val
= (insn
>> 9) & 7;
1625 src
= gen_im32(val
);
1626 gen_logic_cc(s
, src
);
1627 gen_ea(s
, insn
, OS_LONG
, src
, NULL
);
1638 op
= (insn
>> 6) & 3;
1642 s
->cc_op
= CC_OP_CMPB
;
1646 s
->cc_op
= CC_OP_CMPW
;
1650 s
->cc_op
= CC_OP_SUB
;
1655 src
= gen_ea(s
, insn
, opsize
, -1, NULL
);
1656 reg
= DREG(insn
, 9);
1657 dest
= gen_new_qreg(QMODE_I32
);
1658 gen_op_sub32(dest
, reg
, src
);
1659 gen_op_update_cc_add(dest
, src
);
1674 src
= gen_ea(s
, insn
, opsize
, -1, NULL
);
1675 reg
= AREG(insn
, 9);
1676 dest
= gen_new_qreg(QMODE_I32
);
1677 gen_op_sub32(dest
, reg
, src
);
1678 gen_op_update_cc_add(dest
, src
);
1679 s
->cc_op
= CC_OP_SUB
;
1689 src
= gen_ea(s
, insn
, OS_LONG
, 0, &addr
);
1690 reg
= DREG(insn
, 9);
1691 dest
= gen_new_qreg(QMODE_I32
);
1692 gen_op_xor32(dest
, src
, reg
);
1693 gen_logic_cc(s
, dest
);
1694 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
1704 reg
= DREG(insn
, 9);
1705 dest
= gen_new_qreg(QMODE_I32
);
1707 src
= gen_ea(s
, insn
, OS_LONG
, 0, &addr
);
1708 gen_op_and32(dest
, src
, reg
);
1709 gen_ea(s
, insn
, OS_LONG
, dest
, &addr
);
1711 src
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
1712 gen_op_and32(dest
, src
, reg
);
1713 gen_op_mov32(reg
, dest
);
1715 gen_logic_cc(s
, dest
);
1723 src
= gen_ea(s
, insn
, OS_LONG
, 0, NULL
);
1724 reg
= AREG(insn
, 9);
1725 gen_op_add32(reg
, reg
, src
);
1736 reg
= DREG(insn
, 9);
1737 src
= DREG(insn
, 0);
1738 dest
= gen_new_qreg(QMODE_I32
);
1739 gen_op_mov32 (dest
, reg
);
1740 gen_op_addx_cc(dest
, src
);
1742 tmp
= gen_new_qreg(QMODE_I32
);
1743 gen_op_mov32 (tmp
, QREG_CC_DEST
);
1744 gen_op_update_cc_add(dest
, src
);
1745 gen_op_mov32(reg
, dest
);
1746 s
->cc_op
= CC_OP_DYNAMIC
;
1748 gen_op_or32(tmp
, tmp
, gen_im32(~CCF_Z
));
1749 gen_op_and32(QREG_CC_DEST
, QREG_CC_DEST
, tmp
);
1750 s
->cc_op
= CC_OP_FLAGS
;
1753 DISAS_INSN(shift_im
)
1758 reg
= DREG(insn
, 0);
1759 tmp
= (insn
>> 9) & 7;
1763 gen_op_shl_im_cc(reg
, tmp
);
1764 s
->cc_op
= CC_OP_SHL
;
1767 gen_op_shr_im_cc(reg
, tmp
);
1768 s
->cc_op
= CC_OP_SHR
;
1770 gen_op_sar_im_cc(reg
, tmp
);
1771 s
->cc_op
= CC_OP_SAR
;
1776 DISAS_INSN(shift_reg
)
1782 reg
= DREG(insn
, 0);
1783 src
= DREG(insn
, 9);
1784 tmp
= gen_new_qreg(QMODE_I32
);
1785 gen_op_and32(tmp
, src
, gen_im32(63));
1787 gen_op_shl_cc(reg
, tmp
);
1788 s
->cc_op
= CC_OP_SHL
;
1791 gen_op_shr_cc(reg
, tmp
);
1792 s
->cc_op
= CC_OP_SHR
;
1794 gen_op_sar_cc(reg
, tmp
);
1795 s
->cc_op
= CC_OP_SAR
;
1802 cpu_abort(NULL
, "Unimplemented insn: ff1");
1805 static int gen_get_sr(DisasContext
*s
)
1810 ccr
= gen_get_ccr(s
);
1811 sr
= gen_new_qreg(QMODE_I32
);
1812 gen_op_and32(sr
, QREG_SR
, gen_im32(0xffe0));
1813 gen_op_or32(sr
, sr
, ccr
);
1823 ext
= lduw_code(s
->pc
);
1825 if (ext
!= 0x46FC) {
1826 gen_exception(s
, addr
, EXCP_UNSUPPORTED
);
1829 ext
= lduw_code(s
->pc
);
1831 if (IS_USER(s
) || (ext
& SR_S
) == 0) {
1832 gen_exception(s
, addr
, EXCP_PRIVILEGE
);
1835 gen_push(s
, gen_get_sr(s
));
1836 gen_set_sr_im(s
, ext
, 0);
1839 DISAS_INSN(move_from_sr
)
1845 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1849 reg
= DREG(insn
, 0);
1850 gen_partset_reg(OS_WORD
, reg
, sr
);
1853 DISAS_INSN(move_to_sr
)
1856 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1859 gen_set_sr(s
, insn
, 0);
1863 DISAS_INSN(move_from_usp
)
1866 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1869 /* TODO: Implement USP. */
1870 gen_exception(s
, s
->pc
- 2, EXCP_ILLEGAL
);
1873 DISAS_INSN(move_to_usp
)
1876 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1879 /* TODO: Implement USP. */
1880 gen_exception(s
, s
->pc
- 2, EXCP_ILLEGAL
);
1885 gen_jmp(s
, gen_im32(s
->pc
));
1894 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1898 ext
= lduw_code(s
->pc
);
1901 gen_set_sr_im(s
, ext
, 0);
1902 gen_jmp(s
, gen_im32(s
->pc
));
1909 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1912 gen_exception(s
, s
->pc
- 2, EXCP_RTE
);
1921 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1925 ext
= lduw_code(s
->pc
);
1929 reg
= AREG(ext
, 12);
1931 reg
= DREG(ext
, 12);
1933 gen_op_movec(gen_im32(ext
& 0xfff), reg
);
1940 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1943 /* ICache fetch. Implement as no-op. */
1949 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1952 /* Cache push/invalidate. Implement as no-op. */
1957 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1963 gen_exception(s
, s
->pc
- 2, EXCP_PRIVILEGE
);
1966 /* TODO: Implement wdebug. */
1967 qemu_assert(0, "WDEBUG not implemented");
1972 gen_exception(s
, s
->pc
- 2, EXCP_TRAP0
+ (insn
& 0xf));
1975 /* ??? FP exceptions are not implemented. Most exceptions are deferred until
1976 immediately before the next FP instruction is executed. */
1987 ext
= lduw_code(s
->pc
);
1989 opmode
= ext
& 0x7f;
1990 switch ((ext
>> 13) & 7) {
1995 case 3: /* fmove out */
1998 /* ??? TODO: Proper behavior on overflow. */
1999 switch ((ext
>> 10) & 7) {
2002 res
= gen_new_qreg(QMODE_I32
);
2003 gen_op_f64_to_i32(res
, src
);
2007 res
= gen_new_qreg(QMODE_F32
);
2008 gen_op_f64_to_f32(res
, src
);
2012 res
= gen_new_qreg(QMODE_I32
);
2013 gen_op_f64_to_i32(res
, src
);
2021 res
= gen_new_qreg(QMODE_I32
);
2022 gen_op_f64_to_i32(res
, src
);
2027 gen_ea(s
, insn
, opsize
, res
, NULL
);
2029 case 4: /* fmove to control register. */
2030 switch ((ext
>> 10) & 7) {
2032 /* Not implemented. Ignore writes. */
2037 cpu_abort(NULL
, "Unimplemented: fmove to control %d",
2041 case 5: /* fmove from control register. */
2042 switch ((ext
>> 10) & 7) {
2044 /* Not implemented. Always return zero. */
2050 cpu_abort(NULL
, "Unimplemented: fmove from control %d",
2054 gen_ea(s
, insn
, OS_LONG
, res
, NULL
);
2056 case 6: /* fmovem */
2061 if ((ext
& 0x1f00) != 0x1000 || (ext
& 0xff) == 0)
2063 src
= gen_lea(s
, insn
, OS_LONG
);
2064 addr
= gen_new_qreg(QMODE_I32
);
2065 gen_op_mov32(addr
, src
);
2070 if (ext
& (1 << 13)) {
2072 gen_st(s
, f64
, addr
, dest
);
2075 gen_ld(s
, f64
, dest
, addr
);
2077 if (ext
& (mask
- 1))
2078 gen_op_add32(addr
, addr
, gen_im32(8));
2086 if (ext
& (1 << 14)) {
2089 /* Source effective address. */
2090 switch ((ext
>> 10) & 7) {
2091 case 0: opsize
= OS_LONG
; break;
2092 case 1: opsize
= OS_SINGLE
; break;
2093 case 4: opsize
= OS_WORD
; break;
2094 case 5: opsize
= OS_DOUBLE
; break;
2095 case 6: opsize
= OS_BYTE
; break;
2099 tmp
= gen_ea(s
, insn
, opsize
, -1, NULL
);
2100 if (opsize
== OS_DOUBLE
) {
2103 src
= gen_new_qreg(QMODE_F64
);
2108 gen_op_i32_to_f64(src
, tmp
);
2111 gen_op_f32_to_f64(src
, tmp
);
2116 /* Source register. */
2117 src
= FREG(ext
, 10);
2119 dest
= FREG(ext
, 7);
2120 res
= gen_new_qreg(QMODE_F64
);
2122 gen_op_movf64(res
, dest
);
2125 case 0: case 0x40: case 0x44: /* fmove */
2126 gen_op_movf64(res
, src
);
2129 gen_op_iround_f64(res
, src
);
2132 case 3: /* fintrz */
2133 gen_op_itrunc_f64(res
, src
);
2136 case 4: case 0x41: case 0x45: /* fsqrt */
2137 gen_op_sqrtf64(res
, src
);
2139 case 0x18: case 0x58: case 0x5c: /* fabs */
2140 gen_op_absf64(res
, src
);
2142 case 0x1a: case 0x5a: case 0x5e: /* fneg */
2143 gen_op_chsf64(res
, src
);
2145 case 0x20: case 0x60: case 0x64: /* fdiv */
2146 gen_op_divf64(res
, res
, src
);
2148 case 0x22: case 0x62: case 0x66: /* fadd */
2149 gen_op_addf64(res
, res
, src
);
2151 case 0x23: case 0x63: case 0x67: /* fmul */
2152 gen_op_mulf64(res
, res
, src
);
2154 case 0x28: case 0x68: case 0x6c: /* fsub */
2155 gen_op_subf64(res
, res
, src
);
2157 case 0x38: /* fcmp */
2158 gen_op_sub_cmpf64(res
, res
, src
);
2162 case 0x3a: /* ftst */
2163 gen_op_movf64(res
, src
);
2171 if (opmode
& 0x40) {
2172 if ((opmode
& 0x4) != 0)
2174 } else if ((s
->fpcr
& M68K_FPCR_PREC
) == 0) {
2181 tmp
= gen_new_qreg(QMODE_F32
);
2182 gen_op_f64_to_f32(tmp
, res
);
2183 gen_op_f32_to_f64(res
, tmp
);
2185 gen_op_fp_result(res
);
2187 gen_op_movf64(dest
, res
);
2192 disas_undef_fpu(s
, insn
);
2204 offset
= ldsw_code(s
->pc
);
2206 if (insn
& (1 << 6)) {
2207 offset
= (offset
<< 16) | lduw_code(s
->pc
);
2211 l1
= gen_new_label();
2212 /* TODO: Raise BSUN exception. */
2213 flag
= gen_new_qreg(QMODE_I32
);
2214 zero
= gen_new_qreg(QMODE_F64
);
2215 gen_op_zerof64(zero
);
2216 gen_op_compare_quietf64(flag
, QREG_FP_RESULT
, zero
);
2217 /* Jump to l1 if condition is true. */
2218 switch (insn
& 0xf) {
2221 case 1: /* eq (=0) */
2222 gen_op_jmp_z32(flag
, l1
);
2224 case 2: /* ogt (=1) */
2225 gen_op_sub32(flag
, flag
, gen_im32(1));
2226 gen_op_jmp_z32(flag
, l1
);
2228 case 3: /* oge (=0 or =1) */
2229 gen_op_jmp_z32(flag
, l1
);
2230 gen_op_sub32(flag
, flag
, gen_im32(1));
2231 gen_op_jmp_z32(flag
, l1
);
2233 case 4: /* olt (=-1) */
2234 gen_op_jmp_s32(flag
, l1
);
2236 case 5: /* ole (=-1 or =0) */
2237 gen_op_jmp_s32(flag
, l1
);
2238 gen_op_jmp_z32(flag
, l1
);
2240 case 6: /* ogl (=-1 or =1) */
2241 gen_op_jmp_s32(flag
, l1
);
2242 gen_op_sub32(flag
, flag
, gen_im32(1));
2243 gen_op_jmp_z32(flag
, l1
);
2245 case 7: /* or (=2) */
2246 gen_op_sub32(flag
, flag
, gen_im32(2));
2247 gen_op_jmp_z32(flag
, l1
);
2249 case 8: /* un (<2) */
2250 gen_op_sub32(flag
, flag
, gen_im32(2));
2251 gen_op_jmp_s32(flag
, l1
);
2253 case 9: /* ueq (=0 or =2) */
2254 gen_op_jmp_z32(flag
, l1
);
2255 gen_op_sub32(flag
, flag
, gen_im32(2));
2256 gen_op_jmp_z32(flag
, l1
);
2258 case 10: /* ugt (>0) */
2259 /* ??? Add jmp_gtu. */
2260 gen_op_sub32(flag
, flag
, gen_im32(1));
2261 gen_op_jmp_ns32(flag
, l1
);
2263 case 11: /* uge (>=0) */
2264 gen_op_jmp_ns32(flag
, l1
);
2266 case 12: /* ult (=-1 or =2) */
2267 gen_op_jmp_s32(flag
, l1
);
2268 gen_op_sub32(flag
, flag
, gen_im32(2));
2269 gen_op_jmp_z32(flag
, l1
);
2271 case 13: /* ule (!=1) */
2272 gen_op_sub32(flag
, flag
, gen_im32(1));
2273 gen_op_jmp_nz32(flag
, l1
);
2275 case 14: /* ne (!=0) */
2276 gen_op_jmp_nz32(flag
, l1
);
2279 gen_op_mov32(flag
, gen_im32(1));
2282 gen_jmp_tb(s
, 0, s
->pc
);
2284 gen_jmp_tb(s
, 1, addr
+ offset
);
2287 DISAS_INSN(frestore
)
2289 /* TODO: Implement frestore. */
2290 qemu_assert(0, "FRESTORE not implemented");
2295 /* TODO: Implement fsave. */
2296 qemu_assert(0, "FSAVE not implemented");
2299 static disas_proc opcode_table
[65536];
2302 register_opcode (disas_proc proc
, uint16_t opcode
, uint16_t mask
)
2308 /* Sanity check. All set bits must be included in the mask. */
2311 /* This could probably be cleverer. For now just optimize the case where
2312 the top bits are known. */
2313 /* Find the first zero bit in the mask. */
2315 while ((i
& mask
) != 0)
2317 /* Iterate over all combinations of this and lower bits. */
2322 from
= opcode
& ~(i
- 1);
2324 for (i
= from
; i
< to
; i
++) {
2325 if ((i
& mask
) == opcode
)
2326 opcode_table
[i
] = proc
;
2330 /* Register m68k opcode handlers. Order is important.
2331 Later insn override earlier ones. */
2332 void register_m68k_insns (CPUM68KState
*env
)
2334 #define INSN(name, opcode, mask, feature) \
2335 if (m68k_feature(env, M68K_FEATURE_##feature)) \
2336 register_opcode(disas_##name, 0x##opcode, 0x##mask)
2337 INSN(undef
, 0000, 0000, CF_ISA_A
);
2338 INSN(arith_im
, 0080, fff8
, CF_ISA_A
);
2339 INSN(bitrev
, 00c0
, fff8
, CF_ISA_C
);
2340 INSN(bitop_reg
, 0100, f1c0
, CF_ISA_A
);
2341 INSN(bitop_reg
, 0140, f1c0
, CF_ISA_A
);
2342 INSN(bitop_reg
, 0180, f1c0
, CF_ISA_A
);
2343 INSN(bitop_reg
, 01c0
, f1c0
, CF_ISA_A
);
2344 INSN(arith_im
, 0280, fff8
, CF_ISA_A
);
2345 INSN(byterev
, 02c0
, fff8
, CF_ISA_A
);
2346 INSN(arith_im
, 0480, fff8
, CF_ISA_A
);
2347 INSN(ff1
, 04c0
, fff8
, CF_ISA_C
);
2348 INSN(arith_im
, 0680, fff8
, CF_ISA_A
);
2349 INSN(bitop_im
, 0800, ffc0
, CF_ISA_A
);
2350 INSN(bitop_im
, 0840, ffc0
, CF_ISA_A
);
2351 INSN(bitop_im
, 0880, ffc0
, CF_ISA_A
);
2352 INSN(bitop_im
, 08c0
, ffc0
, CF_ISA_A
);
2353 INSN(arith_im
, 0a80
, fff8
, CF_ISA_A
);
2354 INSN(arith_im
, 0c00
, ff38
, CF_ISA_A
);
2355 INSN(move
, 1000, f000
, CF_ISA_A
);
2356 INSN(move
, 2000, f000
, CF_ISA_A
);
2357 INSN(move
, 3000, f000
, CF_ISA_A
);
2358 INSN(strldsr
, 40e7
, ffff
, CF_ISA_A
);
2359 INSN(negx
, 4080, fff8
, CF_ISA_A
);
2360 INSN(move_from_sr
, 40c0
, fff8
, CF_ISA_A
);
2361 INSN(lea
, 41c0
, f1c0
, CF_ISA_A
);
2362 INSN(clr
, 4200, ff00
, CF_ISA_A
);
2363 INSN(undef
, 42c0
, ffc0
, CF_ISA_A
);
2364 INSN(move_from_ccr
, 42c0
, fff8
, CF_ISA_A
);
2365 INSN(neg
, 4480, fff8
, CF_ISA_A
);
2366 INSN(move_to_ccr
, 44c0
, ffc0
, CF_ISA_A
);
2367 INSN(not, 4680, fff8
, CF_ISA_A
);
2368 INSN(move_to_sr
, 46c0
, ffc0
, CF_ISA_A
);
2369 INSN(pea
, 4840, ffc0
, CF_ISA_A
);
2370 INSN(swap
, 4840, fff8
, CF_ISA_A
);
2371 INSN(movem
, 48c0
, fbc0
, CF_ISA_A
);
2372 INSN(ext
, 4880, fff8
, CF_ISA_A
);
2373 INSN(ext
, 48c0
, fff8
, CF_ISA_A
);
2374 INSN(ext
, 49c0
, fff8
, CF_ISA_A
);
2375 INSN(tst
, 4a00
, ff00
, CF_ISA_A
);
2376 INSN(tas
, 4ac0
, ffc0
, CF_ISA_B
);
2377 INSN(halt
, 4ac8
, ffff
, CF_ISA_A
);
2378 INSN(pulse
, 4acc
, ffff
, CF_ISA_A
);
2379 INSN(illegal
, 4afc
, ffff
, CF_ISA_A
);
2380 INSN(mull
, 4c00
, ffc0
, CF_ISA_A
);
2381 INSN(divl
, 4c40
, ffc0
, CF_ISA_A
);
2382 INSN(sats
, 4c80
, fff8
, CF_ISA_B
);
2383 INSN(trap
, 4e40
, fff0
, CF_ISA_A
);
2384 INSN(link
, 4e50
, fff8
, CF_ISA_A
);
2385 INSN(unlk
, 4e58
, fff8
, CF_ISA_A
);
2386 INSN(move_to_usp
, 4e60
, fff8
, CF_ISA_B
);
2387 INSN(move_from_usp
, 4e68
, fff8
, CF_ISA_B
);
2388 INSN(nop
, 4e71
, ffff
, CF_ISA_A
);
2389 INSN(stop
, 4e72
, ffff
, CF_ISA_A
);
2390 INSN(rte
, 4e73
, ffff
, CF_ISA_A
);
2391 INSN(rts
, 4e75
, ffff
, CF_ISA_A
);
2392 INSN(movec
, 4e7b
, ffff
, CF_ISA_A
);
2393 INSN(jump
, 4e80
, ffc0
, CF_ISA_A
);
2394 INSN(jump
, 4ec0
, ffc0
, CF_ISA_A
);
2395 INSN(addsubq
, 5180, f1c0
, CF_ISA_A
);
2396 INSN(scc
, 50c0
, f0f8
, CF_ISA_A
);
2397 INSN(addsubq
, 5080, f1c0
, CF_ISA_A
);
2398 INSN(tpf
, 51f8
, fff8
, CF_ISA_A
);
2399 INSN(branch
, 6000, f000
, CF_ISA_A
);
2400 INSN(moveq
, 7000, f100
, CF_ISA_A
);
2401 INSN(mvzs
, 7100, f100
, CF_ISA_B
);
2402 INSN(or, 8000, f000
, CF_ISA_A
);
2403 INSN(divw
, 80c0
, f0c0
, CF_ISA_A
);
2404 INSN(addsub
, 9000, f000
, CF_ISA_A
);
2405 INSN(subx
, 9180, f1f8
, CF_ISA_A
);
2406 INSN(suba
, 91c0
, f1c0
, CF_ISA_A
);
2407 INSN(undef_mac
, a000
, f000
, CF_ISA_A
);
2408 INSN(mov3q
, a140
, f1c0
, CF_ISA_B
);
2409 INSN(cmp
, b000
, f1c0
, CF_ISA_B
); /* cmp.b */
2410 INSN(cmp
, b040
, f1c0
, CF_ISA_B
); /* cmp.w */
2411 INSN(cmpa
, b0c0
, f1c0
, CF_ISA_B
); /* cmpa.w */
2412 INSN(cmp
, b080
, f1c0
, CF_ISA_A
);
2413 INSN(cmpa
, b1c0
, f1c0
, CF_ISA_A
);
2414 INSN(eor
, b180
, f1c0
, CF_ISA_A
);
2415 INSN(and, c000
, f000
, CF_ISA_A
);
2416 INSN(mulw
, c0c0
, f0c0
, CF_ISA_A
);
2417 INSN(addsub
, d000
, f000
, CF_ISA_A
);
2418 INSN(addx
, d180
, f1f8
, CF_ISA_A
);
2419 INSN(adda
, d1c0
, f1c0
, CF_ISA_A
);
2420 INSN(shift_im
, e080
, f0f0
, CF_ISA_A
);
2421 INSN(shift_reg
, e0a0
, f0f0
, CF_ISA_A
);
2422 INSN(undef_fpu
, f000
, f000
, CF_ISA_A
);
2423 INSN(fpu
, f200
, ffc0
, CF_FPU
);
2424 INSN(fbcc
, f280
, ffc0
, CF_FPU
);
2425 INSN(frestore
, f340
, ffc0
, CF_FPU
);
2426 INSN(fsave
, f340
, ffc0
, CF_FPU
);
2427 INSN(intouch
, f340
, ffc0
, CF_ISA_A
);
2428 INSN(cpushl
, f428
, ff38
, CF_ISA_A
);
2429 INSN(wddata
, fb00
, ff00
, CF_ISA_A
);
2430 INSN(wdebug
, fbc0
, ffc0
, CF_ISA_A
);
2434 /* ??? Some of this implementation is not exception safe. We should always
2435 write back the result to memory before setting the condition codes. */
2436 static void disas_m68k_insn(CPUState
* env
, DisasContext
*s
)
2440 insn
= lduw_code(s
->pc
);
2443 opcode_table
[insn
](s
, insn
);
2447 /* Save the result of a floating point operation. */
2448 static void expand_op_fp_result(qOP
*qop
)
2450 gen_op_movf64(QREG_FP_RESULT
, qop
->args
[0]);
2453 /* Dummy op to indicate that the flags have been set. */
2454 static void expand_op_flags_set(qOP
*qop
)
2458 /* Convert the confition codes into CC_OP_FLAGS format. */
2459 static void expand_op_flush_flags(qOP
*qop
)
2463 if (qop
->args
[0] == CC_OP_DYNAMIC
)
2464 cc_opreg
= QREG_CC_OP
;
2466 cc_opreg
= gen_im32(qop
->args
[0]);
2467 gen_op_helper32(QREG_NULL
, cc_opreg
, HELPER_flush_flags
);
2470 /* Set CC_DEST after a logical or direct flag setting operation. */
2471 static void expand_op_logic_cc(qOP
*qop
)
2473 gen_op_mov32(QREG_CC_DEST
, qop
->args
[0]);
2476 /* Set CC_SRC and CC_DEST after an arithmetic operation. */
2477 static void expand_op_update_cc_add(qOP
*qop
)
2479 gen_op_mov32(QREG_CC_DEST
, qop
->args
[0]);
2480 gen_op_mov32(QREG_CC_SRC
, qop
->args
[1]);
2483 /* Update the X flag. */
2484 static void expand_op_update_xflag(qOP
*qop
)
2489 arg0
= qop
->args
[0];
2490 arg1
= qop
->args
[1];
2491 if (arg1
== QREG_NULL
) {
2493 gen_op_mov32(QREG_CC_X
, arg0
);
2495 /* CC_X = arg0 < (unsigned)arg1. */
2496 gen_op_set_ltu32(QREG_CC_X
, arg0
, arg1
);
2500 /* Set arg0 to the contents of the X flag. */
2501 static void expand_op_get_xflag(qOP
*qop
)
2503 gen_op_mov32(qop
->args
[0], QREG_CC_X
);
2506 /* Expand a shift by immediate. The ISA only allows shifts by 1-8, so we
2507 already know the shift is within range. */
2508 static inline void expand_shift_im(qOP
*qop
, int right
, int arith
)
2518 val
= gen_new_qreg(QMODE_I32
);
2519 gen_op_mov32(val
, reg
);
2520 gen_op_mov32(QREG_CC_DEST
, val
);
2521 gen_op_mov32(QREG_CC_SRC
, tmp
);
2524 gen_op_sar32(reg
, val
, tmp
);
2526 gen_op_shr32(reg
, val
, tmp
);
2531 tmp
= gen_im32(im
- 1);
2533 gen_op_shl32(reg
, val
, tmp
);
2534 tmp
= gen_im32(32 - im
);
2536 if (tmp
!= QREG_NULL
)
2537 gen_op_shr32(val
, val
, tmp
);
2538 gen_op_and32(QREG_CC_X
, val
, gen_im32(1));
2541 static void expand_op_shl_im_cc(qOP
*qop
)
2543 expand_shift_im(qop
, 0, 0);
2546 static void expand_op_shr_im_cc(qOP
*qop
)
2548 expand_shift_im(qop
, 1, 0);
2551 static void expand_op_sar_im_cc(qOP
*qop
)
2553 expand_shift_im(qop
, 1, 1);
2556 /* Expand a shift by register. */
2557 /* ??? This gives incorrect answers for shifts by 0 or >= 32 */
2558 static inline void expand_shift_reg(qOP
*qop
, int right
, int arith
)
2566 shift
= qop
->args
[1];
2567 val
= gen_new_qreg(QMODE_I32
);
2568 gen_op_mov32(val
, reg
);
2569 gen_op_mov32(QREG_CC_DEST
, val
);
2570 gen_op_mov32(QREG_CC_SRC
, shift
);
2571 tmp
= gen_new_qreg(QMODE_I32
);
2574 gen_op_sar32(reg
, val
, shift
);
2576 gen_op_shr32(reg
, val
, shift
);
2578 gen_op_sub32(tmp
, shift
, gen_im32(1));
2580 gen_op_shl32(reg
, val
, shift
);
2581 gen_op_sub32(tmp
, gen_im32(31), shift
);
2583 gen_op_shl32(val
, val
, tmp
);
2584 gen_op_and32(QREG_CC_X
, val
, gen_im32(1));
2587 static void expand_op_shl_cc(qOP
*qop
)
2589 expand_shift_reg(qop
, 0, 0);
2592 static void expand_op_shr_cc(qOP
*qop
)
2594 expand_shift_reg(qop
, 1, 0);
2597 static void expand_op_sar_cc(qOP
*qop
)
2599 expand_shift_reg(qop
, 1, 1);
2602 /* Set the Z flag to (arg0 & arg1) == 0. */
2603 static void expand_op_btest(qOP
*qop
)
2608 l1
= gen_new_label();
2609 tmp
= gen_new_qreg(QMODE_I32
);
2610 gen_op_and32(tmp
, qop
->args
[0], qop
->args
[1]);
2611 gen_op_and32(QREG_CC_DEST
, QREG_CC_DEST
, gen_im32(~(uint32_t)CCF_Z
));
2612 gen_op_jmp_nz32(tmp
, l1
);
2613 gen_op_or32(QREG_CC_DEST
, QREG_CC_DEST
, gen_im32(CCF_Z
));
2617 /* arg0 += arg1 + CC_X */
2618 static void expand_op_addx_cc(qOP
*qop
)
2620 int arg0
= qop
->args
[0];
2621 int arg1
= qop
->args
[1];
2624 gen_op_add32 (arg0
, arg0
, arg1
);
2625 l1
= gen_new_label();
2626 l2
= gen_new_label();
2627 gen_op_jmp_z32(QREG_CC_X
, l1
);
2628 gen_op_add32(arg0
, arg0
, gen_im32(1));
2629 gen_op_mov32(QREG_CC_OP
, gen_im32(CC_OP_ADDX
));
2630 gen_op_set_leu32(QREG_CC_X
, arg0
, arg1
);
2633 gen_op_mov32(QREG_CC_OP
, gen_im32(CC_OP_ADD
));
2634 gen_op_set_ltu32(QREG_CC_X
, arg0
, arg1
);
2638 /* arg0 -= arg1 + CC_X */
2639 static void expand_op_subx_cc(qOP
*qop
)
2641 int arg0
= qop
->args
[0];
2642 int arg1
= qop
->args
[1];
2645 l1
= gen_new_label();
2646 l2
= gen_new_label();
2647 gen_op_jmp_z32(QREG_CC_X
, l1
);
2648 gen_op_set_leu32(QREG_CC_X
, arg0
, arg1
);
2649 gen_op_sub32(arg0
, arg0
, gen_im32(1));
2650 gen_op_mov32(QREG_CC_OP
, gen_im32(CC_OP_SUBX
));
2653 gen_op_set_ltu32(QREG_CC_X
, arg0
, arg1
);
2654 gen_op_mov32(QREG_CC_OP
, gen_im32(CC_OP_SUB
));
2656 gen_op_sub32 (arg0
, arg0
, arg1
);
2659 /* Expand target specific ops to generic qops. */
2660 static void expand_target_qops(void)
2666 /* Copy the list of qops, expanding target specific ops as we go. */
2667 qop
= gen_first_qop
;
2668 gen_first_qop
= NULL
;
2669 gen_last_qop
= NULL
;
2670 for (; qop
; qop
= next
) {
2673 if (c
< FIRST_TARGET_OP
) {
2674 qop
->prev
= gen_last_qop
;
2677 gen_last_qop
->next
= qop
;
2679 gen_first_qop
= qop
;
2684 #define DEF(name, nargs, barrier) \
2685 case INDEX_op_##name: \
2686 expand_op_##name(qop); \
2688 #include "qop-target.def"
2691 cpu_abort(NULL
, "Unexpanded target qop");
2696 /* ??? Implement this. */
2698 optimize_flags(void)
2703 /* generate intermediate code for basic block 'tb'. */
2705 gen_intermediate_code_internal(CPUState
*env
, TranslationBlock
*tb
,
2708 DisasContext dc1
, *dc
= &dc1
;
2709 uint16_t *gen_opc_end
;
2711 target_ulong pc_start
;
2715 /* generate intermediate code */
2720 gen_opc_ptr
= gen_opc_buf
;
2721 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
2722 gen_opparam_ptr
= gen_opparam_buf
;
2724 dc
->is_jmp
= DISAS_NEXT
;
2726 dc
->cc_op
= CC_OP_DYNAMIC
;
2727 dc
->singlestep_enabled
= env
->singlestep_enabled
;
2728 dc
->fpcr
= env
->fpcr
;
2729 dc
->user
= (env
->sr
& SR_S
) == 0;
2734 pc_offset
= dc
->pc
- pc_start
;
2735 gen_throws_exception
= NULL
;
2736 if (env
->nb_breakpoints
> 0) {
2737 for(j
= 0; j
< env
->nb_breakpoints
; j
++) {
2738 if (env
->breakpoints
[j
] == dc
->pc
) {
2739 gen_exception(dc
, dc
->pc
, EXCP_DEBUG
);
2740 dc
->is_jmp
= DISAS_JUMP
;
2748 j
= gen_opc_ptr
- gen_opc_buf
;
2752 gen_opc_instr_start
[lj
++] = 0;
2754 gen_opc_pc
[lj
] = dc
->pc
;
2755 gen_opc_instr_start
[lj
] = 1;
2757 last_cc_op
= dc
->cc_op
;
2758 disas_m68k_insn(env
, dc
);
2759 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
2760 !env
->singlestep_enabled
&&
2761 (pc_offset
) < (TARGET_PAGE_SIZE
- 32));
2763 if (__builtin_expect(env
->singlestep_enabled
, 0)) {
2764 /* Make sure the pc is updated, and raise a debug exception. */
2766 gen_flush_cc_op(dc
);
2767 gen_op_mov32(QREG_PC
, gen_im32((long)dc
->pc
));
2769 gen_op_raise_exception(EXCP_DEBUG
);
2771 switch(dc
->is_jmp
) {
2773 gen_flush_cc_op(dc
);
2774 gen_jmp_tb(dc
, 0, dc
->pc
);
2779 gen_flush_cc_op(dc
);
2780 /* indicate that the hash table must be used to find the next TB */
2781 gen_op_mov32(QREG_T0
, gen_im32(0));
2785 /* nothing more to generate */
2789 *gen_opc_ptr
= INDEX_op_end
;
2792 if (loglevel
& CPU_LOG_TB_IN_ASM
) {
2793 fprintf(logfile
, "----------------\n");
2794 fprintf(logfile
, "IN: %s\n", lookup_symbol(pc_start
));
2795 target_disas(logfile
, pc_start
, dc
->pc
- pc_start
, 0);
2796 fprintf(logfile
, "\n");
2797 if (loglevel
& (CPU_LOG_TB_OP
)) {
2798 fprintf(logfile
, "OP:\n");
2799 dump_ops(gen_opc_buf
, gen_opparam_buf
);
2800 fprintf(logfile
, "\n");
2805 j
= gen_opc_ptr
- gen_opc_buf
;
2808 gen_opc_instr_start
[lj
++] = 0;
2811 tb
->size
= dc
->pc
- pc_start
;
2815 //expand_target_qops();
2819 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
2821 return gen_intermediate_code_internal(env
, tb
, 0);
2824 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
2826 return gen_intermediate_code_internal(env
, tb
, 1);
2829 void cpu_reset(CPUM68KState
*env
)
2831 memset(env
, 0, offsetof(CPUM68KState
, breakpoints
));
2832 #if !defined (CONFIG_USER_ONLY)
2835 /* ??? FP regs should be initialized to NaN. */
2836 env
->cc_op
= CC_OP_FLAGS
;
2837 /* TODO: We should set PC from the interrupt vector. */
2842 CPUM68KState
*cpu_m68k_init(void)
2846 env
= malloc(sizeof(CPUM68KState
));
2855 void cpu_m68k_close(CPUM68KState
*env
)
2860 void cpu_dump_state(CPUState
*env
, FILE *f
,
2861 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
2867 for (i
= 0; i
< 8; i
++)
2869 u
.d
= env
->fregs
[i
];
2870 cpu_fprintf (f
, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
2871 i
, env
->dregs
[i
], i
, env
->aregs
[i
],
2872 i
, u
.l
.upper
, u
.l
.lower
, u
.d
);
2874 cpu_fprintf (f
, "PC = %08x ", env
->pc
);
2876 cpu_fprintf (f
, "SR = %04x %c%c%c%c%c ", sr
, (sr
& 0x10) ? 'X' : '-',
2877 (sr
& CCF_N
) ? 'N' : '-', (sr
& CCF_Z
) ? 'Z' : '-',
2878 (sr
& CCF_V
) ? 'V' : '-', (sr
& CCF_C
) ? 'C' : '-');
2879 cpu_fprintf (f
, "FPRESULT = %12g\n", env
->fp_result
);