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