]> git.proxmox.com Git - mirror_qemu.git/blob - target/m68k/translate.c
target/m68k: Check for USER_ONLY definition instead of SOFTMMU one
[mirror_qemu.git] / target / m68k / translate.c
1 /*
2 * m68k translation
3 *
4 * Copyright (c) 2005-2007 CodeSourcery
5 * Written by Paul Brook
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "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 //#define DEBUG_DISPATCH 1
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
49 static TCGv_i32 cpu_halted;
50 static TCGv_i32 cpu_exception_index;
51
52 static char cpu_reg_names[2 * 8 * 3 + 5 * 4];
53 static TCGv cpu_dregs[8];
54 static TCGv cpu_aregs[8];
55 static 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
63 static TCGv NULL_QREG;
64 #define IS_NULL_QREG(t) (t == NULL_QREG)
65 /* Used to distinguish stores from bad addressing modes. */
66 static TCGv store_dummy;
67
68 void 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 /* internal defines */
114 typedef struct DisasContext {
115 DisasContextBase base;
116 CPUM68KState *env;
117 target_ulong pc;
118 target_ulong pc_prev;
119 CCOp cc_op; /* Current CC operation */
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
128 static 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
137 static 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
158 static 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 /* is_jmp field values */
172 #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
173 #define DISAS_EXIT DISAS_TARGET_1 /* cpu state was modified dynamically */
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
185 typedef 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
205 static 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
214 static 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 * Discard CC computation that will no longer be used.
227 * Note that X and N are never dead.
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 /* Update the CPU env CC_OP state. */
242 static 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 /* Generate a jump to an immediate address. */
251 static 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 /* Generate a jump to the address in qreg DEST. */
259 static 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
266 static void gen_raise_exception(int nr)
267 {
268 gen_helper_raise_exception(cpu_env, tcg_constant_i32(nr));
269 }
270
271 static void gen_raise_exception_format2(DisasContext *s, int nr,
272 target_ulong this_pc)
273 {
274 /*
275 * Pass the address of the insn to the exception handler,
276 * for recording in the Format $2 (6-word) stack frame.
277 * Re-use mmu.ar for the purpose, since that's only valid
278 * after tlb_fill.
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
286 static 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
296 static inline void gen_addr_fault(DisasContext *s)
297 {
298 gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
299 }
300
301 /*
302 * Generate a load from the specified address. Narrow values are
303 * sign extended to full register width.
304 */
305 static 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 /* Generate a store. */
324 static 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
338 typedef enum {
339 EA_STORE,
340 EA_LOADU,
341 EA_LOADS
342 } ea_what;
343
344 /*
345 * Generate an unsigned load if VAL is 0 a signed load if val is -1,
346 * otherwise generate a store.
347 */
348 static 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 /* Read a 16-bit immediate constant */
360 static 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 /* Read an 8-bit immediate constant */
369 static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
370 {
371 return read_im16(env, s);
372 }
373
374 /* Read a 32-bit immediate constant. */
375 static 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 /* Read a 64-bit immediate constant. */
384 static 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 /* Calculate and address index. */
393 static 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 * Handle a base + index + displacement effective address.
413 * A NULL_QREG base means pc-relative.
414 */
415 static 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 /* full extension word format */
436 if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
437 return NULL_QREG;
438
439 if ((ext & 0x30) > 0x10) {
440 /* base displacement */
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 /* pre-index */
452 add = gen_addr_index(s, ext, tmp);
453 } else {
454 add = NULL_QREG;
455 }
456 if ((ext & 0x80) == 0) {
457 /* base not suppressed */
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 /* memory indirect */
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 /* outer displacement */
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 /* brief extension word format */
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 /* Sign or zero extend a value. */
519
520 static 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 /* Evaluate all the CC flags. */
546
547 static 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 /* Compute signed overflow for addition. */
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 /* Compute signed overflow for subtraction. */
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 /* Compute signed overflow for subtraction. */
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 /* Note that flush_flags also assigned to env->cc_op. */
617 s->cc_op = CC_OP_FLAGS;
618 }
619
620 static 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
634 static 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
640 static 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
647 static 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
653 static 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
668 static 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
679 static 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 * Assign value to a register. If the width is less than the register width
696 * only the low part of the register is set.
697 */
698 static 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 * Generate code for an "effective address". Does not adjust the base
725 * register for autoincrement addressing modes.
726 */
727 static 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: /* Data register direct. */
737 case 1: /* Address register direct. */
738 return NULL_QREG;
739 case 3: /* Indirect postincrement. */
740 if (opsize == OS_UNSIZED) {
741 return NULL_QREG;
742 }
743 /* fallthru */
744 case 2: /* Indirect register */
745 return get_areg(s, reg0);
746 case 4: /* Indirect predecrememnt. */
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: /* Indirect displacement. */
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: /* Indirect index + displacement. */
766 reg = get_areg(s, reg0);
767 return gen_lea_indexed(env, s, reg);
768 case 7: /* Other */
769 switch (reg0) {
770 case 0: /* Absolute short. */
771 offset = (int16_t)read_im16(env, s);
772 return tcg_constant_i32(offset);
773 case 1: /* Absolute long. */
774 offset = read_im32(env, s);
775 return tcg_constant_i32(offset);
776 case 2: /* pc displacement */
777 offset = s->pc;
778 offset += (int16_t)read_im16(env, s);
779 return tcg_constant_i32(offset);
780 case 3: /* pc index+displacement. */
781 return gen_lea_indexed(env, s, NULL_QREG);
782 case 4: /* Immediate. */
783 default:
784 return NULL_QREG;
785 }
786 }
787 /* Should never happen. */
788 return NULL_QREG;
789 }
790
791 static 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 * Generate code to load/store a value from/into an EA. If WHAT > 0 this is
801 * a write otherwise it is a read (0 == sign extend, -1 == zero extend).
802 * ADDRP is non-null for readwrite operands.
803 */
804 static 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: /* Data register direct. */
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: /* Address register direct. */
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: /* Indirect register */
829 reg = get_areg(s, reg0);
830 return gen_ldst(s, opsize, reg, val, what, index);
831 case 3: /* Indirect postincrement. */
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: /* Indirect predecrememnt. */
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: /* Indirect displacement. */
863 case 6: /* Indirect index + displacement. */
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: /* Other */
878 switch (reg0) {
879 case 0: /* Absolute short. */
880 case 1: /* Absolute long. */
881 case 2: /* pc displacement */
882 case 3: /* pc index+displacement. */
883 goto do_indirect;
884 case 4: /* Immediate. */
885 /* Sign extend values for consistency. */
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 /* Should never happen. */
913 return NULL_QREG;
914 }
915
916 static 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
924 static 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
931 static 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
938 static 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
952 static 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 * unimplemented data type on 68040/ColdFire
990 * FIXME if needed for another FPU
991 */
992 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
993 break;
994 default:
995 g_assert_not_reached();
996 }
997 }
998
999 static 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 * unimplemented data type on 68040/ColdFire
1037 * FIXME if needed for another FPU
1038 */
1039 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1040 break;
1041 default:
1042 g_assert_not_reached();
1043 }
1044 }
1045
1046 static 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
1056 static 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: /* Data register direct. */
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: /* Address register direct. */
1102 return -1;
1103 case 2: /* Indirect register */
1104 addr = get_areg(s, reg0);
1105 gen_ldst_fp(s, opsize, addr, fp, what, index);
1106 return 0;
1107 case 3: /* Indirect postincrement. */
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: /* Indirect predecrememnt. */
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: /* Indirect displacement. */
1121 case 6: /* Indirect index + displacement. */
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: /* Other */
1130 switch (reg0) {
1131 case 0: /* Absolute short. */
1132 case 1: /* Absolute long. */
1133 case 2: /* pc displacement */
1134 case 3: /* pc index+displacement. */
1135 goto do_indirect;
1136 case 4: /* Immediate. */
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 * unimplemented data type on 68040/ColdFire
1174 * FIXME if needed for another FPU
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
1189 static 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
1197 typedef struct {
1198 TCGCond tcond;
1199 TCGv v1;
1200 TCGv v2;
1201 } DisasCompare;
1202
1203 static 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 /* The CC_OP_CMP form can handle most normal comparisons directly. */
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: /* HI */
1215 case 3: /* LS */
1216 tcond = TCG_COND_LEU;
1217 goto done;
1218 case 4: /* CC */
1219 case 5: /* CS */
1220 tcond = TCG_COND_LTU;
1221 goto done;
1222 case 6: /* NE */
1223 case 7: /* EQ */
1224 tcond = TCG_COND_EQ;
1225 goto done;
1226 case 10: /* PL */
1227 case 11: /* MI */
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 /* fallthru */
1233 case 12: /* GE */
1234 case 13: /* LT */
1235 tcond = TCG_COND_LT;
1236 goto done;
1237 case 14: /* GT */
1238 case 15: /* LE */
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: /* T */
1248 case 1: /* F */
1249 c->v1 = c->v2;
1250 tcond = TCG_COND_NEVER;
1251 goto done;
1252 case 14: /* GT (!(Z || (N ^ V))) */
1253 case 15: /* LE (Z || (N ^ V)) */
1254 /*
1255 * Logic operations clear V, which simplifies LE to (Z || N),
1256 * and since Z and N are co-located, this becomes a normal
1257 * comparison vs N.
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: /* GE (!(N ^ V)) */
1266 case 13: /* LT (N ^ V) */
1267 /* Logic operations clear V, which simplifies this to N. */
1268 if (op != CC_OP_LOGIC) {
1269 break;
1270 }
1271 /* fallthru */
1272 case 10: /* PL (!N) */
1273 case 11: /* MI (N) */
1274 /* Several cases represent N normally. */
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: /* NE (!Z) */
1284 case 7: /* EQ (Z) */
1285 /* Some cases fold Z into N. */
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: /* CC (!C) */
1295 case 5: /* CS (C) */
1296 /* Some cases fold C into X. */
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 /* fallthru */
1304 case 8: /* VC (!V) */
1305 case 9: /* VS (V) */
1306 /* Logic operations clear V and C. */
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 /* Otherwise, flush flag state to CC_OP_FLAGS. */
1316 gen_flush_flags(s);
1317
1318 switch (cond) {
1319 case 0: /* T */
1320 case 1: /* F */
1321 default:
1322 /* Invalid, or handled above. */
1323 abort();
1324 case 2: /* HI (!C && !Z) -> !(C || Z)*/
1325 case 3: /* LS (C || Z) */
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: /* CC (!C) */
1332 case 5: /* CS (C) */
1333 c->v1 = QREG_CC_C;
1334 tcond = TCG_COND_NE;
1335 break;
1336 case 6: /* NE (!Z) */
1337 case 7: /* EQ (Z) */
1338 c->v1 = QREG_CC_Z;
1339 tcond = TCG_COND_EQ;
1340 break;
1341 case 8: /* VC (!V) */
1342 case 9: /* VS (V) */
1343 c->v1 = QREG_CC_V;
1344 tcond = TCG_COND_LT;
1345 break;
1346 case 10: /* PL (!N) */
1347 case 11: /* MI (N) */
1348 c->v1 = QREG_CC_N;
1349 tcond = TCG_COND_LT;
1350 break;
1351 case 12: /* GE (!(N ^ V)) */
1352 case 13: /* LT (N ^ V) */
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: /* GT (!(Z || (N ^ V))) */
1358 case 15: /* LE (Z || (N ^ V)) */
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
1376 static 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 /* Force a TB lookup after an instruction that changes the CPU state. */
1386 static 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 /* Generate a jump to an immediate address. */
1412 static 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
1430 DISAS_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
1446 DISAS_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
1470 DISAS_INSN(undef_mac)
1471 {
1472 gen_exception(s, s->base.pc_next, EXCP_LINEA);
1473 }
1474
1475 DISAS_INSN(undef_fpu)
1476 {
1477 gen_exception(s, s->base.pc_next, EXCP_LINEF);
1478 }
1479
1480 DISAS_INSN(undef)
1481 {
1482 /*
1483 * ??? This is both instructions that are as yet unimplemented
1484 * for the 680x0 series, as well as those that are implemented
1485 * but actually illegal for CPU32 or pre-68020.
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
1492 DISAS_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
1512 DISAS_INSN(divw)
1513 {
1514 int sign;
1515 TCGv src;
1516 TCGv destr;
1517 TCGv ilen;
1518
1519 /* divX.w <EA>,Dn 32/16 -> 16r:16q */
1520
1521 sign = (insn & 0x100) != 0;
1522
1523 /* dest.l / src.w */
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
1537 DISAS_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 /* divX.l <EA>, Dr:Dq 64/32 -> 32r:32q */
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 /* divX.l <EA>, Dq 32/32 -> 32q */
1569 /* divXl.l <EA>, Dr:Dq 32/32 -> 32r:32q */
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
1584 static void bcd_add(TCGv dest, TCGv src)
1585 {
1586 TCGv t0, t1;
1587
1588 /*
1589 * dest10 = dest10 + src10 + X
1590 *
1591 * t1 = src
1592 * t2 = t1 + 0x066
1593 * t3 = t2 + dest + X
1594 * t4 = t2 ^ dest
1595 * t5 = t3 ^ t4
1596 * t6 = ~t5 & 0x110
1597 * t7 = (t6 >> 2) | (t6 >> 3)
1598 * return t3 - t7
1599 */
1600
1601 /*
1602 * t1 = (src + 0x066) + dest + X
1603 * = result with some possible exceeding 0x6
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 /* we will remove exceeding 0x6 where there is no carry */
1614
1615 /*
1616 * t0 = (src + 0x0066) ^ dest
1617 * = t1 without carries
1618 */
1619
1620 tcg_gen_xor_i32(t0, t0, dest);
1621
1622 /*
1623 * extract the carries
1624 * t0 = t0 ^ t1
1625 * = only the carries
1626 */
1627
1628 tcg_gen_xor_i32(t0, t0, t1);
1629
1630 /*
1631 * generate 0x1 where there is no carry
1632 * and for each 0x10, generate a 0x6
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 * remove the exceeding 0x6
1643 * for digits that have not generated a carry
1644 */
1645
1646 tcg_gen_sub_i32(dest, t1, dest);
1647 }
1648
1649 static void bcd_sub(TCGv dest, TCGv src)
1650 {
1651 TCGv t0, t1, t2;
1652
1653 /*
1654 * dest10 = dest10 - src10 - X
1655 * = bcd_add(dest + 1 - X, 0x199 - src)
1656 */
1657
1658 /* t0 = 0x066 + (0x199 - src) */
1659
1660 t0 = tcg_temp_new();
1661 tcg_gen_subfi_i32(t0, 0x1ff, src);
1662
1663 /* t1 = t0 + dest + 1 - X*/
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 /* t2 = t0 ^ dest */
1671
1672 t2 = tcg_temp_new();
1673 tcg_gen_xor_i32(t2, t0, dest);
1674
1675 /* t0 = t1 ^ t2 */
1676
1677 tcg_gen_xor_i32(t0, t1, t2);
1678
1679 /*
1680 * t2 = ~t0 & 0x110
1681 * t0 = (t2 >> 2) | (t2 >> 3)
1682 *
1683 * to fit on 8bit operands, changed in:
1684 *
1685 * t2 = ~(t0 >> 3) & 0x22
1686 * t0 = t2 + t2
1687 * t0 = t0 + t2
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 /* return t1 - t0 */
1697
1698 tcg_gen_sub_i32(dest, t1, t0);
1699 }
1700
1701 static 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
1711 DISAS_INSN(abcd_reg)
1712 {
1713 TCGv src;
1714 TCGv dest;
1715
1716 gen_flush_flags(s); /* !Z is sticky */
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
1726 DISAS_INSN(abcd_mem)
1727 {
1728 TCGv src, dest, addr;
1729
1730 gen_flush_flags(s); /* !Z is sticky */
1731
1732 /* Indirect pre-decrement load (mode 4) */
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
1747 DISAS_INSN(sbcd_reg)
1748 {
1749 TCGv src, dest;
1750
1751 gen_flush_flags(s); /* !Z is sticky */
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
1763 DISAS_INSN(sbcd_mem)
1764 {
1765 TCGv src, dest, addr;
1766
1767 gen_flush_flags(s); /* !Z is sticky */
1768
1769 /* Indirect pre-decrement load (mode 4) */
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
1784 DISAS_INSN(nbcd)
1785 {
1786 TCGv src, dest;
1787 TCGv addr;
1788
1789 gen_flush_flags(s); /* !Z is sticky */
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
1802 DISAS_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 /* Reverse the order of the bits in REG. */
1841 DISAS_INSN(bitrev)
1842 {
1843 TCGv reg;
1844 reg = DREG(insn, 0);
1845 gen_helper_bitrev(reg, reg);
1846 }
1847
1848 DISAS_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: /* bchg */
1880 tcg_gen_xor_i32(dest, src1, tmp);
1881 break;
1882 case 2: /* bclr */
1883 tcg_gen_andc_i32(dest, src1, tmp);
1884 break;
1885 case 3: /* bset */
1886 tcg_gen_or_i32(dest, src1, tmp);
1887 break;
1888 default: /* btst */
1889 break;
1890 }
1891 if (op) {
1892 DEST_EA(env, insn, opsize, dest, &addr);
1893 }
1894 }
1895
1896 DISAS_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
1905 static 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
1915 static TCGv mreg(int reg)
1916 {
1917 if (reg < 8) {
1918 /* Dx */
1919 return cpu_dregs[reg];
1920 }
1921 /* Ax */
1922 return cpu_aregs[reg & 7];
1923 }
1924
1925 DISAS_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: /* data register direct */
1939 case 1: /* addr register direct */
1940 do_addr_fault:
1941 gen_addr_fault(s);
1942 return;
1943
1944 case 2: /* indirect */
1945 break;
1946
1947 case 3: /* indirect post-increment */
1948 if (!is_load) {
1949 /* post-increment is not allowed */
1950 goto do_addr_fault;
1951 }
1952 break;
1953
1954 case 4: /* indirect pre-decrement */
1955 if (is_load) {
1956 /* pre-decrement is not allowed */
1957 goto do_addr_fault;
1958 }
1959 /*
1960 * We want a bare copy of the address reg, without any pre-decrement
1961 * adjustment, as gen_lea would provide.
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 /* memory to register */
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 /* post-increment: movem (An)+,X */
1992 tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1993 }
1994 } else {
1995 /* register to memory */
1996 if (mode == 4) {
1997 /* pre-decrement: movem X,-(An) */
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 * M68020+: if the addressing register is the
2005 * register moved to memory, the value written
2006 * is the initial value decremented by the size of
2007 * the operation, regardless of how many actual
2008 * stores have been performed until this point.
2009 * M68000/M68010: the value is the initial value.
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
2031 DISAS_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
2074 DISAS_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: /* bchg */
2118 tcg_gen_xori_i32(tmp, src1, mask);
2119 break;
2120 case 2: /* bclr */
2121 tcg_gen_andi_i32(tmp, src1, ~mask);
2122 break;
2123 case 3: /* bset */
2124 tcg_gen_ori_i32(tmp, src1, mask);
2125 break;
2126 default: /* btst */
2127 break;
2128 }
2129 DEST_EA(env, insn, opsize, tmp, &addr);
2130 }
2131 }
2132
2133 static 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
2143 static 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
2155 static 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 /* Must writeback before changing security state. */
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
2171 static 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 /* Must writeback before changing security state. */
2177 do_writebacks(s);
2178 gen_helper_set_sr(cpu_env, val);
2179 }
2180 set_cc_op(s, CC_OP_FLAGS);
2181 }
2182
2183 static 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
2197 DISAS_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 /* SR/CCR can only be used with andi/eori/ori */
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 /* OS_LONG; others already g_assert_not_reached. */
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: /* ori */
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: /* andi */
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: /* subi */
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: /* addi */
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: /* eori */
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: /* cmpi */
2295 gen_update_cc_cmp(s, src1, im, opsize);
2296 break;
2297 default:
2298 abort();
2299 }
2300 }
2301
2302 DISAS_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 /* cas Dc,Du,<EA> */
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 * if <EA> == Dc then
2342 * <EA> = Du
2343 * Dc = <EA> (because <EA> == Dc)
2344 * else
2345 * Dc = <EA>
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 /* update flags before setting cmp to load */
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: /* Indirect postincrement. */
2357 tcg_gen_addi_i32(AREG(insn, 0), addr, opsize_bytes(opsize));
2358 break;
2359 case 4: /* Indirect predecrememnt. */
2360 tcg_gen_mov_i32(AREG(insn, 0), addr);
2361 break;
2362 }
2363 }
2364
2365 DISAS_INSN(cas2w)
2366 {
2367 uint16_t ext1, ext2;
2368 TCGv addr1, addr2;
2369
2370 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2371
2372 ext1 = read_im16(env, s);
2373
2374 if (ext1 & 0x8000) {
2375 /* Address Register */
2376 addr1 = AREG(ext1, 12);
2377 } else {
2378 /* Data Register */
2379 addr1 = DREG(ext1, 12);
2380 }
2381
2382 ext2 = read_im16(env, s);
2383 if (ext2 & 0x8000) {
2384 /* Address Register */
2385 addr2 = AREG(ext2, 12);
2386 } else {
2387 /* Data Register */
2388 addr2 = DREG(ext2, 12);
2389 }
2390
2391 /*
2392 * if (R1) == Dc1 && (R2) == Dc2 then
2393 * (R1) = Du1
2394 * (R2) = Du2
2395 * else
2396 * Dc1 = (R1)
2397 * Dc2 = (R2)
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 /* Note that cas2w also assigned to env->cc_op. */
2411 s->cc_op = CC_OP_CMPW;
2412 s->cc_op_synced = 1;
2413 }
2414
2415 DISAS_INSN(cas2l)
2416 {
2417 uint16_t ext1, ext2;
2418 TCGv addr1, addr2, regs;
2419
2420 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2421
2422 ext1 = read_im16(env, s);
2423
2424 if (ext1 & 0x8000) {
2425 /* Address Register */
2426 addr1 = AREG(ext1, 12);
2427 } else {
2428 /* Data Register */
2429 addr1 = DREG(ext1, 12);
2430 }
2431
2432 ext2 = read_im16(env, s);
2433 if (ext2 & 0x8000) {
2434 /* Address Register */
2435 addr2 = AREG(ext2, 12);
2436 } else {
2437 /* Data Register */
2438 addr2 = DREG(ext2, 12);
2439 }
2440
2441 /*
2442 * if (R1) == Dc1 && (R2) == Dc2 then
2443 * (R1) = Du1
2444 * (R2) = Du2
2445 * else
2446 * Dc1 = (R1)
2447 * Dc2 = (R2)
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 /* Note that cas2l also assigned to env->cc_op. */
2461 s->cc_op = CC_OP_CMPL;
2462 s->cc_op_synced = 1;
2463 }
2464
2465 DISAS_INSN(byterev)
2466 {
2467 TCGv reg;
2468
2469 reg = DREG(insn, 0);
2470 tcg_gen_bswap32_i32(reg, reg);
2471 }
2472
2473 DISAS_INSN(move)
2474 {
2475 TCGv src;
2476 TCGv dest;
2477 int op;
2478 int opsize;
2479
2480 switch (insn >> 12) {
2481 case 1: /* move.b */
2482 opsize = OS_BYTE;
2483 break;
2484 case 2: /* move.l */
2485 opsize = OS_LONG;
2486 break;
2487 case 3: /* move.w */
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 /* movea */
2497 /* The value will already have been sign extended. */
2498 dest = AREG(insn, 9);
2499 tcg_gen_mov_i32(dest, src);
2500 } else {
2501 /* normal move */
2502 uint16_t dest_ea;
2503 dest_ea = ((insn >> 9) & 7) | (op << 3);
2504 DEST_EA(env, dest_ea, opsize, src, NULL);
2505 /* This will be correct because loads sign extend. */
2506 gen_logic_cc(s, src, opsize);
2507 }
2508 }
2509
2510 DISAS_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); /* compute old Z */
2521
2522 /*
2523 * Perform subtract with borrow.
2524 * (X, N) = -(src + X);
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 * Compute signed-overflow for negation. The normal formula for
2536 * subtraction is (res ^ src) & (src ^ dest), but with dest==0
2537 * this simplifies to res & src.
2538 */
2539
2540 tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src);
2541
2542 /* Copy the rest of the results into place. */
2543 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
2544 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
2545
2546 set_cc_op(s, CC_OP_FLAGS);
2547
2548 /* result is in QREG_CC_N */
2549
2550 DEST_EA(env, insn, opsize, QREG_CC_N, &addr);
2551 }
2552
2553 DISAS_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
2567 DISAS_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
2578 DISAS_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
2586 DISAS_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
2603 DISAS_INSN(move_to_ccr)
2604 {
2605 gen_move_to_sr(env, s, insn, true);
2606 }
2607
2608 DISAS_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
2623 DISAS_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
2638 DISAS_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
2647 DISAS_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
2659 DISAS_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
2679 DISAS_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
2689 DISAS_INSN(pulse)
2690 {
2691 /* Implemented as a NOP. */
2692 }
2693
2694 DISAS_INSN(illegal)
2695 {
2696 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2697 }
2698
2699 DISAS_INSN(tas)
2700 {
2701 int mode = extract32(insn, 3, 3);
2702 int reg0 = REG(insn, 0);
2703
2704 if (mode == 0) {
2705 /* data register direct */
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: /* Indirect postincrement. */
2724 tcg_gen_addi_i32(AREG(insn, 0), addr, 1);
2725 break;
2726 case 4: /* Indirect predecrememnt. */
2727 tcg_gen_mov_i32(AREG(insn, 0), addr);
2728 break;
2729 }
2730 }
2731 }
2732
2733 DISAS_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 /* if Dl == Dh, 68040 returns low word */
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 /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */
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 /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */
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 * The upper 32 bits of the product are discarded, so
2789 * muls.l and mulu.l are functionally equivalent.
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
2796 static 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
2811 DISAS_INSN(link)
2812 {
2813 int16_t offset;
2814
2815 offset = read_im16(env, s);
2816 gen_link(s, insn, offset);
2817 }
2818
2819 DISAS_INSN(linkl)
2820 {
2821 int32_t offset;
2822
2823 offset = read_im32(env, s);
2824 gen_link(s, insn, offset);
2825 }
2826
2827 DISAS_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)
2842 DISAS_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
2853 DISAS_INSN(nop)
2854 {
2855 }
2856
2857 DISAS_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
2867 DISAS_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
2884 DISAS_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
2893 DISAS_INSN(jump)
2894 {
2895 TCGv tmp;
2896
2897 /*
2898 * Load the target address first to ensure correct exception
2899 * behavior.
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 /* jsr */
2908 gen_push(s, tcg_constant_i32(s->pc));
2909 }
2910 gen_jmp(s, tmp);
2911 }
2912
2913 DISAS_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 /* Operation on address register is always long. */
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 * Don't update condition codes if the destination is an
2939 * address register.
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
2961 DISAS_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 /* bsr */
2977 gen_push(s, tcg_constant_i32(s->pc));
2978 }
2979 if (op > 1) {
2980 /* Bcc */
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 /* Unconditional branch. */
2988 update_cc_op(s);
2989 gen_jmp_tb(s, 0, base + offset, s->base.pc_next);
2990 }
2991 }
2992
2993 DISAS_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
2999 DISAS_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
3015 DISAS_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
3038 DISAS_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
3048 static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3049 {
3050 TCGv tmp, zero;
3051
3052 gen_flush_flags(s); /* compute old Z */
3053
3054 /*
3055 * Perform subtract with borrow.
3056 * (X, N) = dest - (src + X);
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 /* Compute signed-overflow for subtract. */
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 /* Copy the rest of the results into place. */
3073 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3074 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3075
3076 set_cc_op(s, CC_OP_FLAGS);
3077
3078 /* result is in QREG_CC_N */
3079 }
3080
3081 DISAS_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
3097 DISAS_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
3120 DISAS_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
3134 DISAS_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
3146 DISAS_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
3162 DISAS_INSN(cmpm)
3163 {
3164 int opsize = insn_opsize(insn);
3165 TCGv src, dst;
3166
3167 /* Post-increment load (mode 3) from Ay. */
3168 src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize,
3169 NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3170 /* Post-increment load (mode 3) from Ax. */
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
3177 DISAS_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
3193 static 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
3201 DISAS_INSN(exg_dd)
3202 {
3203 /* exchange Dx and Dy */
3204 do_exg(DREG(insn, 9), DREG(insn, 0));
3205 }
3206
3207 DISAS_INSN(exg_aa)
3208 {
3209 /* exchange Ax and Ay */
3210 do_exg(AREG(insn, 9), AREG(insn, 0));
3211 }
3212
3213 DISAS_INSN(exg_da)
3214 {
3215 /* exchange Dx and Ay */
3216 do_exg(DREG(insn, 9), AREG(insn, 0));
3217 }
3218
3219 DISAS_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
3243 DISAS_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
3253 static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3254 {
3255 TCGv tmp, zero;
3256
3257 gen_flush_flags(s); /* compute old Z */
3258
3259 /*
3260 * Perform addition with carry.
3261 * (X, N) = src + dest + X;
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 /* Compute signed-overflow for addition. */
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 /* Copy the rest of the results into place. */
3277 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3278 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3279
3280 set_cc_op(s, CC_OP_FLAGS);
3281
3282 /* result is in QREG_CC_N */
3283 }
3284
3285 DISAS_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
3301 DISAS_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
3324 static 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 * Note that ColdFire always clears V (done above),
3343 * while M68000 sets if the most significant bit is changed at
3344 * any time during the shift operation.
3345 */
3346 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3347 /* if shift count >= bits, V is (reg != 0) */
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
3376 static 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 * Note that m68k truncates the shift count modulo 64, not 32.
3391 * In addition, a 64-bit shift makes it easy to find "the last
3392 * bit shifted out", for the carry flag.
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 /* Optimistically set V=0. Also used as a zero source below. */
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 /* Note that C=0 if shift count is 0, and we get that for free. */
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 /* X = C, but only if the shift count was non-zero. */
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 * M68000 sets V if the most significant bit is changed at
3421 * any time during the shift operation. Do this via creating
3422 * an extension of the sign bit, comparing, and discarding
3423 * the bits below the sign bit. I.e.
3424 * int64_t s = (intN_t)reg;
3425 * int64_t t = (int64_t)(intN_t)reg << count;
3426 * V = ((s ^ t) & (-1 << (bits - 1))) != 0
3427 */
3428 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3429 TCGv_i64 tt = tcg_constant_i64(32);
3430 /* if shift is greater than 32, use 32 */
3431 tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64);
3432 /* Sign extend the input to 64 bits; re-do the shift. */
3433 tcg_gen_ext_i32_i64(t64, reg);
3434 tcg_gen_shl_i64(s64, t64, s64);
3435 /* Clear all bits that are unchanged. */
3436 tcg_gen_xor_i64(t64, t64, s64);
3437 /* Ignore the bits below the sign bit. */
3438 tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
3439 /* If any bits remain set, we have overflow. */
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 /* Note that C=0 if shift count is 0, and we get that for free. */
3454 tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
3455
3456 /* X = C, but only if the shift count was non-zero. */
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 /* Write back the result. */
3464 gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3465 set_cc_op(s, CC_OP_FLAGS);
3466 }
3467
3468 DISAS_INSN(shift8_im)
3469 {
3470 shift_im(s, insn, OS_BYTE);
3471 }
3472
3473 DISAS_INSN(shift16_im)
3474 {
3475 shift_im(s, insn, OS_WORD);
3476 }
3477
3478 DISAS_INSN(shift_im)
3479 {
3480 shift_im(s, insn, OS_LONG);
3481 }
3482
3483 DISAS_INSN(shift8_reg)
3484 {
3485 shift_reg(s, insn, OS_BYTE);
3486 }
3487
3488 DISAS_INSN(shift16_reg)
3489 {
3490 shift_reg(s, insn, OS_WORD);
3491 }
3492
3493 DISAS_INSN(shift_reg)
3494 {
3495 shift_reg(s, insn, OS_LONG);
3496 }
3497
3498 DISAS_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 * Note that ColdFire always clears V,
3513 * while M68000 sets if the most significant bit is changed at
3514 * any time during the shift operation
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
3538 static void rotate(TCGv reg, TCGv shift, int left, int size)
3539 {
3540 switch (size) {
3541 case 8:
3542 /* Replicate the 8-bit input so that a 32-bit rotate works. */
3543 tcg_gen_ext8u_i32(reg, reg);
3544 tcg_gen_muli_i32(reg, reg, 0x01010101);
3545 goto do_long;
3546 case 16:
3547 /* Replicate the 16-bit input so that a 32-bit rotate works. */
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 /* compute flags */
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 /* QREG_CC_X is not affected */
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); /* always cleared */
3584 }
3585
3586 static 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 /* Result of rotate_x() is valid if 0 <= shift <= size */
3606 static 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); /* shl = shift */
3617 tcg_gen_movi_i32(shr, size + 1);
3618 tcg_gen_sub_i32(shr, shr, shift); /* shr = size + 1 - shift */
3619 tcg_gen_subi_i32(shx, shift, 1); /* shx = shift - 1 */
3620 /* shx = shx < 0 ? size : shx; */
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); /* shr = shift */
3625 tcg_gen_movi_i32(shl, size + 1);
3626 tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */
3627 tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */
3628 }
3629
3630 /* reg = (reg << shl) | (reg >> shr) | (x << shx); */
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 /* X = (reg >> size) & 1 */
3639
3640 X = tcg_temp_new();
3641 tcg_gen_extract_i32(X, reg, size, 1);
3642
3643 return X;
3644 }
3645
3646 /* Result of rotate32_x() is valid if 0 <= shift < 33 */
3647 static 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 /* create [reg:X:..] */
3663
3664 tcg_gen_shli_i32(lo, QREG_CC_X, 31);
3665 tcg_gen_concat_i32_i64(t0, lo, reg);
3666
3667 /* rotate */
3668
3669 tcg_gen_rotl_i64(t0, t0, shift64);
3670
3671 /* result is [reg:..:reg:X] */
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 /* create [..:X:reg] */
3679
3680 tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X);
3681
3682 tcg_gen_rotr_i64(t0, t0, shift64);
3683
3684 /* result is value: [X:reg:..:reg] */
3685
3686 tcg_gen_extr_i64_i32(lo, hi, t0);
3687
3688 /* extract X */
3689
3690 tcg_gen_shri_i32(X, hi, 31);
3691
3692 /* extract result */
3693
3694 tcg_gen_shli_i32(hi, hi, 1);
3695 }
3696 tcg_gen_or_i32(lo, lo, hi);
3697
3698 /* if shift == 0, register and X are not affected */
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
3707 DISAS_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
3729 DISAS_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
3754 DISAS_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
3778 DISAS_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 /* shift in [0..63] */
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 /* if shift == 0, clear C */
3795 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3796 t0, QREG_CC_V /* 0 */,
3797 QREG_CC_V /* 0 */, QREG_CC_C);
3798 } else {
3799 TCGv X;
3800 /* modulo 33 */
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
3809 DISAS_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 /* shift in [0..63] */
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 /* if shift == 0, clear C */
3826 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3827 t0, QREG_CC_V /* 0 */,
3828 QREG_CC_V /* 0 */, QREG_CC_C);
3829 } else {
3830 TCGv X;
3831 /* modulo 9 */
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
3841 DISAS_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 /* shift in [0..63] */
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 /* if shift == 0, clear C */
3858 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3859 t0, QREG_CC_V /* 0 */,
3860 QREG_CC_V /* 0 */, QREG_CC_C);
3861 } else {
3862 TCGv X;
3863 /* modulo 17 */
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
3873 DISAS_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
3893 DISAS_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); /* big bit-endian */
3901 int pos = 32 - ofs - len; /* little bit-endian */
3902 TCGv tmp = tcg_temp_new();
3903 TCGv shift;
3904
3905 /*
3906 * In general, we're going to rotate the field so that it's at the
3907 * top of the word and then right-shift by the complement of the
3908 * width to extend the field.
3909 */
3910 if (ext & 0x20) {
3911 /* Variable width. */
3912 if (ext & 0x800) {
3913 /* Variable offset. */
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 /* Immediate width. */
3931 if (ext & 0x800) {
3932 /* Variable offset */
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 * Immediate offset. If the field doesn't wrap around the
3940 * end of the word, rely on (s)extract completely.
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
3960 DISAS_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
3995 DISAS_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); /* big bit-endian */
4001 TCGv mask, tofs = NULL, tlen = NULL;
4002 bool is_bfffo = (insn & 0x0f00) == 0x0d00;
4003
4004 if ((ext & 0x820) == 0) {
4005 /* Immediate width and offset. */
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 /* Variable width */
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 /* Immediate width */
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 /* Variable offset */
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 /* Immediate offset (and variable width) */
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: /* bfchg */
4063 tcg_gen_eqv_i32(src, src, mask);
4064 break;
4065 case 0x0c00: /* bfclr */
4066 tcg_gen_and_i32(src, src, mask);
4067 break;
4068 case 0x0d00: /* bfffo */
4069 gen_helper_bfffo_reg(DREG(ext, 12), QREG_CC_N, tofs, tlen);
4070 break;
4071 case 0x0e00: /* bfset */
4072 tcg_gen_orc_i32(src, src, mask);
4073 break;
4074 case 0x0800: /* bftst */
4075 /* flags already set; no other work to do. */
4076 break;
4077 default:
4078 g_assert_not_reached();
4079 }
4080 }
4081
4082 DISAS_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: /* bfchg */
4107 gen_helper_bfchg_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4108 break;
4109 case 0x0c00: /* bfclr */
4110 gen_helper_bfclr_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4111 break;
4112 case 0x0d00: /* bfffo */
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: /* bfset */
4118 gen_helper_bfset_mem(QREG_CC_N, cpu_env, addr, ofs, len);
4119 break;
4120 case 0x0800: /* bftst */
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
4129 DISAS_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); /* big bit-endian */
4136 int pos = 32 - ofs - len; /* little bit-endian */
4137 TCGv tmp;
4138
4139 tmp = tcg_temp_new();
4140
4141 if (ext & 0x20) {
4142 /* Variable width */
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 /* Immediate width */
4148 tcg_gen_shli_i32(QREG_CC_N, src, 32 - len);
4149 }
4150 set_cc_op(s, CC_OP_LOGIC);
4151
4152 /* Immediate width and offset */
4153 if ((ext & 0x820) == 0) {
4154 /* Check for suitability for deposit. */
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 /* Variable width */
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 /* Immediate width (variable offset) */
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 /* Variable offset */
4186 tcg_gen_add_i32(rot, rot, DREG(ext, 6));
4187 } else {
4188 /* Immediate offset (variable width) */
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
4199 DISAS_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
4226 DISAS_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
4234 DISAS_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 /* fallthru */
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
4260 DISAS_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
4305 static 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
4326 DISAS_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 /* Ax can be Ay, so save Ay before incrementing Ax */
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
4346 DISAS_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 /* MOVE16 (xxx).L, (Ay) */
4356 m68k_copy_line(reg, addr, index);
4357 } else {
4358 /* MOVE16 (Ay), (xxx).L */
4359 m68k_copy_line(addr, reg, index);
4360 }
4361
4362 if (((insn >> 3) & 2) == 0) {
4363 /* (Ay)+ */
4364 tcg_gen_addi_i32(reg, reg, 16);
4365 }
4366 }
4367
4368 DISAS_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
4389 DISAS_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)
4402 DISAS_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 /* address register */
4421 reg = AREG(ext, 12);
4422 extend = 1;
4423 } else {
4424 /* data register */
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 /* from reg to ea */
4437 gen_store(s, opsize, addr, reg, DFC_INDEX(s));
4438 } else {
4439 /* from ea to reg */
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: /* Indirect postincrement. */
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: /* Indirect predecrememnt. */
4455 tcg_gen_mov_i32(AREG(insn, 0), addr);
4456 break;
4457 }
4458 }
4459
4460 DISAS_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
4470 DISAS_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
4480 DISAS_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
4490 DISAS_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
4500 DISAS_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
4516 DISAS_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
4525 DISAS_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
4546 DISAS_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
4572 DISAS_INSN(intouch)
4573 {
4574 if (IS_USER(s)) {
4575 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4576 return;
4577 }
4578 /* ICache fetch. Implement as no-op. */
4579 }
4580
4581 DISAS_INSN(cpushl)
4582 {
4583 if (IS_USER(s)) {
4584 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4585 return;
4586 }
4587 /* Cache push/invalidate. Implement as no-op. */
4588 }
4589
4590 DISAS_INSN(cpush)
4591 {
4592 if (IS_USER(s)) {
4593 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4594 return;
4595 }
4596 /* Cache push/invalidate. Implement as no-op. */
4597 }
4598
4599 DISAS_INSN(cinv)
4600 {
4601 if (IS_USER(s)) {
4602 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4603 return;
4604 }
4605 /* Invalidate cache line. Implement as no-op. */
4606 }
4607
4608 #if !defined(CONFIG_USER_ONLY)
4609 DISAS_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
4622 DISAS_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
4635 DISAS_INSN(wddata)
4636 {
4637 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4638 }
4639
4640 DISAS_INSN(wdebug)
4641 {
4642 if (IS_USER(s)) {
4643 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4644 return;
4645 }
4646 /* TODO: Implement wdebug. */
4647 cpu_abort(env_cpu(env), "WDEBUG not implemented");
4648 }
4649 #endif
4650
4651 DISAS_INSN(trap)
4652 {
4653 gen_exception(s, s->pc, EXCP_TRAP0 + (insn & 0xf));
4654 }
4655
4656 static 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 /* Jump over if !c. */
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
4679 DISAS_INSN(trapcc)
4680 {
4681 DisasCompare c;
4682
4683 /* Consume and discard the immediate operand. */
4684 switch (extract32(insn, 0, 3)) {
4685 case 2: /* trapcc.w */
4686 (void)read_im16(env, s);
4687 break;
4688 case 3: /* trapcc.l */
4689 (void)read_im32(env, s);
4690 break;
4691 case 4: /* trapcc (no operand) */
4692 break;
4693 default:
4694 /* trapcc registered with only valid opmodes */
4695 g_assert_not_reached();
4696 }
4697
4698 gen_cc_cond(&c, s, extract32(insn, 8, 4));
4699 do_trapcc(s, &c);
4700 }
4701
4702 DISAS_INSN(trapv)
4703 {
4704 DisasCompare c;
4705
4706 gen_cc_cond(&c, s, 9); /* V set */
4707 do_trapcc(s, &c);
4708 }
4709
4710 static 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
4725 static 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
4739 static 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
4749 static 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
4760 static 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: /* Dn */
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: /* An, only with FPIAR */
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: /* Immediate */
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 * mask:
4820 *
4821 * 0b100 Floating-Point Control Register
4822 * 0b010 Floating-Point Status Register
4823 * 0b001 Floating-Point Instruction Address Register
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
4856 static 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; /* FIXME */
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 /* Dynamic register list */
4879 tcg_gen_ext8u_i32(tmp, DREG(ext, 4));
4880 } else {
4881 /* Static register list */
4882 tcg_gen_movi_i32(tmp, ext & 0xff);
4883 }
4884
4885 if (!is_load && (mode & 2) == 0) {
4886 /*
4887 * predecrement addressing mode
4888 * only available to store register to memory
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 /* postincrement addressing mode */
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 * ??? FP exceptions are not implemented. Most exceptions are deferred until
4918 * immediately before the next FP instruction is executed.
4919 */
4920 DISAS_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 /* fmovecr */
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: /* fmove out */
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: /* fmove to control register. */
4953 case 5: /* fmove from control register. */
4954 gen_op_fmove_fcr(env, s, insn, ext);
4955 return;
4956 case 6: /* fmovem */
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 /* Source effective address. */
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 /* Source register. */
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: /* fmove */
4981 gen_fp_move(cpu_dest, cpu_src);
4982 break;
4983 case 0x40: /* fsmove */
4984 gen_helper_fsround(cpu_env, cpu_dest, cpu_src);
4985 break;
4986 case 0x44: /* fdmove */
4987 gen_helper_fdround(cpu_env, cpu_dest, cpu_src);
4988 break;
4989 case 1: /* fint */
4990 gen_helper_firound(cpu_env, cpu_dest, cpu_src);
4991 break;
4992 case 2: /* fsinh */
4993 gen_helper_fsinh(cpu_env, cpu_dest, cpu_src);
4994 break;
4995 case 3: /* fintrz */
4996 gen_helper_fitrunc(cpu_env, cpu_dest, cpu_src);
4997 break;
4998 case 4: /* fsqrt */
4999 gen_helper_fsqrt(cpu_env, cpu_dest, cpu_src);
5000 break;
5001 case 0x41: /* fssqrt */
5002 gen_helper_fssqrt(cpu_env, cpu_dest, cpu_src);
5003 break;
5004 case 0x45: /* fdsqrt */
5005 gen_helper_fdsqrt(cpu_env, cpu_dest, cpu_src);
5006 break;
5007 case 0x06: /* flognp1 */
5008 gen_helper_flognp1(cpu_env, cpu_dest, cpu_src);
5009 break;
5010 case 0x08: /* fetoxm1 */
5011 gen_helper_fetoxm1(cpu_env, cpu_dest, cpu_src);
5012 break;
5013 case 0x09: /* ftanh */
5014 gen_helper_ftanh(cpu_env, cpu_dest, cpu_src);
5015 break;
5016 case 0x0a: /* fatan */
5017 gen_helper_fatan(cpu_env, cpu_dest, cpu_src);
5018 break;
5019 case 0x0c: /* fasin */
5020 gen_helper_fasin(cpu_env, cpu_dest, cpu_src);
5021 break;
5022 case 0x0d: /* fatanh */
5023 gen_helper_fatanh(cpu_env, cpu_dest, cpu_src);
5024 break;
5025 case 0x0e: /* fsin */
5026 gen_helper_fsin(cpu_env, cpu_dest, cpu_src);
5027 break;
5028 case 0x0f: /* ftan */
5029 gen_helper_ftan(cpu_env, cpu_dest, cpu_src);
5030 break;
5031 case 0x10: /* fetox */
5032 gen_helper_fetox(cpu_env, cpu_dest, cpu_src);
5033 break;
5034 case 0x11: /* ftwotox */
5035 gen_helper_ftwotox(cpu_env, cpu_dest, cpu_src);
5036 break;
5037 case 0x12: /* ftentox */
5038 gen_helper_ftentox(cpu_env, cpu_dest, cpu_src);
5039 break;
5040 case 0x14: /* flogn */
5041 gen_helper_flogn(cpu_env, cpu_dest, cpu_src);
5042 break;
5043 case 0x15: /* flog10 */
5044 gen_helper_flog10(cpu_env, cpu_dest, cpu_src);
5045 break;
5046 case 0x16: /* flog2 */
5047 gen_helper_flog2(cpu_env, cpu_dest, cpu_src);
5048 break;
5049 case 0x18: /* fabs */
5050 gen_helper_fabs(cpu_env, cpu_dest, cpu_src);
5051 break;
5052 case 0x58: /* fsabs */
5053 gen_helper_fsabs(cpu_env, cpu_dest, cpu_src);
5054 break;
5055 case 0x5c: /* fdabs */
5056 gen_helper_fdabs(cpu_env, cpu_dest, cpu_src);
5057 break;
5058 case 0x19: /* fcosh */
5059 gen_helper_fcosh(cpu_env, cpu_dest, cpu_src);
5060 break;
5061 case 0x1a: /* fneg */
5062 gen_helper_fneg(cpu_env, cpu_dest, cpu_src);
5063 break;
5064 case 0x5a: /* fsneg */
5065 gen_helper_fsneg(cpu_env, cpu_dest, cpu_src);
5066 break;
5067 case 0x5e: /* fdneg */
5068 gen_helper_fdneg(cpu_env, cpu_dest, cpu_src);
5069 break;
5070 case 0x1c: /* facos */
5071 gen_helper_facos(cpu_env, cpu_dest, cpu_src);
5072 break;
5073 case 0x1d: /* fcos */
5074 gen_helper_fcos(cpu_env, cpu_dest, cpu_src);
5075 break;
5076 case 0x1e: /* fgetexp */
5077 gen_helper_fgetexp(cpu_env, cpu_dest, cpu_src);
5078 break;
5079 case 0x1f: /* fgetman */
5080 gen_helper_fgetman(cpu_env, cpu_dest, cpu_src);
5081 break;
5082 case 0x20: /* fdiv */
5083 gen_helper_fdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5084 break;
5085 case 0x60: /* fsdiv */
5086 gen_helper_fsdiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5087 break;
5088 case 0x64: /* fddiv */
5089 gen_helper_fddiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5090 break;
5091 case 0x21: /* fmod */
5092 gen_helper_fmod(cpu_env, cpu_dest, cpu_src, cpu_dest);
5093 break;
5094 case 0x22: /* fadd */
5095 gen_helper_fadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5096 break;
5097 case 0x62: /* fsadd */
5098 gen_helper_fsadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5099 break;
5100 case 0x66: /* fdadd */
5101 gen_helper_fdadd(cpu_env, cpu_dest, cpu_src, cpu_dest);
5102 break;
5103 case 0x23: /* fmul */
5104 gen_helper_fmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5105 break;
5106 case 0x63: /* fsmul */
5107 gen_helper_fsmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5108 break;
5109 case 0x67: /* fdmul */
5110 gen_helper_fdmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5111 break;
5112 case 0x24: /* fsgldiv */
5113 gen_helper_fsgldiv(cpu_env, cpu_dest, cpu_src, cpu_dest);
5114 break;
5115 case 0x25: /* frem */
5116 gen_helper_frem(cpu_env, cpu_dest, cpu_src, cpu_dest);
5117 break;
5118 case 0x26: /* fscale */
5119 gen_helper_fscale(cpu_env, cpu_dest, cpu_src, cpu_dest);
5120 break;
5121 case 0x27: /* fsglmul */
5122 gen_helper_fsglmul(cpu_env, cpu_dest, cpu_src, cpu_dest);
5123 break;
5124 case 0x28: /* fsub */
5125 gen_helper_fsub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5126 break;
5127 case 0x68: /* fssub */
5128 gen_helper_fssub(cpu_env, cpu_dest, cpu_src, cpu_dest);
5129 break;
5130 case 0x6c: /* fdsub */
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: /* fcmp */
5141 gen_helper_fcmp(cpu_env, cpu_src, cpu_dest);
5142 return;
5143 case 0x3a: /* ftst */
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;
5151 undef:
5152 /* FIXME: Is this right for offset addressing modes? */
5153 s->pc -= 2;
5154 disas_undef_fpu(env, s, insn);
5155 }
5156
5157 static void gen_fcc_cond(DisasCompare *c, DisasContext *s, int cond)
5158 {
5159 TCGv fpsr;
5160
5161 c->v2 = tcg_constant_i32(0);
5162 /* TODO: Raise BSUN exception. */
5163 fpsr = tcg_temp_new();
5164 gen_load_fcr(s, fpsr, M68K_FPSR);
5165 switch (cond) {
5166 case 0: /* False */
5167 case 16: /* Signaling False */
5168 c->v1 = c->v2;
5169 c->tcond = TCG_COND_NEVER;
5170 break;
5171 case 1: /* EQual Z */
5172 case 17: /* Signaling EQual Z */
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: /* Ordered Greater Than !(A || Z || N) */
5178 case 18: /* Greater Than !(A || Z || N) */
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: /* Ordered Greater than or Equal Z || !(A || N) */
5185 case 19: /* Greater than or Equal Z || !(A || N) */
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: /* Ordered Less Than !(!N || A || Z); */
5195 case 20: /* Less Than !(!N || A || Z); */
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: /* Ordered Less than or Equal Z || (N && !A) */
5202 case 21: /* Less than or Equal Z || (N && !A) */
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: /* Ordered Greater or Less than !(A || Z) */
5211 case 22: /* Greater or Less than !(A || Z) */
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: /* Ordered !A */
5217 case 23: /* Greater, Less or Equal !A */
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: /* Unordered A */
5223 case 24: /* Not Greater, Less or Equal A */
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: /* Unordered or Equal A || Z */
5229 case 25: /* Not Greater or Less then A || Z */
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: /* Unordered or Greater Than A || !(N || Z)) */
5235 case 26: /* Not Less or Equal A || !(N || Z)) */
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: /* Unordered or Greater or Equal A || Z || !N */
5245 case 27: /* Not Less Than A || Z || !N */
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: /* Unordered or Less Than A || (N && !Z) */
5252 case 28: /* Not Greater than or Equal A || (N && !Z) */
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: /* Unordered or Less or Equal A || Z || N */
5261 case 29: /* Not Greater Than A || Z || N */
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: /* Not Equal !Z */
5267 case 30: /* Signaling Not Equal !Z */
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: /* True */
5273 case 31: /* Signaling True */
5274 c->v1 = c->v2;
5275 c->tcond = TCG_COND_ALWAYS;
5276 break;
5277 }
5278 }
5279
5280 static 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
5289 DISAS_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
5309 DISAS_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
5327 DISAS_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 /* Consume and discard the immediate operand. */
5337 switch (extract32(insn, 0, 3)) {
5338 case 2: /* ftrapcc.w */
5339 (void)read_im16(env, s);
5340 break;
5341 case 3: /* ftrapcc.l */
5342 (void)read_im32(env, s);
5343 break;
5344 case 4: /* ftrapcc (no operand) */
5345 break;
5346 default:
5347 /* ftrapcc registered with only valid opmodes */
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)
5356 DISAS_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 /* FIXME: check the state frame */
5367 } else {
5368 disas_undef(env, s, insn);
5369 }
5370 }
5371
5372 DISAS_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 /* always write IDLE */
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
5389 static 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
5411 static 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
5417 DISAS_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 /* MAC with load. */
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 * Load the value now to ensure correct exception behavior.
5449 * Perform writeback after reading the MAC inputs.
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 /* Disabled because conditional branches clobber temporary vars. */
5466 if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
5467 /* Skip the multiply if we know we will ignore it. */
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 /* Word. */
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 /* Save the overflow flag from the multiply. */
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 /* Disabled because conditional branches clobber temporary vars. */
5507 if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
5508 /* Skip the accumulate if the value is already saturated. */
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 /* Disabled because conditional branches clobber temporary vars. */
5530 if (l1 != -1)
5531 gen_set_label(l1);
5532 #endif
5533
5534 if (dual) {
5535 /* Dual accumulate variant. */
5536 acc = (ext >> 2) & 3;
5537 /* Restore the overflow flag from the multiplier. */
5538 tcg_gen_mov_i32(QREG_MACSR, saved_flags);
5539 #if 0
5540 /* Disabled because conditional branches clobber temporary vars. */
5541 if ((s->env->macsr & MACSR_OMC) != 0) {
5542 /* Skip the accumulate if the value is already saturated. */
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 /* Disabled because conditional branches clobber temporary vars. */
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 * FIXME: Should address writeback happen with the masked or
5573 * unmasked value?
5574 */
5575 switch ((insn >> 3) & 7) {
5576 case 3: /* Post-increment. */
5577 tcg_gen_addi_i32(AREG(insn, 0), addr, 4);
5578 break;
5579 case 4: /* Pre-decrement. */
5580 tcg_gen_mov_i32(AREG(insn, 0), addr);
5581 }
5582 }
5583 }
5584
5585 DISAS_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
5609 DISAS_INSN(move_mac)
5610 {
5611 /* FIXME: This can be done without a helper. */
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
5621 DISAS_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
5629 DISAS_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
5636 DISAS_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
5648 DISAS_INSN(macsr_to_ccr)
5649 {
5650 TCGv tmp = tcg_temp_new();
5651
5652 /* Note that X and C are always cleared. */
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
5658 DISAS_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
5679 DISAS_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
5687 DISAS_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
5694 DISAS_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
5708 static disas_proc opcode_table[65536];
5709
5710 static void
5711 register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
5712 {
5713 int i;
5714 int from;
5715 int to;
5716
5717 /* Sanity check. All set bits must be included in the mask. */
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 * This could probably be cleverer. For now just optimize the case where
5726 * the top bits are known.
5727 */
5728 /* Find the first zero bit in the mask. */
5729 i = 0x8000;
5730 while ((i & mask) != 0)
5731 i >>= 1;
5732 /* Iterate over all combinations of this and lower bits. */
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 * Register m68k opcode handlers. Order is important.
5747 * Later insn override earlier ones.
5748 */
5749 void register_m68k_insns (CPUM68KState *env)
5750 {
5751 /*
5752 * Build the opcode table only once to avoid
5753 * multithreading issues.
5754 */
5755 if (opcode_table[0] != NULL) {
5756 return;
5757 }
5758
5759 /*
5760 * use BASE() for instruction available
5761 * for CF_ISA_A and M68000.
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); /* Scc.B Dx */
5877 INSN(scc, 50c0, f0c0, M68K); /* Scc.B <EA> */
5878 INSN(dbcc, 50c8, f0f8, M68K);
5879 INSN(trapcc, 50fa, f0fe, TRAPCC); /* opmode 010, 011 */
5880 INSN(trapcc, 50fc, f0ff, TRAPCC); /* opmode 100 */
5881 INSN(trapcc, 51fa, fffe, CF_ISA_A); /* TPF (trapf) opmode 010, 011 */
5882 INSN(trapcc, 51fc, ffff, CF_ISA_A); /* TPF (trapf) opmode 100 */
5883
5884 /* Branch instructions. */
5885 BASE(branch, 6000, f000);
5886 /* Disable long branch instructions, then add back the ones we want. */
5887 BASE(undef, 60ff, f0ff); /* All long branches. */
5888 INSN(branch, 60ff, f0ff, CF_ISA_B);
5889 INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */
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); /* cmp.b */
5922 INSN(cmp, b040, f1c0, CF_ISA_B); /* cmp.w */
5923 INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */
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); /* bfextu & bfexts */
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); /* bfchg */
5966 INSN(bfop_reg, eac0, fff8, BITFIELD); /* bfchg */
5967 INSN(bfop_mem, ecc0, ffc0, BITFIELD); /* bfclr */
5968 INSN(bfop_reg, ecc0, fff8, BITFIELD); /* bfclr */
5969 INSN(bfop_mem, edc0, ffc0, BITFIELD); /* bfffo */
5970 INSN(bfop_reg, edc0, fff8, BITFIELD); /* bfffo */
5971 INSN(bfop_mem, eec0, ffc0, BITFIELD); /* bfset */
5972 INSN(bfop_reg, eec0, fff8, BITFIELD); /* bfset */
5973 INSN(bfop_mem, e8c0, ffc0, BITFIELD); /* bftst */
5974 INSN(bfop_reg, e8c0, fff8, BITFIELD); /* bftst */
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); /* opmode 010, 011 */
5981 INSN(ftrapcc, f27c, ffff, FPU); /* opmode 100 */
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
6002 static 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 /* This value will always be filled in properly before m68k_tr_tb_stop. */
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 /* If architectural single step active, limit to 1 */
6018 if (dc->ss_active) {
6019 dc->base.max_insns = 1;
6020 }
6021 }
6022
6023 static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
6024 {
6025 }
6026
6027 static 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
6033 static 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 * Stop translation when the next insn might touch a new page.
6048 * This ensures that prefetch aborts at the right place.
6049 *
6050 * We cannot determine the size of the next insn without
6051 * completely decoding it. However, the maximum insn size
6052 * is 32 bytes, so end if we do not have that much remaining.
6053 * This may produce several small TBs at the end of each page,
6054 * but they will all be linked with goto_tb.
6055 *
6056 * ??? ColdFire maximum is 4 bytes; MC68000's maximum is also
6057 * smaller than MC68020's.
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
6068 static 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 /* We updated CC_OP and PC in gen_jmp/gen_jmp_im. */
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 * We updated CC_OP and PC in gen_exit_tb, but also modified
6090 * other state that may require returning to the main loop.
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
6103 static 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
6110 static 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
6119 void 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
6126 static 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
6138 void 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 /* !CONFIG_USER_ONLY */
6208 }