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