master
c 6,214 lines 164 KB
Raw
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 "exec/translation-block.h"
24 #include "exec/target_page.h"
25 #include "tcg/tcg-op.h"
26 #include "qemu/log.h"
27 #include "qemu/qemu-print.h"
28 #include "exec/translator.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "exec/log.h"
32 #include "fpu/softfloat.h"
33 #include "semihosting/semihost.h"
34
35 #define HELPER_H "helper.h"
36 #include "exec/helper-info.c.inc"
37 #undef HELPER_H
38
39 //#define DEBUG_DISPATCH 1
40
41 #define DEFO32(name, offset) static TCGv QREG_##name;
42 #define DEFO64(name, offset) static TCGv_i64 QREG_##name;
43 #include "qregs.h.inc"
44 #undef DEFO32
45 #undef DEFO64
46
47 static char cpu_reg_names[2 * 8 * 3 + 5 * 4];
48 static TCGv cpu_dregs[8];
49 static TCGv cpu_aregs[8];
50 static TCGv_i64 cpu_macc[4];
51
52 #define REG(insn, pos) (((insn) >> (pos)) & 7)
53 #define DREG(insn, pos) cpu_dregs[REG(insn, pos)]
54 #define AREG(insn, pos) get_areg(s, REG(insn, pos))
55 #define MACREG(acc) cpu_macc[acc]
56 #define QREG_SP get_areg(s, 7)
57
58 static TCGv NULL_QREG;
59 #define IS_NULL_QREG(t) (t == NULL_QREG)
60 /* Used to distinguish stores from bad addressing modes. */
61 static TCGv store_dummy;
62
63 void m68k_tcg_init(void)
64 {
65 char *p;
66 int i;
67
68 #define DEFO32(name, offset) \
69 QREG_##name = tcg_global_mem_new_i32(tcg_env, \
70 offsetof(CPUM68KState, offset), #name);
71 #define DEFO64(name, offset) \
72 QREG_##name = tcg_global_mem_new_i64(tcg_env, \
73 offsetof(CPUM68KState, offset), #name);
74 #include "qregs.h.inc"
75 #undef DEFO32
76 #undef DEFO64
77
78 p = cpu_reg_names;
79 for (i = 0; i < 8; i++) {
80 sprintf(p, "D%d", i);
81 cpu_dregs[i] = tcg_global_mem_new(tcg_env,
82 offsetof(CPUM68KState, dregs[i]), p);
83 p += 3;
84 sprintf(p, "A%d", i);
85 cpu_aregs[i] = tcg_global_mem_new(tcg_env,
86 offsetof(CPUM68KState, aregs[i]), p);
87 p += 3;
88 }
89 for (i = 0; i < 4; i++) {
90 sprintf(p, "ACC%d", i);
91 cpu_macc[i] = tcg_global_mem_new_i64(tcg_env,
92 offsetof(CPUM68KState, macc[i]), p);
93 p += 5;
94 }
95
96 NULL_QREG = tcg_global_mem_new(tcg_env, -4, "NULL");
97 store_dummy = tcg_global_mem_new(tcg_env, -8, "NULL");
98 }
99
100 /* internal defines */
101 typedef struct DisasContext {
102 DisasContextBase base;
103 CPUM68KState *env;
104 target_ulong pc;
105 target_ulong pc_prev;
106 CCOp cc_op; /* Current CC operation */
107 int cc_op_synced;
108 TCGv_i64 mactmp;
109 int done_mac;
110 int writeback_mask;
111 TCGv writeback[8];
112 bool ss_active;
113 } DisasContext;
114
115 static TCGv get_areg(DisasContext *s, unsigned regno)
116 {
117 if (s->writeback_mask & (1 << regno)) {
118 return s->writeback[regno];
119 } else {
120 return cpu_aregs[regno];
121 }
122 }
123
124 static void delay_set_areg(DisasContext *s, unsigned regno,
125 TCGv val, bool give_temp)
126 {
127 if (s->writeback_mask & (1 << regno)) {
128 if (give_temp) {
129 s->writeback[regno] = val;
130 } else {
131 tcg_gen_mov_i32(s->writeback[regno], val);
132 }
133 } else {
134 s->writeback_mask |= 1 << regno;
135 if (give_temp) {
136 s->writeback[regno] = val;
137 } else {
138 TCGv tmp = tcg_temp_new();
139 s->writeback[regno] = tmp;
140 tcg_gen_mov_i32(tmp, val);
141 }
142 }
143 }
144
145 static void do_writebacks(DisasContext *s)
146 {
147 unsigned mask = s->writeback_mask;
148 if (mask) {
149 s->writeback_mask = 0;
150 do {
151 unsigned regno = ctz32(mask);
152 tcg_gen_mov_i32(cpu_aregs[regno], s->writeback[regno]);
153 mask &= mask - 1;
154 } while (mask);
155 }
156 }
157
158 /* is_jmp field values */
159 #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
160 #define DISAS_EXIT DISAS_TARGET_1 /* cpu state was modified dynamically */
161
162 #if defined(CONFIG_USER_ONLY)
163 #define IS_USER(s) 1
164 #else
165 #define IS_USER(s) (!(s->base.tb->flags & TB_FLAGS_MSR_S))
166 #define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \
167 MMU_KERNEL_IDX : MMU_USER_IDX)
168 #define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \
169 MMU_KERNEL_IDX : MMU_USER_IDX)
170 #endif
171
172 typedef void (*disas_proc)(CPUM68KState *env, DisasContext *s, uint16_t insn);
173
174 #ifdef DEBUG_DISPATCH
175 #define DISAS_INSN(name) \
176 static void real_disas_##name(CPUM68KState *env, DisasContext *s, \
177 uint16_t insn); \
178 static void disas_##name(CPUM68KState *env, DisasContext *s, \
179 uint16_t insn) \
180 { \
181 qemu_log("Dispatch " #name "\n"); \
182 real_disas_##name(env, s, insn); \
183 } \
184 static void real_disas_##name(CPUM68KState *env, DisasContext *s, \
185 uint16_t insn)
186 #else
187 #define DISAS_INSN(name) \
188 static void disas_##name(CPUM68KState *env, DisasContext *s, \
189 uint16_t insn)
190 #endif
191
192 static const uint8_t cc_op_live[CC_OP_NB] = {
193 [CC_OP_DYNAMIC] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
194 [CC_OP_FLAGS] = CCF_C | CCF_V | CCF_Z | CCF_N | CCF_X,
195 [CC_OP_ADDB ... CC_OP_ADDL] = CCF_X | CCF_N | CCF_V,
196 [CC_OP_SUBB ... CC_OP_SUBL] = CCF_X | CCF_N | CCF_V,
197 [CC_OP_CMPB ... CC_OP_CMPL] = CCF_X | CCF_N | CCF_V,
198 [CC_OP_LOGIC] = CCF_X | CCF_N
199 };
200
201 static void set_cc_op(DisasContext *s, CCOp op)
202 {
203 CCOp old_op = s->cc_op;
204 int dead;
205
206 if (old_op == op) {
207 return;
208 }
209 s->cc_op = op;
210 s->cc_op_synced = 0;
211
212 /*
213 * Discard CC computation that will no longer be used.
214 * Note that X and N are never dead.
215 */
216 dead = cc_op_live[old_op] & ~cc_op_live[op];
217 if (dead & CCF_C) {
218 tcg_gen_discard_i32(QREG_CC_C);
219 }
220 if (dead & CCF_Z) {
221 tcg_gen_discard_i32(QREG_CC_Z);
222 }
223 if (dead & CCF_V) {
224 tcg_gen_discard_i32(QREG_CC_V);
225 }
226 }
227
228 /* Update the CPU env CC_OP state. */
229 static void update_cc_op(DisasContext *s)
230 {
231 if (!s->cc_op_synced) {
232 s->cc_op_synced = 1;
233 tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
234 }
235 }
236
237 /* Generate a jump to an immediate address. */
238 static void gen_jmp_im(DisasContext *s, uint32_t dest)
239 {
240 update_cc_op(s);
241 tcg_gen_movi_i32(QREG_PC, dest);
242 s->base.is_jmp = DISAS_JUMP;
243 }
244
245 /* Generate a jump to the address in qreg DEST. */
246 static void gen_jmp(DisasContext *s, TCGv dest)
247 {
248 update_cc_op(s);
249 tcg_gen_mov_i32(QREG_PC, dest);
250 s->base.is_jmp = DISAS_JUMP;
251 }
252
253 static void gen_raise_exception(int nr)
254 {
255 gen_helper_raise_exception(tcg_env, tcg_constant_i32(nr));
256 }
257
258 static void gen_raise_exception_format2(DisasContext *s, int nr,
259 target_ulong this_pc)
260 {
261 /*
262 * Pass the address of the insn to the exception handler,
263 * for recording in the Format $2 (6-word) stack frame.
264 * Re-use mmu.ar for the purpose, since that's only valid
265 * after tlb_fill.
266 */
267 tcg_gen_st_i32(tcg_constant_i32(this_pc), tcg_env,
268 offsetof(CPUM68KState, mmu.ar));
269 gen_raise_exception(nr);
270 s->base.is_jmp = DISAS_NORETURN;
271 }
272
273 static void gen_exception(DisasContext *s, uint32_t dest, int nr)
274 {
275 update_cc_op(s);
276 tcg_gen_movi_i32(QREG_PC, dest);
277
278 gen_raise_exception(nr);
279
280 s->base.is_jmp = DISAS_NORETURN;
281 }
282
283 static inline void gen_addr_fault(DisasContext *s)
284 {
285 gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
286 }
287
288 /*
289 * Generate a load from the specified address. Narrow values are
290 * sign extended to full register width.
291 */
292 static inline TCGv gen_load(DisasContext *s, int opsize, TCGv addr,
293 int sign, int index)
294 {
295 TCGv tmp = tcg_temp_new_i32();
296
297 switch (opsize) {
298 case OS_BYTE:
299 case OS_WORD:
300 case OS_LONG:
301 tcg_gen_qemu_ld_tl(tmp, addr, index,
302 opsize | (sign ? MO_SIGN : 0) | MO_TE);
303 break;
304 default:
305 g_assert_not_reached();
306 }
307 return tmp;
308 }
309
310 /* Generate a store. */
311 static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val,
312 int index)
313 {
314 switch (opsize) {
315 case OS_BYTE:
316 case OS_WORD:
317 case OS_LONG:
318 tcg_gen_qemu_st_tl(val, addr, index, opsize | MO_TE);
319 break;
320 default:
321 g_assert_not_reached();
322 }
323 }
324
325 typedef enum {
326 EA_STORE,
327 EA_LOADU,
328 EA_LOADS
329 } ea_what;
330
331 /*
332 * Generate an unsigned load if VAL is 0 a signed load if val is -1,
333 * otherwise generate a store.
334 */
335 static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
336 ea_what what, int index)
337 {
338 if (what == EA_STORE) {
339 gen_store(s, opsize, addr, val, index);
340 return store_dummy;
341 } else {
342 return gen_load(s, opsize, addr, what == EA_LOADS, index);
343 }
344 }
345
346 /* Read a 16-bit immediate constant */
347 static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
348 {
349 uint16_t im;
350 im = translator_lduw_end(env, &s->base, s->pc, MO_BE);
351 s->pc += 2;
352 return im;
353 }
354
355 /* Read an 8-bit immediate constant */
356 static inline uint8_t read_im8(CPUM68KState *env, DisasContext *s)
357 {
358 return read_im16(env, s);
359 }
360
361 /* Read a 32-bit immediate constant. */
362 static inline uint32_t read_im32(CPUM68KState *env, DisasContext *s)
363 {
364 uint32_t im;
365 im = read_im16(env, s) << 16;
366 im |= 0xffff & read_im16(env, s);
367 return im;
368 }
369
370 /* Read a 64-bit immediate constant. */
371 static inline uint64_t read_im64(CPUM68KState *env, DisasContext *s)
372 {
373 uint64_t im;
374 im = (uint64_t)read_im32(env, s) << 32;
375 im |= (uint64_t)read_im32(env, s);
376 return im;
377 }
378
379 /* Calculate and address index. */
380 static TCGv gen_addr_index(DisasContext *s, uint16_t ext, TCGv tmp)
381 {
382 TCGv add;
383 int scale;
384
385 add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
386 if ((ext & 0x800) == 0) {
387 tcg_gen_ext16s_i32(tmp, add);
388 add = tmp;
389 }
390 scale = (ext >> 9) & 3;
391 if (scale != 0) {
392 tcg_gen_shli_i32(tmp, add, scale);
393 add = tmp;
394 }
395 return add;
396 }
397
398 /*
399 * Handle a base + index + displacement effective address.
400 * A NULL_QREG base means pc-relative.
401 */
402 static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base)
403 {
404 uint32_t offset;
405 uint16_t ext;
406 TCGv add;
407 TCGv tmp;
408 uint32_t bd, od;
409
410 offset = s->pc;
411 ext = read_im16(env, s);
412
413 if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
414 return NULL_QREG;
415
416 if (m68k_feature(s->env, M68K_FEATURE_M68K) &&
417 !m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) {
418 ext &= ~(3 << 9);
419 }
420
421 if (ext & 0x100) {
422 /* full extension word format */
423 if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
424 return NULL_QREG;
425
426 if ((ext & 0x30) > 0x10) {
427 /* base displacement */
428 if ((ext & 0x30) == 0x20) {
429 bd = (int16_t)read_im16(env, s);
430 } else {
431 bd = read_im32(env, s);
432 }
433 } else {
434 bd = 0;
435 }
436 tmp = tcg_temp_new();
437 if ((ext & 0x44) == 0) {
438 /* pre-index */
439 add = gen_addr_index(s, ext, tmp);
440 } else {
441 add = NULL_QREG;
442 }
443 if ((ext & 0x80) == 0) {
444 /* base not suppressed */
445 if (IS_NULL_QREG(base)) {
446 base = tcg_constant_i32(offset + bd);
447 bd = 0;
448 }
449 if (!IS_NULL_QREG(add)) {
450 tcg_gen_add_i32(tmp, add, base);
451 add = tmp;
452 } else {
453 add = base;
454 }
455 }
456 if (!IS_NULL_QREG(add)) {
457 if (bd != 0) {
458 tcg_gen_addi_i32(tmp, add, bd);
459 add = tmp;
460 }
461 } else {
462 add = tcg_constant_i32(bd);
463 }
464 if ((ext & 3) != 0) {
465 /* memory indirect */
466 base = gen_load(s, OS_LONG, add, 0, IS_USER(s));
467 if ((ext & 0x44) == 4) {
468 add = gen_addr_index(s, ext, tmp);
469 tcg_gen_add_i32(tmp, add, base);
470 add = tmp;
471 } else {
472 add = base;
473 }
474 if ((ext & 3) > 1) {
475 /* outer displacement */
476 if ((ext & 3) == 2) {
477 od = (int16_t)read_im16(env, s);
478 } else {
479 od = read_im32(env, s);
480 }
481 } else {
482 od = 0;
483 }
484 if (od != 0) {
485 tcg_gen_addi_i32(tmp, add, od);
486 add = tmp;
487 }
488 }
489 } else {
490 /* brief extension word format */
491 tmp = tcg_temp_new();
492 add = gen_addr_index(s, ext, tmp);
493 if (!IS_NULL_QREG(base)) {
494 tcg_gen_add_i32(tmp, add, base);
495 if ((int8_t)ext)
496 tcg_gen_addi_i32(tmp, tmp, (int8_t)ext);
497 } else {
498 tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext);
499 }
500 add = tmp;
501 }
502 return add;
503 }
504
505 /* Sign or zero extend a value. */
506
507 static inline void gen_ext(TCGv res, TCGv val, int opsize, int sign)
508 {
509 switch (opsize) {
510 case OS_BYTE:
511 case OS_WORD:
512 case OS_LONG:
513 tcg_gen_ext_i32(res, val, opsize | (sign ? MO_SIGN : 0));
514 break;
515 default:
516 g_assert_not_reached();
517 }
518 }
519
520 /* Evaluate all the CC flags. */
521
522 static void gen_flush_flags(DisasContext *s)
523 {
524 TCGv t0, t1;
525
526 switch (s->cc_op) {
527 case CC_OP_FLAGS:
528 return;
529
530 case CC_OP_ADDB:
531 case CC_OP_ADDW:
532 case CC_OP_ADDL:
533 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
534 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
535 /* Compute signed overflow for addition. */
536 t0 = tcg_temp_new();
537 t1 = tcg_temp_new();
538 tcg_gen_sub_i32(t0, QREG_CC_N, QREG_CC_V);
539 gen_ext(t0, t0, s->cc_op - CC_OP_ADDB, 1);
540 tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V);
541 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
542 tcg_gen_andc_i32(QREG_CC_V, t1, QREG_CC_V);
543 break;
544
545 case CC_OP_SUBB:
546 case CC_OP_SUBW:
547 case CC_OP_SUBL:
548 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
549 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
550 /* Compute signed overflow for subtraction. */
551 t0 = tcg_temp_new();
552 t1 = tcg_temp_new();
553 tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V);
554 gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1);
555 tcg_gen_xor_i32(t1, QREG_CC_N, t0);
556 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0);
557 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1);
558 break;
559
560 case CC_OP_CMPB:
561 case CC_OP_CMPW:
562 case CC_OP_CMPL:
563 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_C, QREG_CC_N, QREG_CC_V);
564 tcg_gen_sub_i32(QREG_CC_Z, QREG_CC_N, QREG_CC_V);
565 gen_ext(QREG_CC_Z, QREG_CC_Z, s->cc_op - CC_OP_CMPB, 1);
566 /* Compute signed overflow for subtraction. */
567 t0 = tcg_temp_new();
568 tcg_gen_xor_i32(t0, QREG_CC_Z, QREG_CC_N);
569 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, QREG_CC_N);
570 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t0);
571 tcg_gen_mov_i32(QREG_CC_N, QREG_CC_Z);
572 break;
573
574 case CC_OP_LOGIC:
575 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
576 tcg_gen_movi_i32(QREG_CC_C, 0);
577 tcg_gen_movi_i32(QREG_CC_V, 0);
578 break;
579
580 case CC_OP_DYNAMIC:
581 gen_helper_flush_flags(tcg_env, QREG_CC_OP);
582 s->cc_op_synced = 1;
583 break;
584
585 default:
586 gen_helper_flush_flags(tcg_env, tcg_constant_i32(s->cc_op));
587 s->cc_op_synced = 1;
588 break;
589 }
590
591 /* Note that flush_flags also assigned to env->cc_op. */
592 s->cc_op = CC_OP_FLAGS;
593 }
594
595 static inline TCGv gen_extend(DisasContext *s, TCGv val, int opsize, int sign)
596 {
597 TCGv tmp;
598
599 if (opsize == OS_LONG) {
600 tmp = val;
601 } else {
602 tmp = tcg_temp_new();
603 gen_ext(tmp, val, opsize, sign);
604 }
605
606 return tmp;
607 }
608
609 static void gen_logic_cc(DisasContext *s, TCGv val, int opsize)
610 {
611 gen_ext(QREG_CC_N, val, opsize, 1);
612 set_cc_op(s, CC_OP_LOGIC);
613 }
614
615 static void gen_update_cc_cmp(DisasContext *s, TCGv dest, TCGv src, int opsize)
616 {
617 tcg_gen_mov_i32(QREG_CC_N, dest);
618 tcg_gen_mov_i32(QREG_CC_V, src);
619 set_cc_op(s, CC_OP_CMPB + opsize);
620 }
621
622 static void gen_update_cc_add(TCGv dest, TCGv src, int opsize)
623 {
624 gen_ext(QREG_CC_N, dest, opsize, 1);
625 tcg_gen_mov_i32(QREG_CC_V, src);
626 }
627
628 static inline int opsize_bytes(int opsize)
629 {
630 switch (opsize) {
631 case OS_BYTE: return 1;
632 case OS_WORD: return 2;
633 case OS_LONG: return 4;
634 case OS_SINGLE: return 4;
635 case OS_DOUBLE: return 8;
636 case OS_EXTENDED: return 12;
637 case OS_PACKED: return 12;
638 default:
639 g_assert_not_reached();
640 }
641 }
642
643 static inline int insn_opsize(int insn)
644 {
645 switch ((insn >> 6) & 3) {
646 case 0: return OS_BYTE;
647 case 1: return OS_WORD;
648 case 2: return OS_LONG;
649 default:
650 g_assert_not_reached();
651 }
652 }
653
654 static inline int ext_opsize(int ext, int pos)
655 {
656 switch ((ext >> pos) & 7) {
657 case 0: return OS_LONG;
658 case 1: return OS_SINGLE;
659 case 2: return OS_EXTENDED;
660 case 3: return OS_PACKED;
661 case 4: return OS_WORD;
662 case 5: return OS_DOUBLE;
663 case 6: return OS_BYTE;
664 default:
665 g_assert_not_reached();
666 }
667 }
668
669 /*
670 * Assign value to a register. If the width is less than the register width
671 * only the low part of the register is set.
672 */
673 static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
674 {
675 switch (opsize) {
676 case OS_BYTE:
677 tcg_gen_deposit_i32(reg, reg, val, 0, 8);
678 break;
679 case OS_WORD:
680 tcg_gen_deposit_i32(reg, reg, val, 0, 16);
681 break;
682 case OS_LONG:
683 case OS_SINGLE:
684 tcg_gen_mov_i32(reg, val);
685 break;
686 default:
687 g_assert_not_reached();
688 }
689 }
690
691 /*
692 * Generate code for an "effective address". Does not adjust the base
693 * register for autoincrement addressing modes.
694 */
695 static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
696 int mode, int reg0, int opsize)
697 {
698 TCGv reg;
699 TCGv tmp;
700 uint16_t ext;
701 uint32_t offset;
702
703 switch (mode) {
704 case 0: /* Data register direct. */
705 case 1: /* Address register direct. */
706 return NULL_QREG;
707 case 3: /* Indirect postincrement. */
708 if (opsize == OS_UNSIZED) {
709 return NULL_QREG;
710 }
711 /* fallthru */
712 case 2: /* Indirect register */
713 tmp = tcg_temp_new();
714 tcg_gen_mov_i32(tmp, get_areg(s, reg0));
715 return tmp;
716 case 4: /* Indirect predecrememnt. */
717 if (opsize == OS_UNSIZED) {
718 return NULL_QREG;
719 }
720 reg = get_areg(s, reg0);
721 tmp = tcg_temp_new();
722 if (reg0 == 7 && opsize == OS_BYTE &&
723 m68k_feature(s->env, M68K_FEATURE_M68K)) {
724 tcg_gen_subi_i32(tmp, reg, 2);
725 } else {
726 tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
727 }
728 return tmp;
729 case 5: /* Indirect displacement. */
730 reg = get_areg(s, reg0);
731 tmp = tcg_temp_new();
732 ext = read_im16(env, s);
733 tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
734 return tmp;
735 case 6: /* Indirect index + displacement. */
736 reg = get_areg(s, reg0);
737 return gen_lea_indexed(env, s, reg);
738 case 7: /* Other */
739 switch (reg0) {
740 case 0: /* Absolute short. */
741 offset = (int16_t)read_im16(env, s);
742 break;
743 case 1: /* Absolute long. */
744 offset = read_im32(env, s);
745 break;
746 case 2: /* pc displacement */
747 offset = s->pc;
748 offset += (int16_t)read_im16(env, s);
749 break;
750 case 3: /* pc index+displacement. */
751 return gen_lea_indexed(env, s, NULL_QREG);
752 case 4: /* Immediate. */
753 default:
754 return NULL_QREG;
755 }
756 tmp = tcg_temp_new();
757 tcg_gen_movi_i32(tmp, offset);
758 return tmp;
759 }
760 /* Should never happen. */
761 return NULL_QREG;
762 }
763
764 static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
765 int opsize)
766 {
767 int mode = extract32(insn, 3, 3);
768 int reg0 = REG(insn, 0);
769 return gen_lea_mode(env, s, mode, reg0, opsize);
770 }
771
772 /*
773 * Generate code to load/store a value from/into an EA. If WHAT > 0 this is
774 * a write otherwise it is a read (0 == sign extend, -1 == zero extend).
775 * ADDRP is non-null for readwrite operands.
776 */
777 static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
778 int opsize, TCGv val, TCGv *addrp, ea_what what,
779 int index)
780 {
781 TCGv reg, tmp, result;
782 int32_t offset;
783
784 switch (mode) {
785 case 0: /* Data register direct. */
786 reg = cpu_dregs[reg0];
787 if (what == EA_STORE) {
788 gen_partset_reg(opsize, reg, val);
789 return store_dummy;
790 } else {
791 return gen_extend(s, reg, opsize, what == EA_LOADS);
792 }
793 case 1: /* Address register direct. */
794 reg = get_areg(s, reg0);
795 if (what == EA_STORE) {
796 tcg_gen_mov_i32(reg, val);
797 return store_dummy;
798 } else {
799 return gen_extend(s, reg, opsize, what == EA_LOADS);
800 }
801 case 2: /* Indirect register */
802 reg = get_areg(s, reg0);
803 return gen_ldst(s, opsize, reg, val, what, index);
804 case 3: /* Indirect postincrement. */
805 reg = get_areg(s, reg0);
806 result = gen_ldst(s, opsize, reg, val, what, index);
807 if (what == EA_STORE || !addrp) {
808 tmp = tcg_temp_new();
809 if (reg0 == 7 && opsize == OS_BYTE &&
810 m68k_feature(s->env, M68K_FEATURE_M68K)) {
811 tcg_gen_addi_i32(tmp, reg, 2);
812 } else {
813 tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize));
814 }
815 delay_set_areg(s, reg0, tmp, true);
816 }
817 return result;
818 case 4: /* Indirect predecrememnt. */
819 if (addrp && what == EA_STORE) {
820 tmp = *addrp;
821 } else {
822 tmp = gen_lea_mode(env, s, mode, reg0, opsize);
823 if (IS_NULL_QREG(tmp)) {
824 return tmp;
825 }
826 if (addrp) {
827 *addrp = tmp;
828 }
829 }
830 result = gen_ldst(s, opsize, tmp, val, what, index);
831 if (what == EA_STORE || !addrp) {
832 delay_set_areg(s, reg0, tmp, false);
833 }
834 return result;
835 case 5: /* Indirect displacement. */
836 case 6: /* Indirect index + displacement. */
837 do_indirect:
838 if (addrp && what == EA_STORE) {
839 tmp = *addrp;
840 } else {
841 tmp = gen_lea_mode(env, s, mode, reg0, opsize);
842 if (IS_NULL_QREG(tmp)) {
843 return tmp;
844 }
845 if (addrp) {
846 *addrp = tmp;
847 }
848 }
849 return gen_ldst(s, opsize, tmp, val, what, index);
850 case 7: /* Other */
851 switch (reg0) {
852 case 0: /* Absolute short. */
853 case 1: /* Absolute long. */
854 case 2: /* pc displacement */
855 case 3: /* pc index+displacement. */
856 goto do_indirect;
857 case 4: /* Immediate. */
858 /* Sign extend values for consistency. */
859 switch (opsize) {
860 case OS_BYTE:
861 if (what == EA_LOADS) {
862 offset = (int8_t)read_im8(env, s);
863 } else {
864 offset = read_im8(env, s);
865 }
866 break;
867 case OS_WORD:
868 if (what == EA_LOADS) {
869 offset = (int16_t)read_im16(env, s);
870 } else {
871 offset = read_im16(env, s);
872 }
873 break;
874 case OS_LONG:
875 offset = read_im32(env, s);
876 break;
877 default:
878 g_assert_not_reached();
879 }
880 return tcg_constant_i32(offset);
881 default:
882 return NULL_QREG;
883 }
884 }
885 /* Should never happen. */
886 return NULL_QREG;
887 }
888
889 static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
890 int opsize, TCGv val, TCGv *addrp, ea_what what, int index)
891 {
892 int mode = extract32(insn, 3, 3);
893 int reg0 = REG(insn, 0);
894 return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what, index);
895 }
896
897 static TCGv_ptr gen_fp_ptr(int freg)
898 {
899 TCGv_ptr fp = tcg_temp_new_ptr();
900 tcg_gen_addi_ptr(fp, tcg_env, offsetof(CPUM68KState, fregs[freg]));
901 return fp;
902 }
903
904 static TCGv_ptr gen_fp_result_ptr(void)
905 {
906 TCGv_ptr fp = tcg_temp_new_ptr();
907 tcg_gen_addi_ptr(fp, tcg_env, offsetof(CPUM68KState, fp_result));
908 return fp;
909 }
910
911 static void gen_fp_move(TCGv_ptr dest, TCGv_ptr src)
912 {
913 TCGv t32;
914 TCGv_i64 t64;
915
916 t32 = tcg_temp_new();
917 tcg_gen_ld16u_i32(t32, src, offsetof(FPReg, l.upper));
918 tcg_gen_st16_i32(t32, dest, offsetof(FPReg, l.upper));
919
920 t64 = tcg_temp_new_i64();
921 tcg_gen_ld_i64(t64, src, offsetof(FPReg, l.lower));
922 tcg_gen_st_i64(t64, dest, offsetof(FPReg, l.lower));
923 }
924
925 static void gen_load_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
926 int index)
927 {
928 TCGv tmp;
929 TCGv_i64 t64;
930
931 t64 = tcg_temp_new_i64();
932 tmp = tcg_temp_new();
933 switch (opsize) {
934 case OS_BYTE:
935 case OS_WORD:
936 case OS_LONG:
937 tcg_gen_qemu_ld_tl(tmp, addr, index, opsize | MO_SIGN | MO_TE);
938 gen_helper_exts32(tcg_env, fp, tmp);
939 break;
940 case OS_SINGLE:
941 tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL);
942 gen_helper_extf32(tcg_env, fp, tmp);
943 break;
944 case OS_DOUBLE:
945 tcg_gen_qemu_ld_i64(t64, addr, index, MO_TEUQ);
946 gen_helper_extf64(tcg_env, fp, t64);
947 break;
948 case OS_EXTENDED:
949 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
950 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
951 break;
952 }
953 tcg_gen_qemu_ld_i32(tmp, addr, index, MO_TEUL);
954 tcg_gen_shri_i32(tmp, tmp, 16);
955 tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
956 tcg_gen_addi_i32(tmp, addr, 4);
957 tcg_gen_qemu_ld_i64(t64, tmp, index, MO_TEUQ);
958 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
959 break;
960 case OS_PACKED:
961 /*
962 * unimplemented data type on 68040/ColdFire
963 * FIXME if needed for another FPU
964 */
965 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
966 break;
967 default:
968 g_assert_not_reached();
969 }
970 }
971
972 static void gen_store_fp(DisasContext *s, int opsize, TCGv addr, TCGv_ptr fp,
973 int index)
974 {
975 TCGv tmp;
976 TCGv_i64 t64;
977
978 t64 = tcg_temp_new_i64();
979 tmp = tcg_temp_new();
980 switch (opsize) {
981 case OS_BYTE:
982 case OS_WORD:
983 case OS_LONG:
984 gen_helper_reds32(tmp, tcg_env, fp);
985 tcg_gen_qemu_st_tl(tmp, addr, index, opsize | MO_TE);
986 break;
987 case OS_SINGLE:
988 gen_helper_redf32(tmp, tcg_env, fp);
989 tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
990 break;
991 case OS_DOUBLE:
992 gen_helper_redf64(t64, tcg_env, fp);
993 tcg_gen_qemu_st_i64(t64, addr, index, MO_TEUQ);
994 break;
995 case OS_EXTENDED:
996 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
997 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
998 break;
999 }
1000 tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
1001 tcg_gen_shli_i32(tmp, tmp, 16);
1002 tcg_gen_qemu_st_i32(tmp, addr, index, MO_TEUL);
1003 tcg_gen_addi_i32(tmp, addr, 4);
1004 tcg_gen_ld_i64(t64, fp, offsetof(FPReg, l.lower));
1005 tcg_gen_qemu_st_i64(t64, tmp, index, MO_TEUQ);
1006 break;
1007 case OS_PACKED:
1008 /*
1009 * unimplemented data type on 68040/ColdFire
1010 * FIXME if needed for another FPU
1011 */
1012 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1013 break;
1014 default:
1015 g_assert_not_reached();
1016 }
1017 }
1018
1019 static void gen_ldst_fp(DisasContext *s, int opsize, TCGv addr,
1020 TCGv_ptr fp, ea_what what, int index)
1021 {
1022 if (what == EA_STORE) {
1023 gen_store_fp(s, opsize, addr, fp, index);
1024 } else {
1025 gen_load_fp(s, opsize, addr, fp, index);
1026 }
1027 }
1028
1029 static int gen_ea_mode_fp(CPUM68KState *env, DisasContext *s, int mode,
1030 int reg0, int opsize, TCGv_ptr fp, ea_what what,
1031 int index)
1032 {
1033 TCGv reg, addr, tmp;
1034 TCGv_i64 t64;
1035
1036 switch (mode) {
1037 case 0: /* Data register direct. */
1038 reg = cpu_dregs[reg0];
1039 if (what == EA_STORE) {
1040 switch (opsize) {
1041 case OS_BYTE:
1042 case OS_WORD:
1043 case OS_LONG:
1044 gen_helper_reds32(reg, tcg_env, fp);
1045 break;
1046 case OS_SINGLE:
1047 gen_helper_redf32(reg, tcg_env, fp);
1048 break;
1049 default:
1050 g_assert_not_reached();
1051 }
1052 } else {
1053 tmp = tcg_temp_new();
1054 switch (opsize) {
1055 case OS_BYTE:
1056 case OS_WORD:
1057 case OS_LONG:
1058 tcg_gen_ext_i32(tmp, reg, opsize | MO_SIGN);
1059 gen_helper_exts32(tcg_env, fp, tmp);
1060 break;
1061 case OS_SINGLE:
1062 gen_helper_extf32(tcg_env, fp, reg);
1063 break;
1064 default:
1065 g_assert_not_reached();
1066 }
1067 }
1068 return 0;
1069 case 1: /* Address register direct. */
1070 return -1;
1071 case 2: /* Indirect register */
1072 addr = get_areg(s, reg0);
1073 gen_ldst_fp(s, opsize, addr, fp, what, index);
1074 return 0;
1075 case 3: /* Indirect postincrement. */
1076 addr = cpu_aregs[reg0];
1077 gen_ldst_fp(s, opsize, addr, fp, what, index);
1078 tcg_gen_addi_i32(addr, addr, opsize_bytes(opsize));
1079 return 0;
1080 case 4: /* Indirect predecrememnt. */
1081 addr = gen_lea_mode(env, s, mode, reg0, opsize);
1082 if (IS_NULL_QREG(addr)) {
1083 return -1;
1084 }
1085 gen_ldst_fp(s, opsize, addr, fp, what, index);
1086 tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1087 return 0;
1088 case 5: /* Indirect displacement. */
1089 case 6: /* Indirect index + displacement. */
1090 do_indirect:
1091 addr = gen_lea_mode(env, s, mode, reg0, opsize);
1092 if (IS_NULL_QREG(addr)) {
1093 return -1;
1094 }
1095 gen_ldst_fp(s, opsize, addr, fp, what, index);
1096 return 0;
1097 case 7: /* Other */
1098 switch (reg0) {
1099 case 0: /* Absolute short. */
1100 case 1: /* Absolute long. */
1101 case 2: /* pc displacement */
1102 case 3: /* pc index+displacement. */
1103 goto do_indirect;
1104 case 4: /* Immediate. */
1105 if (what == EA_STORE) {
1106 return -1;
1107 }
1108 switch (opsize) {
1109 case OS_BYTE:
1110 tmp = tcg_constant_i32((int8_t)read_im8(env, s));
1111 gen_helper_exts32(tcg_env, fp, tmp);
1112 break;
1113 case OS_WORD:
1114 tmp = tcg_constant_i32((int16_t)read_im16(env, s));
1115 gen_helper_exts32(tcg_env, fp, tmp);
1116 break;
1117 case OS_LONG:
1118 tmp = tcg_constant_i32(read_im32(env, s));
1119 gen_helper_exts32(tcg_env, fp, tmp);
1120 break;
1121 case OS_SINGLE:
1122 tmp = tcg_constant_i32(read_im32(env, s));
1123 gen_helper_extf32(tcg_env, fp, tmp);
1124 break;
1125 case OS_DOUBLE:
1126 t64 = tcg_constant_i64(read_im64(env, s));
1127 gen_helper_extf64(tcg_env, fp, t64);
1128 break;
1129 case OS_EXTENDED:
1130 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
1131 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1132 break;
1133 }
1134 tmp = tcg_constant_i32(read_im32(env, s) >> 16);
1135 tcg_gen_st16_i32(tmp, fp, offsetof(FPReg, l.upper));
1136 t64 = tcg_constant_i64(read_im64(env, s));
1137 tcg_gen_st_i64(t64, fp, offsetof(FPReg, l.lower));
1138 break;
1139 case OS_PACKED:
1140 /*
1141 * unimplemented data type on 68040/ColdFire
1142 * FIXME if needed for another FPU
1143 */
1144 gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
1145 break;
1146 default:
1147 g_assert_not_reached();
1148 }
1149 return 0;
1150 default:
1151 return -1;
1152 }
1153 }
1154 return -1;
1155 }
1156
1157 static int gen_ea_fp(CPUM68KState *env, DisasContext *s, uint16_t insn,
1158 int opsize, TCGv_ptr fp, ea_what what, int index)
1159 {
1160 int mode = extract32(insn, 3, 3);
1161 int reg0 = REG(insn, 0);
1162 return gen_ea_mode_fp(env, s, mode, reg0, opsize, fp, what, index);
1163 }
1164
1165 typedef struct {
1166 TCGCond tcond;
1167 TCGv v1;
1168 TCGv v2;
1169 } DisasCompare;
1170
1171 static void gen_cc_cond(DisasCompare *c, DisasContext *s, int cond)
1172 {
1173 TCGv tmp, tmp2;
1174 TCGCond tcond;
1175 CCOp op = s->cc_op;
1176
1177 /* The CC_OP_CMP form can handle most normal comparisons directly. */
1178 if (op == CC_OP_CMPB || op == CC_OP_CMPW || op == CC_OP_CMPL) {
1179 c->v1 = QREG_CC_N;
1180 c->v2 = QREG_CC_V;
1181 switch (cond) {
1182 case 2: /* HI */
1183 case 3: /* LS */
1184 tcond = TCG_COND_LEU;
1185 goto done;
1186 case 4: /* CC */
1187 case 5: /* CS */
1188 tcond = TCG_COND_LTU;
1189 goto done;
1190 case 6: /* NE */
1191 case 7: /* EQ */
1192 tcond = TCG_COND_EQ;
1193 goto done;
1194 case 10: /* PL */
1195 case 11: /* MI */
1196 c->v2 = tcg_constant_i32(0);
1197 c->v1 = tmp = tcg_temp_new();
1198 tcg_gen_sub_i32(tmp, QREG_CC_N, QREG_CC_V);
1199 gen_ext(tmp, tmp, op - CC_OP_CMPB, 1);
1200 /* fallthru */
1201 case 12: /* GE */
1202 case 13: /* LT */
1203 tcond = TCG_COND_LT;
1204 goto done;
1205 case 14: /* GT */
1206 case 15: /* LE */
1207 tcond = TCG_COND_LE;
1208 goto done;
1209 }
1210 }
1211
1212 c->v2 = tcg_constant_i32(0);
1213
1214 switch (cond) {
1215 case 0: /* T */
1216 case 1: /* F */
1217 c->v1 = c->v2;
1218 tcond = TCG_COND_NEVER;
1219 goto done;
1220 case 14: /* GT (!(Z || (N ^ V))) */
1221 case 15: /* LE (Z || (N ^ V)) */
1222 /*
1223 * Logic operations clear V, which simplifies LE to (Z || N),
1224 * and since Z and N are co-located, this becomes a normal
1225 * comparison vs N.
1226 */
1227 if (op == CC_OP_LOGIC) {
1228 c->v1 = QREG_CC_N;
1229 tcond = TCG_COND_LE;
1230 goto done;
1231 }
1232 break;
1233 case 12: /* GE (!(N ^ V)) */
1234 case 13: /* LT (N ^ V) */
1235 /* Logic operations clear V, which simplifies this to N. */
1236 if (op != CC_OP_LOGIC) {
1237 break;
1238 }
1239 /* fallthru */
1240 case 10: /* PL (!N) */
1241 case 11: /* MI (N) */
1242 /* Several cases represent N normally. */
1243 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1244 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1245 op == CC_OP_LOGIC) {
1246 c->v1 = QREG_CC_N;
1247 tcond = TCG_COND_LT;
1248 goto done;
1249 }
1250 break;
1251 case 6: /* NE (!Z) */
1252 case 7: /* EQ (Z) */
1253 /* Some cases fold Z into N. */
1254 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1255 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL ||
1256 op == CC_OP_LOGIC) {
1257 tcond = TCG_COND_EQ;
1258 c->v1 = QREG_CC_N;
1259 goto done;
1260 }
1261 break;
1262 case 4: /* CC (!C) */
1263 case 5: /* CS (C) */
1264 /* Some cases fold C into X. */
1265 if (op == CC_OP_ADDB || op == CC_OP_ADDW || op == CC_OP_ADDL ||
1266 op == CC_OP_SUBB || op == CC_OP_SUBW || op == CC_OP_SUBL) {
1267 tcond = TCG_COND_NE;
1268 c->v1 = QREG_CC_X;
1269 goto done;
1270 }
1271 /* fallthru */
1272 case 8: /* VC (!V) */
1273 case 9: /* VS (V) */
1274 /* Logic operations clear V and C. */
1275 if (op == CC_OP_LOGIC) {
1276 tcond = TCG_COND_NEVER;
1277 c->v1 = c->v2;
1278 goto done;
1279 }
1280 break;
1281 }
1282
1283 /* Otherwise, flush flag state to CC_OP_FLAGS. */
1284 gen_flush_flags(s);
1285
1286 switch (cond) {
1287 case 0: /* T */
1288 case 1: /* F */
1289 default:
1290 /* Invalid, or handled above. */
1291 abort();
1292 case 2: /* HI (!C && !Z) -> !(C || Z)*/
1293 case 3: /* LS (C || Z) */
1294 c->v1 = tmp = tcg_temp_new();
1295 tcg_gen_setcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1296 tcg_gen_or_i32(tmp, tmp, QREG_CC_C);
1297 tcond = TCG_COND_NE;
1298 break;
1299 case 4: /* CC (!C) */
1300 case 5: /* CS (C) */
1301 c->v1 = QREG_CC_C;
1302 tcond = TCG_COND_NE;
1303 break;
1304 case 6: /* NE (!Z) */
1305 case 7: /* EQ (Z) */
1306 c->v1 = QREG_CC_Z;
1307 tcond = TCG_COND_EQ;
1308 break;
1309 case 8: /* VC (!V) */
1310 case 9: /* VS (V) */
1311 c->v1 = QREG_CC_V;
1312 tcond = TCG_COND_LT;
1313 break;
1314 case 10: /* PL (!N) */
1315 case 11: /* MI (N) */
1316 c->v1 = QREG_CC_N;
1317 tcond = TCG_COND_LT;
1318 break;
1319 case 12: /* GE (!(N ^ V)) */
1320 case 13: /* LT (N ^ V) */
1321 c->v1 = tmp = tcg_temp_new();
1322 tcg_gen_xor_i32(tmp, QREG_CC_N, QREG_CC_V);
1323 tcond = TCG_COND_LT;
1324 break;
1325 case 14: /* GT (!(Z || (N ^ V))) */
1326 case 15: /* LE (Z || (N ^ V)) */
1327 c->v1 = tmp = tcg_temp_new();
1328 tcg_gen_negsetcond_i32(TCG_COND_EQ, tmp, QREG_CC_Z, c->v2);
1329 tmp2 = tcg_temp_new();
1330 tcg_gen_xor_i32(tmp2, QREG_CC_N, QREG_CC_V);
1331 tcg_gen_or_i32(tmp, tmp, tmp2);
1332 tcond = TCG_COND_LT;
1333 break;
1334 }
1335
1336 done:
1337 if ((cond & 1) == 0) {
1338 tcond = tcg_invert_cond(tcond);
1339 }
1340 c->tcond = tcond;
1341 }
1342
1343 static void gen_jmpcc(DisasContext *s, int cond, TCGLabel *l1)
1344 {
1345 DisasCompare c;
1346
1347 gen_cc_cond(&c, s, cond);
1348 update_cc_op(s);
1349 tcg_gen_brcond_i32(c.tcond, c.v1, c.v2, l1);
1350 }
1351
1352 /* Force a TB lookup after an instruction that changes the CPU state. */
1353 static void gen_exit_tb(DisasContext *s)
1354 {
1355 update_cc_op(s);
1356 tcg_gen_movi_i32(QREG_PC, s->pc);
1357 s->base.is_jmp = DISAS_EXIT;
1358 }
1359
1360 #define SRC_EA(env, result, opsize, op_sign, addrp) do { \
1361 result = gen_ea(env, s, insn, opsize, NULL_QREG, addrp, \
1362 op_sign ? EA_LOADS : EA_LOADU, IS_USER(s)); \
1363 if (IS_NULL_QREG(result)) { \
1364 gen_addr_fault(s); \
1365 return; \
1366 } \
1367 } while (0)
1368
1369 #define DEST_EA(env, insn, opsize, val, addrp) do { \
1370 TCGv ea_result = gen_ea(env, s, insn, opsize, val, addrp, \
1371 EA_STORE, IS_USER(s)); \
1372 if (IS_NULL_QREG(ea_result)) { \
1373 gen_addr_fault(s); \
1374 return; \
1375 } \
1376 } while (0)
1377
1378 /* Generate a jump to an immediate address. */
1379 static void gen_jmp_tb(DisasContext *s, int n, target_ulong dest,
1380 target_ulong src)
1381 {
1382 if (unlikely(s->ss_active)) {
1383 update_cc_op(s);
1384 tcg_gen_movi_i32(QREG_PC, dest);
1385 gen_raise_exception_format2(s, EXCP_TRACE, src);
1386 } else if (translator_use_goto_tb(&s->base, dest)) {
1387 tcg_gen_goto_tb(n);
1388 tcg_gen_movi_i32(QREG_PC, dest);
1389 tcg_gen_exit_tb(s->base.tb, n);
1390 } else {
1391 gen_jmp_im(s, dest);
1392 tcg_gen_exit_tb(NULL, 0);
1393 }
1394 s->base.is_jmp = DISAS_NORETURN;
1395 }
1396
1397 #ifndef CONFIG_USER_ONLY
1398 static bool semihosting_test(DisasContext *s)
1399 {
1400 uint32_t test;
1401
1402 if (!semihosting_enabled(IS_USER(s))) {
1403 return false;
1404 }
1405
1406 /*
1407 * "The semihosting instruction is immediately preceded by a
1408 * nop aligned to a 4-byte boundary..."
1409 * The preceding 2-byte (aligned) nop plus the 2-byte halt/bkpt
1410 * means that we have advanced 4 bytes from the required nop.
1411 */
1412 if (s->pc % 4 != 0) {
1413 return false;
1414 }
1415 test = translator_lduw_end(s->env, &s->base, s->pc - 4, MO_BE);
1416 if (test != 0x4e71) {
1417 return false;
1418 }
1419 /* "... and followed by an invalid sentinel instruction movec %sp,0." */
1420 test = translator_ldl_end(s->env, &s->base, s->pc, MO_BE);
1421 if (test != 0x4e7bf000) {
1422 return false;
1423 }
1424
1425 /* Consume the sentinel. */
1426 s->pc += 4;
1427 return true;
1428 }
1429 #endif /* !CONFIG_USER_ONLY */
1430
1431 DISAS_INSN(scc)
1432 {
1433 DisasCompare c;
1434 int cond;
1435 TCGv tmp;
1436
1437 cond = (insn >> 8) & 0xf;
1438 gen_cc_cond(&c, s, cond);
1439
1440 tmp = tcg_temp_new();
1441 tcg_gen_negsetcond_i32(c.tcond, tmp, c.v1, c.v2);
1442
1443 DEST_EA(env, insn, OS_BYTE, tmp, NULL);
1444 }
1445
1446 DISAS_INSN(dbcc)
1447 {
1448 TCGLabel *l1;
1449 TCGv reg;
1450 TCGv tmp;
1451 int16_t offset;
1452 uint32_t base;
1453
1454 reg = DREG(insn, 0);
1455 base = s->pc;
1456 offset = (int16_t)read_im16(env, s);
1457 l1 = gen_new_label();
1458 gen_jmpcc(s, (insn >> 8) & 0xf, l1);
1459
1460 tmp = tcg_temp_new();
1461 tcg_gen_ext16s_i32(tmp, reg);
1462 tcg_gen_addi_i32(tmp, tmp, -1);
1463 gen_partset_reg(OS_WORD, reg, tmp);
1464 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, -1, l1);
1465 gen_jmp_tb(s, 1, base + offset, s->base.pc_next);
1466 gen_set_label(l1);
1467 gen_jmp_tb(s, 0, s->pc, s->base.pc_next);
1468 }
1469
1470 DISAS_INSN(undef_mac)
1471 {
1472 gen_exception(s, s->base.pc_next, EXCP_LINEA);
1473 }
1474
1475 DISAS_INSN(undef_fpu)
1476 {
1477 gen_exception(s, s->base.pc_next, EXCP_LINEF);
1478 }
1479
1480 DISAS_INSN(undef)
1481 {
1482 /*
1483 * ??? This is both instructions that are as yet unimplemented
1484 * for the 680x0 series, as well as those that are implemented
1485 * but actually illegal for CPU32 or pre-68020.
1486 */
1487 qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %" VADDR_PRIx "\n",
1488 insn, s->base.pc_next);
1489 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1490 }
1491
1492 DISAS_INSN(mulw)
1493 {
1494 TCGv reg;
1495 TCGv tmp;
1496 TCGv src;
1497 int sign;
1498
1499 sign = (insn & 0x100) != 0;
1500 reg = DREG(insn, 9);
1501 tmp = tcg_temp_new();
1502 if (sign)
1503 tcg_gen_ext16s_i32(tmp, reg);
1504 else
1505 tcg_gen_ext16u_i32(tmp, reg);
1506 SRC_EA(env, src, OS_WORD, sign, NULL);
1507 tcg_gen_mul_i32(tmp, tmp, src);
1508 tcg_gen_mov_i32(reg, tmp);
1509 gen_logic_cc(s, tmp, OS_LONG);
1510 }
1511
1512 DISAS_INSN(divw)
1513 {
1514 int sign;
1515 TCGv src;
1516 TCGv destr;
1517 TCGv ilen;
1518
1519 /* divX.w <EA>,Dn 32/16 -> 16r:16q */
1520
1521 sign = (insn & 0x100) != 0;
1522
1523 /* dest.l / src.w */
1524
1525 SRC_EA(env, src, OS_WORD, sign, NULL);
1526 destr = tcg_constant_i32(REG(insn, 9));
1527 ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1528 if (sign) {
1529 gen_helper_divsw(tcg_env, destr, src, ilen);
1530 } else {
1531 gen_helper_divuw(tcg_env, destr, src, ilen);
1532 }
1533
1534 set_cc_op(s, CC_OP_FLAGS);
1535 }
1536
1537 DISAS_INSN(divl)
1538 {
1539 TCGv num, reg, den, ilen;
1540 int sign;
1541 uint16_t ext;
1542
1543 ext = read_im16(env, s);
1544
1545 sign = (ext & 0x0800) != 0;
1546
1547 if (ext & 0x400) {
1548 if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
1549 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
1550 return;
1551 }
1552
1553 /* divX.l <EA>, Dr:Dq 64/32 -> 32r:32q */
1554
1555 SRC_EA(env, den, OS_LONG, 0, NULL);
1556 num = tcg_constant_i32(REG(ext, 12));
1557 reg = tcg_constant_i32(REG(ext, 0));
1558 ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1559 if (sign) {
1560 gen_helper_divsll(tcg_env, num, reg, den, ilen);
1561 } else {
1562 gen_helper_divull(tcg_env, num, reg, den, ilen);
1563 }
1564 set_cc_op(s, CC_OP_FLAGS);
1565 return;
1566 }
1567
1568 /* divX.l <EA>, Dq 32/32 -> 32q */
1569 /* divXl.l <EA>, Dr:Dq 32/32 -> 32r:32q */
1570
1571 SRC_EA(env, den, OS_LONG, 0, NULL);
1572 num = tcg_constant_i32(REG(ext, 12));
1573 reg = tcg_constant_i32(REG(ext, 0));
1574 ilen = tcg_constant_i32(s->pc - s->base.pc_next);
1575 if (sign) {
1576 gen_helper_divsl(tcg_env, num, reg, den, ilen);
1577 } else {
1578 gen_helper_divul(tcg_env, num, reg, den, ilen);
1579 }
1580
1581 set_cc_op(s, CC_OP_FLAGS);
1582 }
1583
1584 static void bcd_add(TCGv dest, TCGv src)
1585 {
1586 TCGv t0, t1;
1587
1588 /*
1589 * dest10 = dest10 + src10 + X
1590 *
1591 * t1 = src
1592 * t2 = t1 + 0x066
1593 * t3 = t2 + dest + X
1594 * t4 = t2 ^ dest
1595 * t5 = t3 ^ t4
1596 * t6 = ~t5 & 0x110
1597 * t7 = (t6 >> 2) | (t6 >> 3)
1598 * return t3 - t7
1599 */
1600
1601 /*
1602 * t1 = (src + 0x066) + dest + X
1603 * = result with some possible exceeding 0x6
1604 */
1605
1606 t0 = tcg_temp_new();
1607 tcg_gen_addi_i32(t0, src, 0x066);
1608
1609 t1 = tcg_temp_new();
1610 tcg_gen_add_i32(t1, t0, dest);
1611 tcg_gen_add_i32(t1, t1, QREG_CC_X);
1612
1613 /* we will remove exceeding 0x6 where there is no carry */
1614
1615 /*
1616 * t0 = (src + 0x0066) ^ dest
1617 * = t1 without carries
1618 */
1619
1620 tcg_gen_xor_i32(t0, t0, dest);
1621
1622 /*
1623 * extract the carries
1624 * t0 = t0 ^ t1
1625 * = only the carries
1626 */
1627
1628 tcg_gen_xor_i32(t0, t0, t1);
1629
1630 /*
1631 * generate 0x1 where there is no carry
1632 * and for each 0x10, generate a 0x6
1633 */
1634
1635 tcg_gen_shri_i32(t0, t0, 3);
1636 tcg_gen_not_i32(t0, t0);
1637 tcg_gen_andi_i32(t0, t0, 0x22);
1638 tcg_gen_add_i32(dest, t0, t0);
1639 tcg_gen_add_i32(dest, dest, t0);
1640
1641 /*
1642 * remove the exceeding 0x6
1643 * for digits that have not generated a carry
1644 */
1645
1646 tcg_gen_sub_i32(dest, t1, dest);
1647 }
1648
1649 static void bcd_sub(TCGv dest, TCGv src)
1650 {
1651 TCGv t0, t1, t2;
1652
1653 /*
1654 * dest10 = dest10 - src10 - X
1655 * = bcd_add(dest + 1 - X, 0x199 - src)
1656 */
1657
1658 /* t0 = 0x066 + (0x199 - src) */
1659
1660 t0 = tcg_temp_new();
1661 tcg_gen_subfi_i32(t0, 0x1ff, src);
1662
1663 /* t1 = t0 + dest + 1 - X*/
1664
1665 t1 = tcg_temp_new();
1666 tcg_gen_add_i32(t1, t0, dest);
1667 tcg_gen_addi_i32(t1, t1, 1);
1668 tcg_gen_sub_i32(t1, t1, QREG_CC_X);
1669
1670 /* t2 = t0 ^ dest */
1671
1672 t2 = tcg_temp_new();
1673 tcg_gen_xor_i32(t2, t0, dest);
1674
1675 /* t0 = t1 ^ t2 */
1676
1677 tcg_gen_xor_i32(t0, t1, t2);
1678
1679 /*
1680 * t2 = ~t0 & 0x110
1681 * t0 = (t2 >> 2) | (t2 >> 3)
1682 *
1683 * to fit on 8bit operands, changed in:
1684 *
1685 * t2 = ~(t0 >> 3) & 0x22
1686 * t0 = t2 + t2
1687 * t0 = t0 + t2
1688 */
1689
1690 tcg_gen_shri_i32(t2, t0, 3);
1691 tcg_gen_not_i32(t2, t2);
1692 tcg_gen_andi_i32(t2, t2, 0x22);
1693 tcg_gen_add_i32(t0, t2, t2);
1694 tcg_gen_add_i32(t0, t0, t2);
1695
1696 /* return t1 - t0 */
1697
1698 tcg_gen_sub_i32(dest, t1, t0);
1699 }
1700
1701 static void bcd_flags(TCGv val)
1702 {
1703 tcg_gen_andi_i32(QREG_CC_C, val, 0x0ff);
1704 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_C);
1705
1706 tcg_gen_extract_i32(QREG_CC_C, val, 8, 1);
1707
1708 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
1709 }
1710
1711 DISAS_INSN(abcd_reg)
1712 {
1713 TCGv src;
1714 TCGv dest;
1715
1716 gen_flush_flags(s); /* !Z is sticky */
1717
1718 src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1719 dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1720 bcd_add(dest, src);
1721 gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1722
1723 bcd_flags(dest);
1724 }
1725
1726 DISAS_INSN(abcd_mem)
1727 {
1728 TCGv src, dest, addr;
1729
1730 gen_flush_flags(s); /* !Z is sticky */
1731
1732 /* Indirect pre-decrement load (mode 4) */
1733
1734 src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1735 NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1736 dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1737 NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1738
1739 bcd_add(dest, src);
1740
1741 gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1742 EA_STORE, IS_USER(s));
1743
1744 bcd_flags(dest);
1745 }
1746
1747 DISAS_INSN(sbcd_reg)
1748 {
1749 TCGv src, dest;
1750
1751 gen_flush_flags(s); /* !Z is sticky */
1752
1753 src = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
1754 dest = gen_extend(s, DREG(insn, 9), OS_BYTE, 0);
1755
1756 bcd_sub(dest, src);
1757
1758 gen_partset_reg(OS_BYTE, DREG(insn, 9), dest);
1759
1760 bcd_flags(dest);
1761 }
1762
1763 DISAS_INSN(sbcd_mem)
1764 {
1765 TCGv src, dest, addr;
1766
1767 gen_flush_flags(s); /* !Z is sticky */
1768
1769 /* Indirect pre-decrement load (mode 4) */
1770
1771 src = gen_ea_mode(env, s, 4, REG(insn, 0), OS_BYTE,
1772 NULL_QREG, NULL, EA_LOADU, IS_USER(s));
1773 dest = gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE,
1774 NULL_QREG, &addr, EA_LOADU, IS_USER(s));
1775
1776 bcd_sub(dest, src);
1777
1778 gen_ea_mode(env, s, 4, REG(insn, 9), OS_BYTE, dest, &addr,
1779 EA_STORE, IS_USER(s));
1780
1781 bcd_flags(dest);
1782 }
1783
1784 DISAS_INSN(nbcd)
1785 {
1786 TCGv src, dest;
1787 TCGv addr;
1788
1789 gen_flush_flags(s); /* !Z is sticky */
1790
1791 SRC_EA(env, src, OS_BYTE, 0, &addr);
1792
1793 dest = tcg_temp_new();
1794 tcg_gen_movi_i32(dest, 0);
1795 bcd_sub(dest, src);
1796
1797 DEST_EA(env, insn, OS_BYTE, dest, &addr);
1798
1799 bcd_flags(dest);
1800 }
1801
1802 DISAS_INSN(addsub)
1803 {
1804 TCGv reg;
1805 TCGv dest;
1806 TCGv src;
1807 TCGv tmp;
1808 TCGv addr;
1809 int add;
1810 int opsize;
1811
1812 add = (insn & 0x4000) != 0;
1813 opsize = insn_opsize(insn);
1814 reg = gen_extend(s, DREG(insn, 9), opsize, 1);
1815 dest = tcg_temp_new();
1816 if (insn & 0x100) {
1817 SRC_EA(env, tmp, opsize, 1, &addr);
1818 src = reg;
1819 } else {
1820 tmp = reg;
1821 SRC_EA(env, src, opsize, 1, NULL);
1822 }
1823 if (add) {
1824 tcg_gen_add_i32(dest, tmp, src);
1825 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, src);
1826 set_cc_op(s, CC_OP_ADDB + opsize);
1827 } else {
1828 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, tmp, src);
1829 tcg_gen_sub_i32(dest, tmp, src);
1830 set_cc_op(s, CC_OP_SUBB + opsize);
1831 }
1832 gen_update_cc_add(dest, src, opsize);
1833 if (insn & 0x100) {
1834 DEST_EA(env, insn, opsize, dest, &addr);
1835 } else {
1836 gen_partset_reg(opsize, DREG(insn, 9), dest);
1837 }
1838 }
1839
1840 /* Reverse the order of the bits in REG. */
1841 DISAS_INSN(bitrev)
1842 {
1843 TCGv reg;
1844 reg = DREG(insn, 0);
1845 gen_helper_bitrev(reg, reg);
1846 }
1847
1848 DISAS_INSN(bitop_reg)
1849 {
1850 int opsize;
1851 int op;
1852 TCGv src1;
1853 TCGv src2;
1854 TCGv tmp;
1855 TCGv addr;
1856 TCGv dest;
1857
1858 if ((insn & 0x38) != 0)
1859 opsize = OS_BYTE;
1860 else
1861 opsize = OS_LONG;
1862 op = (insn >> 6) & 3;
1863 SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
1864
1865 gen_flush_flags(s);
1866 src2 = tcg_temp_new();
1867 if (opsize == OS_BYTE)
1868 tcg_gen_andi_i32(src2, DREG(insn, 9), 7);
1869 else
1870 tcg_gen_andi_i32(src2, DREG(insn, 9), 31);
1871
1872 tmp = tcg_temp_new();
1873 tcg_gen_shl_i32(tmp, tcg_constant_i32(1), src2);
1874
1875 tcg_gen_and_i32(QREG_CC_Z, src1, tmp);
1876
1877 dest = tcg_temp_new();
1878 switch (op) {
1879 case 1: /* bchg */
1880 tcg_gen_xor_i32(dest, src1, tmp);
1881 break;
1882 case 2: /* bclr */
1883 tcg_gen_andc_i32(dest, src1, tmp);
1884 break;
1885 case 3: /* bset */
1886 tcg_gen_or_i32(dest, src1, tmp);
1887 break;
1888 default: /* btst */
1889 break;
1890 }
1891 if (op) {
1892 DEST_EA(env, insn, opsize, dest, &addr);
1893 }
1894 }
1895
1896 DISAS_INSN(sats)
1897 {
1898 TCGv reg;
1899 reg = DREG(insn, 0);
1900 gen_flush_flags(s);
1901 gen_helper_sats(reg, reg, QREG_CC_V);
1902 gen_logic_cc(s, reg, OS_LONG);
1903 }
1904
1905 static void gen_push(DisasContext *s, TCGv val)
1906 {
1907 TCGv tmp;
1908
1909 tmp = tcg_temp_new();
1910 tcg_gen_subi_i32(tmp, QREG_SP, 4);
1911 gen_store(s, OS_LONG, tmp, val, IS_USER(s));
1912 tcg_gen_mov_i32(QREG_SP, tmp);
1913 }
1914
1915 static TCGv mreg(int reg)
1916 {
1917 if (reg < 8) {
1918 /* Dx */
1919 return cpu_dregs[reg];
1920 }
1921 /* Ax */
1922 return cpu_aregs[reg & 7];
1923 }
1924
1925 DISAS_INSN(movem)
1926 {
1927 TCGv addr, incr, tmp, r[16];
1928 int is_load = (insn & 0x0400) != 0;
1929 int opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
1930 uint16_t mask = read_im16(env, s);
1931 int mode = extract32(insn, 3, 3);
1932 int reg0 = REG(insn, 0);
1933 int i;
1934
1935 tmp = cpu_aregs[reg0];
1936
1937 switch (mode) {
1938 case 0: /* data register direct */
1939 case 1: /* addr register direct */
1940 do_addr_fault:
1941 gen_addr_fault(s);
1942 return;
1943
1944 case 2: /* indirect */
1945 break;
1946
1947 case 3: /* indirect post-increment */
1948 if (!is_load) {
1949 /* post-increment is not allowed */
1950 goto do_addr_fault;
1951 }
1952 break;
1953
1954 case 4: /* indirect pre-decrement */
1955 if (is_load) {
1956 /* pre-decrement is not allowed */
1957 goto do_addr_fault;
1958 }
1959 /*
1960 * We want a bare copy of the address reg, without any pre-decrement
1961 * adjustment, as gen_lea would provide.
1962 */
1963 break;
1964
1965 default:
1966 tmp = gen_lea_mode(env, s, mode, reg0, opsize);
1967 if (IS_NULL_QREG(tmp)) {
1968 goto do_addr_fault;
1969 }
1970 break;
1971 }
1972
1973 addr = tcg_temp_new();
1974 tcg_gen_mov_i32(addr, tmp);
1975 incr = tcg_constant_i32(opsize_bytes(opsize));
1976
1977 if (is_load) {
1978 /* memory to register */
1979 for (i = 0; i < 16; i++) {
1980 if (mask & (1 << i)) {
1981 r[i] = gen_load(s, opsize, addr, 1, IS_USER(s));
1982 tcg_gen_add_i32(addr, addr, incr);
1983 }
1984 }
1985 for (i = 0; i < 16; i++) {
1986 if (mask & (1 << i)) {
1987 tcg_gen_mov_i32(mreg(i), r[i]);
1988 }
1989 }
1990 if (mode == 3) {
1991 /* post-increment: movem (An)+,X */
1992 tcg_gen_mov_i32(cpu_aregs[reg0], addr);
1993 }
1994 } else {
1995 /* register to memory */
1996 if (mode == 4) {
1997 /* pre-decrement: movem X,-(An) */
1998 for (i = 15; i >= 0; i--) {
1999 if ((mask << i) & 0x8000) {
2000 tcg_gen_sub_i32(addr, addr, incr);
2001 if (reg0 + 8 == i &&
2002 m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
2003 /*
2004 * M68020+: if the addressing register is the
2005 * register moved to memory, the value written
2006 * is the initial value decremented by the size of
2007 * the operation, regardless of how many actual
2008 * stores have been performed until this point.
2009 * M68000/M68010: the value is the initial value.
2010 */
2011 tmp = tcg_temp_new();
2012 tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr);
2013 gen_store(s, opsize, addr, tmp, IS_USER(s));
2014 } else {
2015 gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2016 }
2017 }
2018 }
2019 tcg_gen_mov_i32(cpu_aregs[reg0], addr);
2020 } else {
2021 for (i = 0; i < 16; i++) {
2022 if (mask & (1 << i)) {
2023 gen_store(s, opsize, addr, mreg(i), IS_USER(s));
2024 tcg_gen_add_i32(addr, addr, incr);
2025 }
2026 }
2027 }
2028 }
2029 }
2030
2031 DISAS_INSN(movep)
2032 {
2033 uint8_t i;
2034 int16_t displ;
2035 TCGv reg;
2036 TCGv addr;
2037 TCGv abuf;
2038 TCGv dbuf;
2039
2040 displ = read_im16(env, s);
2041
2042 addr = AREG(insn, 0);
2043 reg = DREG(insn, 9);
2044
2045 abuf = tcg_temp_new();
2046 tcg_gen_addi_i32(abuf, addr, displ);
2047 dbuf = tcg_temp_new();
2048
2049 if (insn & 0x40) {
2050 i = 4;
2051 } else {
2052 i = 2;
2053 }
2054
2055 if (insn & 0x80) {
2056 for ( ; i > 0 ; i--) {
2057 tcg_gen_shri_i32(dbuf, reg, (i - 1) * 8);
2058 tcg_gen_qemu_st_i32(dbuf, abuf, IS_USER(s), MO_UB);
2059 if (i > 1) {
2060 tcg_gen_addi_i32(abuf, abuf, 2);
2061 }
2062 }
2063 } else {
2064 for ( ; i > 0 ; i--) {
2065 tcg_gen_qemu_ld_tl(dbuf, abuf, IS_USER(s), MO_UB);
2066 tcg_gen_deposit_i32(reg, reg, dbuf, (i - 1) * 8, 8);
2067 if (i > 1) {
2068 tcg_gen_addi_i32(abuf, abuf, 2);
2069 }
2070 }
2071 }
2072 }
2073
2074 DISAS_INSN(bitop_im)
2075 {
2076 int opsize;
2077 int op;
2078 TCGv src1;
2079 uint32_t mask;
2080 int bitnum;
2081 TCGv tmp;
2082 TCGv addr;
2083
2084 if ((insn & 0x38) != 0)
2085 opsize = OS_BYTE;
2086 else
2087 opsize = OS_LONG;
2088 op = (insn >> 6) & 3;
2089
2090 bitnum = read_im16(env, s);
2091 if (m68k_feature(s->env, M68K_FEATURE_M68K)) {
2092 if (bitnum & 0xfe00) {
2093 disas_undef(env, s, insn);
2094 return;
2095 }
2096 } else {
2097 if (bitnum & 0xff00) {
2098 disas_undef(env, s, insn);
2099 return;
2100 }
2101 }
2102
2103 SRC_EA(env, src1, opsize, 0, op ? &addr: NULL);
2104
2105 gen_flush_flags(s);
2106 if (opsize == OS_BYTE)
2107 bitnum &= 7;
2108 else
2109 bitnum &= 31;
2110 mask = 1 << bitnum;
2111
2112 tcg_gen_andi_i32(QREG_CC_Z, src1, mask);
2113
2114 if (op) {
2115 tmp = tcg_temp_new();
2116 switch (op) {
2117 case 1: /* bchg */
2118 tcg_gen_xori_i32(tmp, src1, mask);
2119 break;
2120 case 2: /* bclr */
2121 tcg_gen_andi_i32(tmp, src1, ~mask);
2122 break;
2123 case 3: /* bset */
2124 tcg_gen_ori_i32(tmp, src1, mask);
2125 break;
2126 default: /* btst */
2127 break;
2128 }
2129 DEST_EA(env, insn, opsize, tmp, &addr);
2130 }
2131 }
2132
2133 static TCGv gen_get_ccr(DisasContext *s)
2134 {
2135 TCGv dest;
2136
2137 update_cc_op(s);
2138 dest = tcg_temp_new();
2139 gen_helper_get_ccr(dest, tcg_env);
2140 return dest;
2141 }
2142
2143 static TCGv gen_get_sr(DisasContext *s)
2144 {
2145 TCGv ccr;
2146 TCGv sr;
2147
2148 ccr = gen_get_ccr(s);
2149 sr = tcg_temp_new();
2150 tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
2151 tcg_gen_or_i32(sr, sr, ccr);
2152 return sr;
2153 }
2154
2155 static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
2156 {
2157 if (ccr_only) {
2158 tcg_gen_movi_i32(QREG_CC_C, val & CCF_C ? 1 : 0);
2159 tcg_gen_movi_i32(QREG_CC_V, val & CCF_V ? -1 : 0);
2160 tcg_gen_movi_i32(QREG_CC_Z, val & CCF_Z ? 0 : 1);
2161 tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0);
2162 tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0);
2163 } else {
2164 /* Must writeback before changing security state. */
2165 do_writebacks(s);
2166 gen_helper_set_sr(tcg_env, tcg_constant_i32(val));
2167 }
2168 set_cc_op(s, CC_OP_FLAGS);
2169 }
2170
2171 static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only)
2172 {
2173 if (ccr_only) {
2174 gen_helper_set_ccr(tcg_env, val);
2175 } else {
2176 /* Must writeback before changing security state. */
2177 do_writebacks(s);
2178 gen_helper_set_sr(tcg_env, val);
2179 }
2180 set_cc_op(s, CC_OP_FLAGS);
2181 }
2182
2183 static void gen_move_to_sr(CPUM68KState *env, DisasContext *s, uint16_t insn,
2184 bool ccr_only)
2185 {
2186 if ((insn & 0x3f) == 0x3c) {
2187 uint16_t val;
2188 val = read_im16(env, s);
2189 gen_set_sr_im(s, val, ccr_only);
2190 } else {
2191 TCGv src;
2192 SRC_EA(env, src, OS_WORD, 0, NULL);
2193 gen_set_sr(s, src, ccr_only);
2194 }
2195 }
2196
2197 DISAS_INSN(arith_im)
2198 {
2199 int op;
2200 TCGv im;
2201 TCGv src1;
2202 TCGv dest;
2203 TCGv addr;
2204 int opsize;
2205 bool with_SR = ((insn & 0x3f) == 0x3c);
2206
2207 op = (insn >> 9) & 7;
2208 opsize = insn_opsize(insn);
2209 switch (opsize) {
2210 case OS_BYTE:
2211 im = tcg_constant_i32((int8_t)read_im8(env, s));
2212 break;
2213 case OS_WORD:
2214 im = tcg_constant_i32((int16_t)read_im16(env, s));
2215 break;
2216 case OS_LONG:
2217 im = tcg_constant_i32(read_im32(env, s));
2218 break;
2219 default:
2220 g_assert_not_reached();
2221 }
2222
2223 if (with_SR) {
2224 /* SR/CCR can only be used with andi/eori/ori */
2225 if (op == 2 || op == 3 || op == 6) {
2226 disas_undef(env, s, insn);
2227 return;
2228 }
2229 switch (opsize) {
2230 case OS_BYTE:
2231 src1 = gen_get_ccr(s);
2232 break;
2233 case OS_WORD:
2234 if (IS_USER(s)) {
2235 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2236 return;
2237 }
2238 src1 = gen_get_sr(s);
2239 break;
2240 default:
2241 /* OS_LONG; others already g_assert_not_reached. */
2242 disas_undef(env, s, insn);
2243 return;
2244 }
2245 } else {
2246 SRC_EA(env, src1, opsize, 1, (op == 6) ? NULL : &addr);
2247 }
2248 dest = tcg_temp_new();
2249 switch (op) {
2250 case 0: /* ori */
2251 tcg_gen_or_i32(dest, src1, im);
2252 if (with_SR) {
2253 gen_set_sr(s, dest, opsize == OS_BYTE);
2254 gen_exit_tb(s);
2255 } else {
2256 DEST_EA(env, insn, opsize, dest, &addr);
2257 gen_logic_cc(s, dest, opsize);
2258 }
2259 break;
2260 case 1: /* andi */
2261 tcg_gen_and_i32(dest, src1, im);
2262 if (with_SR) {
2263 gen_set_sr(s, dest, opsize == OS_BYTE);
2264 gen_exit_tb(s);
2265 } else {
2266 DEST_EA(env, insn, opsize, dest, &addr);
2267 gen_logic_cc(s, dest, opsize);
2268 }
2269 break;
2270 case 2: /* subi */
2271 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, src1, im);
2272 tcg_gen_sub_i32(dest, src1, im);
2273 gen_update_cc_add(dest, im, opsize);
2274 set_cc_op(s, CC_OP_SUBB + opsize);
2275 DEST_EA(env, insn, opsize, dest, &addr);
2276 break;
2277 case 3: /* addi */
2278 tcg_gen_add_i32(dest, src1, im);
2279 gen_update_cc_add(dest, im, opsize);
2280 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, im);
2281 set_cc_op(s, CC_OP_ADDB + opsize);
2282 DEST_EA(env, insn, opsize, dest, &addr);
2283 break;
2284 case 5: /* eori */
2285 tcg_gen_xor_i32(dest, src1, im);
2286 if (with_SR) {
2287 gen_set_sr(s, dest, opsize == OS_BYTE);
2288 gen_exit_tb(s);
2289 } else {
2290 DEST_EA(env, insn, opsize, dest, &addr);
2291 gen_logic_cc(s, dest, opsize);
2292 }
2293 break;
2294 case 6: /* cmpi */
2295 gen_update_cc_cmp(s, src1, im, opsize);
2296 break;
2297 default:
2298 abort();
2299 }
2300 }
2301
2302 DISAS_INSN(cas)
2303 {
2304 int opsize;
2305 TCGv addr;
2306 uint16_t ext;
2307 TCGv load;
2308 TCGv cmp;
2309 MemOp opc;
2310
2311 switch ((insn >> 9) & 3) {
2312 case 1:
2313 opsize = OS_BYTE;
2314 opc = MO_SB;
2315 break;
2316 case 2:
2317 opsize = OS_WORD;
2318 opc = MO_TESW;
2319 break;
2320 case 3:
2321 opsize = OS_LONG;
2322 opc = MO_TESL;
2323 break;
2324 default:
2325 g_assert_not_reached();
2326 }
2327
2328 ext = read_im16(env, s);
2329
2330 /* cas Dc,Du,<EA> */
2331
2332 addr = gen_lea(env, s, insn, opsize);
2333 if (IS_NULL_QREG(addr)) {
2334 gen_addr_fault(s);
2335 return;
2336 }
2337
2338 cmp = gen_extend(s, DREG(ext, 0), opsize, 1);
2339
2340 /*
2341 * if <EA> == Dc then
2342 * <EA> = Du
2343 * Dc = <EA> (because <EA> == Dc)
2344 * else
2345 * Dc = <EA>
2346 */
2347
2348 load = tcg_temp_new();
2349 tcg_gen_atomic_cmpxchg_i32(load, addr, cmp, DREG(ext, 6),
2350 IS_USER(s), opc);
2351 /* update flags before setting cmp to load */
2352 gen_update_cc_cmp(s, load, cmp, opsize);
2353 gen_partset_reg(opsize, DREG(ext, 0), load);
2354
2355 switch (extract32(insn, 3, 3)) {
2356 case 3: /* Indirect postincrement. */
2357 tcg_gen_addi_i32(AREG(insn, 0), addr, opsize_bytes(opsize));
2358 break;
2359 case 4: /* Indirect predecrememnt. */
2360 tcg_gen_mov_i32(AREG(insn, 0), addr);
2361 break;
2362 }
2363 }
2364
2365 DISAS_INSN(cas2w)
2366 {
2367 uint16_t ext1, ext2;
2368 TCGv addr1, addr2;
2369
2370 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2371
2372 ext1 = read_im16(env, s);
2373
2374 if (ext1 & 0x8000) {
2375 /* Address Register */
2376 addr1 = AREG(ext1, 12);
2377 } else {
2378 /* Data Register */
2379 addr1 = DREG(ext1, 12);
2380 }
2381
2382 ext2 = read_im16(env, s);
2383 if (ext2 & 0x8000) {
2384 /* Address Register */
2385 addr2 = AREG(ext2, 12);
2386 } else {
2387 /* Data Register */
2388 addr2 = DREG(ext2, 12);
2389 }
2390
2391 /*
2392 * if (R1) == Dc1 && (R2) == Dc2 then
2393 * (R1) = Du1
2394 * (R2) = Du2
2395 * else
2396 * Dc1 = (R1)
2397 * Dc2 = (R2)
2398 */
2399
2400 if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2401 gen_helper_exit_atomic(tcg_env);
2402 } else {
2403 TCGv regs = tcg_constant_i32(REG(ext2, 6) |
2404 (REG(ext1, 6) << 3) |
2405 (REG(ext2, 0) << 6) |
2406 (REG(ext1, 0) << 9));
2407 gen_helper_cas2w(tcg_env, regs, addr1, addr2);
2408 }
2409
2410 /* Note that cas2w also assigned to env->cc_op. */
2411 s->cc_op = CC_OP_CMPW;
2412 s->cc_op_synced = 1;
2413 }
2414
2415 DISAS_INSN(cas2l)
2416 {
2417 uint16_t ext1, ext2;
2418 TCGv addr1, addr2, regs;
2419
2420 /* cas2 Dc1:Dc2,Du1:Du2,(Rn1):(Rn2) */
2421
2422 ext1 = read_im16(env, s);
2423
2424 if (ext1 & 0x8000) {
2425 /* Address Register */
2426 addr1 = AREG(ext1, 12);
2427 } else {
2428 /* Data Register */
2429 addr1 = DREG(ext1, 12);
2430 }
2431
2432 ext2 = read_im16(env, s);
2433 if (ext2 & 0x8000) {
2434 /* Address Register */
2435 addr2 = AREG(ext2, 12);
2436 } else {
2437 /* Data Register */
2438 addr2 = DREG(ext2, 12);
2439 }
2440
2441 /*
2442 * if (R1) == Dc1 && (R2) == Dc2 then
2443 * (R1) = Du1
2444 * (R2) = Du2
2445 * else
2446 * Dc1 = (R1)
2447 * Dc2 = (R2)
2448 */
2449
2450 regs = tcg_constant_i32(REG(ext2, 6) |
2451 (REG(ext1, 6) << 3) |
2452 (REG(ext2, 0) << 6) |
2453 (REG(ext1, 0) << 9));
2454 if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2455 gen_helper_cas2l_parallel(tcg_env, regs, addr1, addr2);
2456 } else {
2457 gen_helper_cas2l(tcg_env, regs, addr1, addr2);
2458 }
2459
2460 /* Note that cas2l also assigned to env->cc_op. */
2461 s->cc_op = CC_OP_CMPL;
2462 s->cc_op_synced = 1;
2463 }
2464
2465 DISAS_INSN(byterev)
2466 {
2467 TCGv reg;
2468
2469 reg = DREG(insn, 0);
2470 tcg_gen_bswap32_i32(reg, reg);
2471 }
2472
2473 DISAS_INSN(move)
2474 {
2475 TCGv src;
2476 TCGv dest;
2477 int op;
2478 int opsize;
2479
2480 switch (insn >> 12) {
2481 case 1: /* move.b */
2482 opsize = OS_BYTE;
2483 break;
2484 case 2: /* move.l */
2485 opsize = OS_LONG;
2486 break;
2487 case 3: /* move.w */
2488 opsize = OS_WORD;
2489 break;
2490 default:
2491 abort();
2492 }
2493 SRC_EA(env, src, opsize, 1, NULL);
2494 op = (insn >> 6) & 7;
2495 if (op == 1) {
2496 /* movea */
2497 /* The value will already have been sign extended. */
2498 dest = AREG(insn, 9);
2499 tcg_gen_mov_i32(dest, src);
2500 } else {
2501 /* normal move */
2502 uint16_t dest_ea;
2503 dest_ea = ((insn >> 9) & 7) | (op << 3);
2504 DEST_EA(env, dest_ea, opsize, src, NULL);
2505 /* This will be correct because loads sign extend. */
2506 gen_logic_cc(s, src, opsize);
2507 }
2508 }
2509
2510 DISAS_INSN(negx)
2511 {
2512 TCGv z;
2513 TCGv src;
2514 TCGv addr;
2515 int opsize;
2516
2517 opsize = insn_opsize(insn);
2518 SRC_EA(env, src, opsize, 1, &addr);
2519
2520 gen_flush_flags(s); /* compute old Z */
2521
2522 /*
2523 * Perform subtract with borrow.
2524 * (X, N) = -(src + X);
2525 */
2526
2527 z = tcg_constant_i32(0);
2528 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, z, QREG_CC_X, z);
2529 tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, z, z, QREG_CC_N, QREG_CC_X);
2530 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
2531
2532 tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
2533
2534 /*
2535 * Compute signed-overflow for negation. The normal formula for
2536 * subtraction is (res ^ src) & (src ^ dest), but with dest==0
2537 * this simplifies to res & src.
2538 */
2539
2540 tcg_gen_and_i32(QREG_CC_V, QREG_CC_N, src);
2541
2542 /* Copy the rest of the results into place. */
2543 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
2544 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
2545
2546 set_cc_op(s, CC_OP_FLAGS);
2547
2548 /* result is in QREG_CC_N */
2549
2550 DEST_EA(env, insn, opsize, QREG_CC_N, &addr);
2551 }
2552
2553 DISAS_INSN(lea)
2554 {
2555 TCGv reg;
2556 TCGv tmp;
2557
2558 reg = AREG(insn, 9);
2559 tmp = gen_lea(env, s, insn, OS_LONG);
2560 if (IS_NULL_QREG(tmp)) {
2561 gen_addr_fault(s);
2562 return;
2563 }
2564 tcg_gen_mov_i32(reg, tmp);
2565 }
2566
2567 DISAS_INSN(clr)
2568 {
2569 int opsize;
2570 TCGv zero;
2571
2572 zero = tcg_constant_i32(0);
2573 opsize = insn_opsize(insn);
2574 DEST_EA(env, insn, opsize, zero, NULL);
2575 gen_logic_cc(s, zero, opsize);
2576 }
2577
2578 DISAS_INSN(move_from_ccr)
2579 {
2580 TCGv ccr;
2581
2582 ccr = gen_get_ccr(s);
2583 DEST_EA(env, insn, OS_WORD, ccr, NULL);
2584 }
2585
2586 DISAS_INSN(neg)
2587 {
2588 TCGv src1;
2589 TCGv dest;
2590 TCGv addr;
2591 int opsize;
2592
2593 opsize = insn_opsize(insn);
2594 SRC_EA(env, src1, opsize, 1, &addr);
2595 dest = tcg_temp_new();
2596 tcg_gen_neg_i32(dest, src1);
2597 set_cc_op(s, CC_OP_SUBB + opsize);
2598 gen_update_cc_add(dest, src1, opsize);
2599 tcg_gen_setcondi_i32(TCG_COND_NE, QREG_CC_X, dest, 0);
2600 DEST_EA(env, insn, opsize, dest, &addr);
2601 }
2602
2603 DISAS_INSN(move_to_ccr)
2604 {
2605 gen_move_to_sr(env, s, insn, true);
2606 }
2607
2608 DISAS_INSN(not)
2609 {
2610 TCGv src1;
2611 TCGv dest;
2612 TCGv addr;
2613 int opsize;
2614
2615 opsize = insn_opsize(insn);
2616 SRC_EA(env, src1, opsize, 1, &addr);
2617 dest = tcg_temp_new();
2618 tcg_gen_not_i32(dest, src1);
2619 DEST_EA(env, insn, opsize, dest, &addr);
2620 gen_logic_cc(s, dest, opsize);
2621 }
2622
2623 DISAS_INSN(swap)
2624 {
2625 TCGv src1;
2626 TCGv src2;
2627 TCGv reg;
2628
2629 src1 = tcg_temp_new();
2630 src2 = tcg_temp_new();
2631 reg = DREG(insn, 0);
2632 tcg_gen_shli_i32(src1, reg, 16);
2633 tcg_gen_shri_i32(src2, reg, 16);
2634 tcg_gen_or_i32(reg, src1, src2);
2635 gen_logic_cc(s, reg, OS_LONG);
2636 }
2637
2638 DISAS_INSN(bkpt)
2639 {
2640 #if defined(CONFIG_USER_ONLY)
2641 gen_exception(s, s->base.pc_next, EXCP_DEBUG);
2642 #else
2643 /* BKPT #0 is the alternate semihosting instruction. */
2644 if ((insn & 7) == 0 && semihosting_test(s)) {
2645 gen_exception(s, s->pc, EXCP_SEMIHOSTING);
2646 return;
2647 }
2648 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2649 #endif
2650 }
2651
2652 DISAS_INSN(pea)
2653 {
2654 TCGv tmp;
2655
2656 tmp = gen_lea(env, s, insn, OS_LONG);
2657 if (IS_NULL_QREG(tmp)) {
2658 gen_addr_fault(s);
2659 return;
2660 }
2661 gen_push(s, tmp);
2662 }
2663
2664 DISAS_INSN(ext)
2665 {
2666 int op;
2667 TCGv reg;
2668 TCGv tmp;
2669
2670 reg = DREG(insn, 0);
2671 op = (insn >> 6) & 7;
2672 tmp = tcg_temp_new();
2673 if (op == 3)
2674 tcg_gen_ext16s_i32(tmp, reg);
2675 else
2676 tcg_gen_ext8s_i32(tmp, reg);
2677 if (op == 2)
2678 gen_partset_reg(OS_WORD, reg, tmp);
2679 else
2680 tcg_gen_mov_i32(reg, tmp);
2681 gen_logic_cc(s, tmp, OS_LONG);
2682 }
2683
2684 DISAS_INSN(tst)
2685 {
2686 int opsize;
2687 TCGv tmp;
2688
2689 opsize = insn_opsize(insn);
2690 SRC_EA(env, tmp, opsize, 1, NULL);
2691 gen_logic_cc(s, tmp, opsize);
2692 }
2693
2694 DISAS_INSN(pulse)
2695 {
2696 /* Implemented as a NOP. */
2697 }
2698
2699 DISAS_INSN(illegal)
2700 {
2701 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2702 }
2703
2704 DISAS_INSN(tas)
2705 {
2706 int mode = extract32(insn, 3, 3);
2707 int reg0 = REG(insn, 0);
2708
2709 if (mode == 0) {
2710 /* data register direct */
2711 TCGv dest = cpu_dregs[reg0];
2712 gen_logic_cc(s, dest, OS_BYTE);
2713 tcg_gen_ori_tl(dest, dest, 0x80);
2714 } else {
2715 TCGv src1, addr;
2716
2717 addr = gen_lea_mode(env, s, mode, reg0, OS_BYTE);
2718 if (IS_NULL_QREG(addr)) {
2719 gen_addr_fault(s);
2720 return;
2721 }
2722 src1 = tcg_temp_new();
2723 tcg_gen_atomic_fetch_or_tl(src1, addr, tcg_constant_tl(0x80),
2724 IS_USER(s), MO_SB);
2725 gen_logic_cc(s, src1, OS_BYTE);
2726
2727 switch (mode) {
2728 case 3: /* Indirect postincrement. */
2729 tcg_gen_addi_i32(AREG(insn, 0), addr, 1);
2730 break;
2731 case 4: /* Indirect predecrememnt. */
2732 tcg_gen_mov_i32(AREG(insn, 0), addr);
2733 break;
2734 }
2735 }
2736 }
2737
2738 DISAS_INSN(mull)
2739 {
2740 uint16_t ext;
2741 TCGv src1;
2742 int sign;
2743
2744 ext = read_im16(env, s);
2745
2746 sign = ext & 0x800;
2747
2748 if (ext & 0x400) {
2749 if (!m68k_feature(s->env, M68K_FEATURE_QUAD_MULDIV)) {
2750 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
2751 return;
2752 }
2753
2754 SRC_EA(env, src1, OS_LONG, 0, NULL);
2755
2756 if (sign) {
2757 tcg_gen_muls2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2758 } else {
2759 tcg_gen_mulu2_i32(QREG_CC_Z, QREG_CC_N, src1, DREG(ext, 12));
2760 }
2761 /* if Dl == Dh, 68040 returns low word */
2762 tcg_gen_mov_i32(DREG(ext, 0), QREG_CC_N);
2763 tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_Z);
2764 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N);
2765
2766 tcg_gen_movi_i32(QREG_CC_V, 0);
2767 tcg_gen_movi_i32(QREG_CC_C, 0);
2768
2769 set_cc_op(s, CC_OP_FLAGS);
2770 return;
2771 }
2772 SRC_EA(env, src1, OS_LONG, 0, NULL);
2773 if (m68k_feature(s->env, M68K_FEATURE_M68K)) {
2774 tcg_gen_movi_i32(QREG_CC_C, 0);
2775 if (sign) {
2776 tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2777 /* QREG_CC_V is -(QREG_CC_V != (QREG_CC_N >> 31)) */
2778 tcg_gen_sari_i32(QREG_CC_Z, QREG_CC_N, 31);
2779 tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V,
2780 QREG_CC_V, QREG_CC_Z);
2781 } else {
2782 tcg_gen_mulu2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12));
2783 /* QREG_CC_V is -(QREG_CC_V != 0), use QREG_CC_C as 0 */
2784 tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V,
2785 QREG_CC_V, QREG_CC_C);
2786 }
2787 tcg_gen_mov_i32(DREG(ext, 12), QREG_CC_N);
2788
2789 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
2790
2791 set_cc_op(s, CC_OP_FLAGS);
2792 } else {
2793 /*
2794 * The upper 32 bits of the product are discarded, so
2795 * muls.l and mulu.l are functionally equivalent.
2796 */
2797 tcg_gen_mul_i32(DREG(ext, 12), src1, DREG(ext, 12));
2798 gen_logic_cc(s, DREG(ext, 12), OS_LONG);
2799 }
2800 }
2801
2802 static void gen_link(DisasContext *s, uint16_t insn, int32_t offset)
2803 {
2804 TCGv reg;
2805 TCGv tmp;
2806
2807 reg = AREG(insn, 0);
2808 tmp = tcg_temp_new();
2809 tcg_gen_subi_i32(tmp, QREG_SP, 4);
2810 gen_store(s, OS_LONG, tmp, reg, IS_USER(s));
2811 if ((insn & 7) != 7) {
2812 tcg_gen_mov_i32(reg, tmp);
2813 }
2814 tcg_gen_addi_i32(QREG_SP, tmp, offset);
2815 }
2816
2817 DISAS_INSN(link)
2818 {
2819 int16_t offset;
2820
2821 offset = read_im16(env, s);
2822 gen_link(s, insn, offset);
2823 }
2824
2825 DISAS_INSN(linkl)
2826 {
2827 int32_t offset;
2828
2829 offset = read_im32(env, s);
2830 gen_link(s, insn, offset);
2831 }
2832
2833 DISAS_INSN(unlk)
2834 {
2835 TCGv src;
2836 TCGv reg;
2837 TCGv tmp;
2838
2839 src = tcg_temp_new();
2840 reg = AREG(insn, 0);
2841 tcg_gen_mov_i32(src, reg);
2842 tmp = gen_load(s, OS_LONG, src, 0, IS_USER(s));
2843 tcg_gen_mov_i32(reg, tmp);
2844 tcg_gen_addi_i32(QREG_SP, src, 4);
2845 }
2846
2847 #if !defined(CONFIG_USER_ONLY)
2848 DISAS_INSN(reset)
2849 {
2850 if (IS_USER(s)) {
2851 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
2852 return;
2853 }
2854
2855 gen_helper_reset(tcg_env);
2856 }
2857 #endif
2858
2859 DISAS_INSN(nop)
2860 {
2861 }
2862
2863 DISAS_INSN(rtd)
2864 {
2865 TCGv tmp;
2866 int16_t offset = read_im16(env, s);
2867
2868 tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2869 tcg_gen_addi_i32(QREG_SP, QREG_SP, offset + 4);
2870 gen_jmp(s, tmp);
2871 }
2872
2873 DISAS_INSN(rtr)
2874 {
2875 TCGv tmp;
2876 TCGv ccr;
2877 TCGv sp;
2878
2879 sp = tcg_temp_new();
2880 ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
2881 tcg_gen_addi_i32(sp, QREG_SP, 2);
2882 tmp = gen_load(s, OS_LONG, sp, 0, IS_USER(s));
2883 tcg_gen_addi_i32(QREG_SP, sp, 4);
2884
2885 gen_set_sr(s, ccr, true);
2886
2887 gen_jmp(s, tmp);
2888 }
2889
2890 DISAS_INSN(rts)
2891 {
2892 TCGv tmp;
2893
2894 tmp = gen_load(s, OS_LONG, QREG_SP, 0, IS_USER(s));
2895 tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
2896 gen_jmp(s, tmp);
2897 }
2898
2899 DISAS_INSN(jump)
2900 {
2901 TCGv tmp;
2902
2903 /*
2904 * Load the target address first to ensure correct exception
2905 * behavior.
2906 */
2907 tmp = gen_lea(env, s, insn, OS_LONG);
2908 if (IS_NULL_QREG(tmp)) {
2909 gen_addr_fault(s);
2910 return;
2911 }
2912 if ((insn & 0x40) == 0) {
2913 /* jsr */
2914 gen_push(s, tcg_constant_i32(s->pc));
2915 }
2916 gen_jmp(s, tmp);
2917 }
2918
2919 DISAS_INSN(addsubq)
2920 {
2921 TCGv src;
2922 TCGv dest;
2923 TCGv val;
2924 int imm;
2925 TCGv addr;
2926 int opsize;
2927
2928 if ((insn & 070) == 010) {
2929 /* Operation on address register is always long. */
2930 opsize = OS_LONG;
2931 } else {
2932 opsize = insn_opsize(insn);
2933 }
2934 SRC_EA(env, src, opsize, 1, &addr);
2935 imm = (insn >> 9) & 7;
2936 if (imm == 0) {
2937 imm = 8;
2938 }
2939 val = tcg_constant_i32(imm);
2940 dest = tcg_temp_new();
2941 tcg_gen_mov_i32(dest, src);
2942 if ((insn & 0x38) == 0x08) {
2943 /*
2944 * Don't update condition codes if the destination is an
2945 * address register.
2946 */
2947 if (insn & 0x0100) {
2948 tcg_gen_sub_i32(dest, dest, val);
2949 } else {
2950 tcg_gen_add_i32(dest, dest, val);
2951 }
2952 } else {
2953 if (insn & 0x0100) {
2954 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
2955 tcg_gen_sub_i32(dest, dest, val);
2956 set_cc_op(s, CC_OP_SUBB + opsize);
2957 } else {
2958 tcg_gen_add_i32(dest, dest, val);
2959 tcg_gen_setcond_i32(TCG_COND_LTU, QREG_CC_X, dest, val);
2960 set_cc_op(s, CC_OP_ADDB + opsize);
2961 }
2962 gen_update_cc_add(dest, val, opsize);
2963 }
2964 DEST_EA(env, insn, opsize, dest, &addr);
2965 }
2966
2967 DISAS_INSN(branch)
2968 {
2969 int32_t offset;
2970 uint32_t base;
2971 int op;
2972
2973 base = s->pc;
2974 op = (insn >> 8) & 0xf;
2975 offset = (int8_t)insn;
2976 if (offset == 0) {
2977 offset = (int16_t)read_im16(env, s);
2978 } else if (offset == -1) {
2979 offset = read_im32(env, s);
2980 }
2981 if (op == 1) {
2982 /* bsr */
2983 gen_push(s, tcg_constant_i32(s->pc));
2984 }
2985 if (op > 1) {
2986 /* Bcc */
2987 TCGLabel *l1 = gen_new_label();
2988 gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
2989 gen_jmp_tb(s, 1, base + offset, s->base.pc_next);
2990 gen_set_label(l1);
2991 gen_jmp_tb(s, 0, s->pc, s->base.pc_next);
2992 } else {
2993 /* Unconditional branch. */
2994 update_cc_op(s);
2995 gen_jmp_tb(s, 0, base + offset, s->base.pc_next);
2996 }
2997 }
2998
2999 DISAS_INSN(moveq)
3000 {
3001 tcg_gen_movi_i32(DREG(insn, 9), (int8_t)insn);
3002 gen_logic_cc(s, DREG(insn, 9), OS_LONG);
3003 }
3004
3005 DISAS_INSN(mvzs)
3006 {
3007 int opsize;
3008 TCGv src;
3009 TCGv reg;
3010
3011 if (insn & 0x40)
3012 opsize = OS_WORD;
3013 else
3014 opsize = OS_BYTE;
3015 SRC_EA(env, src, opsize, (insn & 0x80) == 0, NULL);
3016 reg = DREG(insn, 9);
3017 tcg_gen_mov_i32(reg, src);
3018 gen_logic_cc(s, src, opsize);
3019 }
3020
3021 DISAS_INSN(or)
3022 {
3023 TCGv reg;
3024 TCGv dest;
3025 TCGv src;
3026 TCGv addr;
3027 int opsize;
3028
3029 opsize = insn_opsize(insn);
3030 reg = gen_extend(s, DREG(insn, 9), opsize, 0);
3031 dest = tcg_temp_new();
3032 if (insn & 0x100) {
3033 SRC_EA(env, src, opsize, 0, &addr);
3034 tcg_gen_or_i32(dest, src, reg);
3035 DEST_EA(env, insn, opsize, dest, &addr);
3036 } else {
3037 SRC_EA(env, src, opsize, 0, NULL);
3038 tcg_gen_or_i32(dest, src, reg);
3039 gen_partset_reg(opsize, DREG(insn, 9), dest);
3040 }
3041 gen_logic_cc(s, dest, opsize);
3042 }
3043
3044 DISAS_INSN(suba)
3045 {
3046 TCGv src;
3047 TCGv reg;
3048
3049 SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3050 reg = AREG(insn, 9);
3051 tcg_gen_sub_i32(reg, reg, src);
3052 }
3053
3054 static inline void gen_subx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3055 {
3056 TCGv tmp, zero;
3057
3058 gen_flush_flags(s); /* compute old Z */
3059
3060 /*
3061 * Perform subtract with borrow.
3062 * (X, N) = dest - (src + X);
3063 */
3064
3065 zero = tcg_constant_i32(0);
3066 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, src, zero, QREG_CC_X, zero);
3067 tcg_gen_sub2_i32(QREG_CC_N, QREG_CC_X, dest, zero, QREG_CC_N, QREG_CC_X);
3068 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3069 tcg_gen_andi_i32(QREG_CC_X, QREG_CC_X, 1);
3070
3071 /* Compute signed-overflow for subtract. */
3072
3073 tmp = tcg_temp_new();
3074 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, dest);
3075 tcg_gen_xor_i32(tmp, dest, src);
3076 tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, tmp);
3077
3078 /* Copy the rest of the results into place. */
3079 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3080 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3081
3082 set_cc_op(s, CC_OP_FLAGS);
3083
3084 /* result is in QREG_CC_N */
3085 }
3086
3087 DISAS_INSN(subx_reg)
3088 {
3089 TCGv dest;
3090 TCGv src;
3091 int opsize;
3092
3093 opsize = insn_opsize(insn);
3094
3095 src = gen_extend(s, DREG(insn, 0), opsize, 1);
3096 dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3097
3098 gen_subx(s, src, dest, opsize);
3099
3100 gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3101 }
3102
3103 DISAS_INSN(subx_mem)
3104 {
3105 TCGv src;
3106 TCGv addr_src;
3107 TCGv dest;
3108 TCGv addr_dest;
3109 int opsize;
3110
3111 opsize = insn_opsize(insn);
3112
3113 addr_src = AREG(insn, 0);
3114 tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3115 src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3116
3117 addr_dest = AREG(insn, 9);
3118 tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3119 dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3120
3121 gen_subx(s, src, dest, opsize);
3122
3123 gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3124 }
3125
3126 DISAS_INSN(mov3q)
3127 {
3128 TCGv src;
3129 int val;
3130
3131 val = (insn >> 9) & 7;
3132 if (val == 0) {
3133 val = -1;
3134 }
3135 src = tcg_constant_i32(val);
3136 gen_logic_cc(s, src, OS_LONG);
3137 DEST_EA(env, insn, OS_LONG, src, NULL);
3138 }
3139
3140 DISAS_INSN(cmp)
3141 {
3142 TCGv src;
3143 TCGv reg;
3144 int opsize;
3145
3146 opsize = insn_opsize(insn);
3147 SRC_EA(env, src, opsize, 1, NULL);
3148 reg = gen_extend(s, DREG(insn, 9), opsize, 1);
3149 gen_update_cc_cmp(s, reg, src, opsize);
3150 }
3151
3152 DISAS_INSN(cmpa)
3153 {
3154 int opsize;
3155 TCGv src;
3156 TCGv reg;
3157
3158 if (insn & 0x100) {
3159 opsize = OS_LONG;
3160 } else {
3161 opsize = OS_WORD;
3162 }
3163 SRC_EA(env, src, opsize, 1, NULL);
3164 reg = AREG(insn, 9);
3165 gen_update_cc_cmp(s, reg, src, OS_LONG);
3166 }
3167
3168 DISAS_INSN(cmpm)
3169 {
3170 int opsize = insn_opsize(insn);
3171 TCGv src, dst;
3172
3173 /* Post-increment load (mode 3) from Ay. */
3174 src = gen_ea_mode(env, s, 3, REG(insn, 0), opsize,
3175 NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3176 /* Post-increment load (mode 3) from Ax. */
3177 dst = gen_ea_mode(env, s, 3, REG(insn, 9), opsize,
3178 NULL_QREG, NULL, EA_LOADS, IS_USER(s));
3179
3180 gen_update_cc_cmp(s, dst, src, opsize);
3181 }
3182
3183 DISAS_INSN(eor)
3184 {
3185 TCGv src;
3186 TCGv dest;
3187 TCGv addr;
3188 int opsize;
3189
3190 opsize = insn_opsize(insn);
3191
3192 SRC_EA(env, src, opsize, 0, &addr);
3193 dest = tcg_temp_new();
3194 tcg_gen_xor_i32(dest, src, DREG(insn, 9));
3195 gen_logic_cc(s, dest, opsize);
3196 DEST_EA(env, insn, opsize, dest, &addr);
3197 }
3198
3199 static void do_exg(TCGv reg1, TCGv reg2)
3200 {
3201 TCGv temp = tcg_temp_new();
3202 tcg_gen_mov_i32(temp, reg1);
3203 tcg_gen_mov_i32(reg1, reg2);
3204 tcg_gen_mov_i32(reg2, temp);
3205 }
3206
3207 DISAS_INSN(exg_dd)
3208 {
3209 /* exchange Dx and Dy */
3210 do_exg(DREG(insn, 9), DREG(insn, 0));
3211 }
3212
3213 DISAS_INSN(exg_aa)
3214 {
3215 /* exchange Ax and Ay */
3216 do_exg(AREG(insn, 9), AREG(insn, 0));
3217 }
3218
3219 DISAS_INSN(exg_da)
3220 {
3221 /* exchange Dx and Ay */
3222 do_exg(DREG(insn, 9), AREG(insn, 0));
3223 }
3224
3225 DISAS_INSN(and)
3226 {
3227 TCGv src;
3228 TCGv reg;
3229 TCGv dest;
3230 TCGv addr;
3231 int opsize;
3232
3233 dest = tcg_temp_new();
3234
3235 opsize = insn_opsize(insn);
3236 reg = DREG(insn, 9);
3237 if (insn & 0x100) {
3238 SRC_EA(env, src, opsize, 0, &addr);
3239 tcg_gen_and_i32(dest, src, reg);
3240 DEST_EA(env, insn, opsize, dest, &addr);
3241 } else {
3242 SRC_EA(env, src, opsize, 0, NULL);
3243 tcg_gen_and_i32(dest, src, reg);
3244 gen_partset_reg(opsize, reg, dest);
3245 }
3246 gen_logic_cc(s, dest, opsize);
3247 }
3248
3249 DISAS_INSN(adda)
3250 {
3251 TCGv src;
3252 TCGv reg;
3253
3254 SRC_EA(env, src, (insn & 0x100) ? OS_LONG : OS_WORD, 1, NULL);
3255 reg = AREG(insn, 9);
3256 tcg_gen_add_i32(reg, reg, src);
3257 }
3258
3259 static inline void gen_addx(DisasContext *s, TCGv src, TCGv dest, int opsize)
3260 {
3261 TCGv tmp, zero;
3262
3263 gen_flush_flags(s); /* compute old Z */
3264
3265 /*
3266 * Perform addition with carry.
3267 * (X, N) = src + dest + X;
3268 */
3269
3270 zero = tcg_constant_i32(0);
3271 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_X, zero, dest, zero);
3272 tcg_gen_add2_i32(QREG_CC_N, QREG_CC_X, QREG_CC_N, QREG_CC_X, src, zero);
3273 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3274
3275 /* Compute signed-overflow for addition. */
3276
3277 tmp = tcg_temp_new();
3278 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3279 tcg_gen_xor_i32(tmp, dest, src);
3280 tcg_gen_andc_i32(QREG_CC_V, QREG_CC_V, tmp);
3281
3282 /* Copy the rest of the results into place. */
3283 tcg_gen_or_i32(QREG_CC_Z, QREG_CC_Z, QREG_CC_N); /* !Z is sticky */
3284 tcg_gen_mov_i32(QREG_CC_C, QREG_CC_X);
3285
3286 set_cc_op(s, CC_OP_FLAGS);
3287
3288 /* result is in QREG_CC_N */
3289 }
3290
3291 DISAS_INSN(addx_reg)
3292 {
3293 TCGv dest;
3294 TCGv src;
3295 int opsize;
3296
3297 opsize = insn_opsize(insn);
3298
3299 dest = gen_extend(s, DREG(insn, 9), opsize, 1);
3300 src = gen_extend(s, DREG(insn, 0), opsize, 1);
3301
3302 gen_addx(s, src, dest, opsize);
3303
3304 gen_partset_reg(opsize, DREG(insn, 9), QREG_CC_N);
3305 }
3306
3307 DISAS_INSN(addx_mem)
3308 {
3309 TCGv src;
3310 TCGv addr_src;
3311 TCGv dest;
3312 TCGv addr_dest;
3313 int opsize;
3314
3315 opsize = insn_opsize(insn);
3316
3317 addr_src = AREG(insn, 0);
3318 tcg_gen_subi_i32(addr_src, addr_src, opsize_bytes(opsize));
3319 src = gen_load(s, opsize, addr_src, 1, IS_USER(s));
3320
3321 addr_dest = AREG(insn, 9);
3322 tcg_gen_subi_i32(addr_dest, addr_dest, opsize_bytes(opsize));
3323 dest = gen_load(s, opsize, addr_dest, 1, IS_USER(s));
3324
3325 gen_addx(s, src, dest, opsize);
3326
3327 gen_store(s, opsize, addr_dest, QREG_CC_N, IS_USER(s));
3328 }
3329
3330 static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
3331 {
3332 int count = (insn >> 9) & 7;
3333 int logical = insn & 8;
3334 int left = insn & 0x100;
3335 int bits = opsize_bytes(opsize) * 8;
3336 TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3337
3338 if (count == 0) {
3339 count = 8;
3340 }
3341
3342 tcg_gen_movi_i32(QREG_CC_V, 0);
3343 if (left) {
3344 tcg_gen_shri_i32(QREG_CC_C, reg, bits - count);
3345 tcg_gen_shli_i32(QREG_CC_N, reg, count);
3346
3347 /*
3348 * Note that ColdFire always clears V (done above),
3349 * while M68000 sets if the most significant bit is changed at
3350 * any time during the shift operation.
3351 */
3352 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3353 /* if shift count >= bits, V is (reg != 0) */
3354 if (count >= bits) {
3355 tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V);
3356 } else {
3357 TCGv t0 = tcg_temp_new();
3358 tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1);
3359 tcg_gen_sari_i32(t0, reg, bits - count - 1);
3360 tcg_gen_negsetcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0);
3361 }
3362 }
3363 } else {
3364 tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
3365 if (logical) {
3366 tcg_gen_shri_i32(QREG_CC_N, reg, count);
3367 } else {
3368 tcg_gen_sari_i32(QREG_CC_N, reg, count);
3369 }
3370 }
3371
3372 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3373 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3374 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3375 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3376
3377 gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3378 set_cc_op(s, CC_OP_FLAGS);
3379 }
3380
3381 static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
3382 {
3383 int logical = insn & 8;
3384 int left = insn & 0x100;
3385 int bits = opsize_bytes(opsize) * 8;
3386 TCGv reg = gen_extend(s, DREG(insn, 0), opsize, !logical);
3387 TCGv s32;
3388 TCGv_i64 t64, s64;
3389
3390 t64 = tcg_temp_new_i64();
3391 s64 = tcg_temp_new_i64();
3392 s32 = tcg_temp_new();
3393
3394 /*
3395 * Note that m68k truncates the shift count modulo 64, not 32.
3396 * In addition, a 64-bit shift makes it easy to find "the last
3397 * bit shifted out", for the carry flag.
3398 */
3399 tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
3400 tcg_gen_extu_i32_i64(s64, s32);
3401 tcg_gen_extu_i32_i64(t64, reg);
3402
3403 /* Optimistically set V=0. Also used as a zero source below. */
3404 tcg_gen_movi_i32(QREG_CC_V, 0);
3405 if (left) {
3406 tcg_gen_shl_i64(t64, t64, s64);
3407
3408 if (opsize == OS_LONG) {
3409 tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
3410 /* Note that C=0 if shift count is 0, and we get that for free. */
3411 } else {
3412 TCGv zero = tcg_constant_i32(0);
3413 tcg_gen_extrl_i64_i32(QREG_CC_N, t64);
3414 tcg_gen_shri_i32(QREG_CC_C, QREG_CC_N, bits);
3415 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3416 s32, zero, zero, QREG_CC_C);
3417 }
3418 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3419
3420 /* X = C, but only if the shift count was non-zero. */
3421 tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3422 QREG_CC_C, QREG_CC_X);
3423
3424 /*
3425 * M68000 sets V if the most significant bit is changed at
3426 * any time during the shift operation. Do this via creating
3427 * an extension of the sign bit, comparing, and discarding
3428 * the bits below the sign bit. I.e.
3429 * int64_t s = (intN_t)reg;
3430 * int64_t t = (int64_t)(intN_t)reg << count;
3431 * V = ((s ^ t) & (-1 << (bits - 1))) != 0
3432 */
3433 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3434 TCGv_i64 tt = tcg_constant_i64(32);
3435 /* if shift is greater than 32, use 32 */
3436 tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64);
3437 /* Sign extend the input to 64 bits; re-do the shift. */
3438 tcg_gen_ext_i32_i64(t64, reg);
3439 tcg_gen_shl_i64(s64, t64, s64);
3440 /* Clear all bits that are unchanged. */
3441 tcg_gen_xor_i64(t64, t64, s64);
3442 /* Ignore the bits below the sign bit. */
3443 tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
3444 /* If any bits remain set, we have overflow. */
3445 tcg_gen_negsetcond_i64(TCG_COND_NE, t64, t64, tcg_constant_i64(0));
3446 tcg_gen_extrl_i64_i32(QREG_CC_V, t64);
3447 }
3448 } else {
3449 tcg_gen_shli_i64(t64, t64, 32);
3450 if (logical) {
3451 tcg_gen_shr_i64(t64, t64, s64);
3452 } else {
3453 tcg_gen_sar_i64(t64, t64, s64);
3454 }
3455 tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
3456
3457 /* Note that C=0 if shift count is 0, and we get that for free. */
3458 tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
3459
3460 /* X = C, but only if the shift count was non-zero. */
3461 tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
3462 QREG_CC_C, QREG_CC_X);
3463 }
3464 gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
3465 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3466
3467 /* Write back the result. */
3468 gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
3469 set_cc_op(s, CC_OP_FLAGS);
3470 }
3471
3472 DISAS_INSN(shift8_im)
3473 {
3474 shift_im(s, insn, OS_BYTE);
3475 }
3476
3477 DISAS_INSN(shift16_im)
3478 {
3479 shift_im(s, insn, OS_WORD);
3480 }
3481
3482 DISAS_INSN(shift_im)
3483 {
3484 shift_im(s, insn, OS_LONG);
3485 }
3486
3487 DISAS_INSN(shift8_reg)
3488 {
3489 shift_reg(s, insn, OS_BYTE);
3490 }
3491
3492 DISAS_INSN(shift16_reg)
3493 {
3494 shift_reg(s, insn, OS_WORD);
3495 }
3496
3497 DISAS_INSN(shift_reg)
3498 {
3499 shift_reg(s, insn, OS_LONG);
3500 }
3501
3502 DISAS_INSN(shift_mem)
3503 {
3504 int logical = insn & 8;
3505 int left = insn & 0x100;
3506 TCGv src;
3507 TCGv addr;
3508
3509 SRC_EA(env, src, OS_WORD, !logical, &addr);
3510 tcg_gen_movi_i32(QREG_CC_V, 0);
3511 if (left) {
3512 tcg_gen_shri_i32(QREG_CC_C, src, 15);
3513 tcg_gen_shli_i32(QREG_CC_N, src, 1);
3514
3515 /*
3516 * Note that ColdFire always clears V,
3517 * while M68000 sets if the most significant bit is changed at
3518 * any time during the shift operation
3519 */
3520 if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) {
3521 src = gen_extend(s, src, OS_WORD, 1);
3522 tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
3523 }
3524 } else {
3525 tcg_gen_mov_i32(QREG_CC_C, src);
3526 if (logical) {
3527 tcg_gen_shri_i32(QREG_CC_N, src, 1);
3528 } else {
3529 tcg_gen_sari_i32(QREG_CC_N, src, 1);
3530 }
3531 }
3532
3533 gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1);
3534 tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
3535 tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
3536 tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
3537
3538 DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr);
3539 set_cc_op(s, CC_OP_FLAGS);
3540 }
3541
3542 static void rotate(TCGv reg, TCGv shift, int left, int size)
3543 {
3544 switch (size) {
3545 case 8:
3546 /* Replicate the 8-bit input so that a 32-bit rotate works. */
3547 tcg_gen_ext8u_i32(reg, reg);
3548 tcg_gen_muli_i32(reg, reg, 0x01010101);
3549 goto do_long;
3550 case 16:
3551 /* Replicate the 16-bit input so that a 32-bit rotate works. */
3552 tcg_gen_deposit_i32(reg, reg, reg, 16, 16);
3553 goto do_long;
3554 do_long:
3555 default:
3556 if (left) {
3557 tcg_gen_rotl_i32(reg, reg, shift);
3558 } else {
3559 tcg_gen_rotr_i32(reg, reg, shift);
3560 }
3561 }
3562
3563 /* compute flags */
3564
3565 switch (size) {
3566 case 8:
3567 tcg_gen_ext8s_i32(reg, reg);
3568 break;
3569 case 16:
3570 tcg_gen_ext16s_i32(reg, reg);
3571 break;
3572 default:
3573 break;
3574 }
3575
3576 /* QREG_CC_X is not affected */
3577
3578 tcg_gen_mov_i32(QREG_CC_N, reg);
3579 tcg_gen_mov_i32(QREG_CC_Z, reg);
3580
3581 if (left) {
3582 tcg_gen_andi_i32(QREG_CC_C, reg, 1);
3583 } else {
3584 tcg_gen_shri_i32(QREG_CC_C, reg, 31);
3585 }
3586
3587 tcg_gen_movi_i32(QREG_CC_V, 0); /* always cleared */
3588 }
3589
3590 static void rotate_x_flags(TCGv reg, TCGv X, int size)
3591 {
3592 switch (size) {
3593 case 8:
3594 tcg_gen_ext8s_i32(reg, reg);
3595 break;
3596 case 16:
3597 tcg_gen_ext16s_i32(reg, reg);
3598 break;
3599 default:
3600 break;
3601 }
3602 tcg_gen_mov_i32(QREG_CC_N, reg);
3603 tcg_gen_mov_i32(QREG_CC_Z, reg);
3604 tcg_gen_mov_i32(QREG_CC_X, X);
3605 tcg_gen_mov_i32(QREG_CC_C, X);
3606 tcg_gen_movi_i32(QREG_CC_V, 0);
3607 }
3608
3609 /* Result of rotate_x() is valid if 0 <= shift <= size */
3610 static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size)
3611 {
3612 TCGv X, shl, shr, shx, sz, zero;
3613
3614 sz = tcg_constant_i32(size);
3615
3616 shr = tcg_temp_new();
3617 shl = tcg_temp_new();
3618 shx = tcg_temp_new();
3619 if (left) {
3620 tcg_gen_mov_i32(shl, shift); /* shl = shift */
3621 tcg_gen_movi_i32(shr, size + 1);
3622 tcg_gen_sub_i32(shr, shr, shift); /* shr = size + 1 - shift */
3623 tcg_gen_subi_i32(shx, shift, 1); /* shx = shift - 1 */
3624 /* shx = shx < 0 ? size : shx; */
3625 zero = tcg_constant_i32(0);
3626 tcg_gen_movcond_i32(TCG_COND_LT, shx, shx, zero, sz, shx);
3627 } else {
3628 tcg_gen_mov_i32(shr, shift); /* shr = shift */
3629 tcg_gen_movi_i32(shl, size + 1);
3630 tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */
3631 tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */
3632 }
3633
3634 /* reg = (reg << shl) | (reg >> shr) | (x << shx); */
3635
3636 tcg_gen_shl_i32(shl, reg, shl);
3637 tcg_gen_shr_i32(shr, reg, shr);
3638 tcg_gen_or_i32(reg, shl, shr);
3639 tcg_gen_shl_i32(shx, QREG_CC_X, shx);
3640 tcg_gen_or_i32(reg, reg, shx);
3641
3642 /* X = (reg >> size) & 1 */
3643
3644 X = tcg_temp_new();
3645 tcg_gen_extract_i32(X, reg, size, 1);
3646
3647 return X;
3648 }
3649
3650 /* Result of rotate32_x() is valid if 0 <= shift < 33 */
3651 static TCGv rotate32_x(TCGv reg, TCGv shift, int left)
3652 {
3653 TCGv_i64 t0, shift64;
3654 TCGv X, lo, hi, zero;
3655
3656 shift64 = tcg_temp_new_i64();
3657 tcg_gen_extu_i32_i64(shift64, shift);
3658
3659 t0 = tcg_temp_new_i64();
3660
3661 X = tcg_temp_new();
3662 lo = tcg_temp_new();
3663 hi = tcg_temp_new();
3664
3665 if (left) {
3666 /* create [reg:X:..] */
3667
3668 tcg_gen_shli_i32(lo, QREG_CC_X, 31);
3669 tcg_gen_concat_i32_i64(t0, lo, reg);
3670
3671 /* rotate */
3672
3673 tcg_gen_rotl_i64(t0, t0, shift64);
3674
3675 /* result is [reg:..:reg:X] */
3676
3677 tcg_gen_extr_i64_i32(lo, hi, t0);
3678 tcg_gen_andi_i32(X, lo, 1);
3679
3680 tcg_gen_shri_i32(lo, lo, 1);
3681 } else {
3682 /* create [..:X:reg] */
3683
3684 tcg_gen_concat_i32_i64(t0, reg, QREG_CC_X);
3685
3686 tcg_gen_rotr_i64(t0, t0, shift64);
3687
3688 /* result is value: [X:reg:..:reg] */
3689
3690 tcg_gen_extr_i64_i32(lo, hi, t0);
3691
3692 /* extract X */
3693
3694 tcg_gen_shri_i32(X, hi, 31);
3695
3696 /* extract result */
3697
3698 tcg_gen_shli_i32(hi, hi, 1);
3699 }
3700 tcg_gen_or_i32(lo, lo, hi);
3701
3702 /* if shift == 0, register and X are not affected */
3703
3704 zero = tcg_constant_i32(0);
3705 tcg_gen_movcond_i32(TCG_COND_EQ, X, shift, zero, QREG_CC_X, X);
3706 tcg_gen_movcond_i32(TCG_COND_EQ, reg, shift, zero, reg, lo);
3707
3708 return X;
3709 }
3710
3711 DISAS_INSN(rotate_im)
3712 {
3713 TCGv shift;
3714 int tmp;
3715 int left = (insn & 0x100);
3716
3717 tmp = (insn >> 9) & 7;
3718 if (tmp == 0) {
3719 tmp = 8;
3720 }
3721
3722 shift = tcg_constant_i32(tmp);
3723 if (insn & 8) {
3724 rotate(DREG(insn, 0), shift, left, 32);
3725 } else {
3726 TCGv X = rotate32_x(DREG(insn, 0), shift, left);
3727 rotate_x_flags(DREG(insn, 0), X, 32);
3728 }
3729
3730 set_cc_op(s, CC_OP_FLAGS);
3731 }
3732
3733 DISAS_INSN(rotate8_im)
3734 {
3735 int left = (insn & 0x100);
3736 TCGv reg;
3737 TCGv shift;
3738 int tmp;
3739
3740 reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3741
3742 tmp = (insn >> 9) & 7;
3743 if (tmp == 0) {
3744 tmp = 8;
3745 }
3746
3747 shift = tcg_constant_i32(tmp);
3748 if (insn & 8) {
3749 rotate(reg, shift, left, 8);
3750 } else {
3751 TCGv X = rotate_x(reg, shift, left, 8);
3752 rotate_x_flags(reg, X, 8);
3753 }
3754 gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3755 set_cc_op(s, CC_OP_FLAGS);
3756 }
3757
3758 DISAS_INSN(rotate16_im)
3759 {
3760 int left = (insn & 0x100);
3761 TCGv reg;
3762 TCGv shift;
3763 int tmp;
3764
3765 reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
3766 tmp = (insn >> 9) & 7;
3767 if (tmp == 0) {
3768 tmp = 8;
3769 }
3770
3771 shift = tcg_constant_i32(tmp);
3772 if (insn & 8) {
3773 rotate(reg, shift, left, 16);
3774 } else {
3775 TCGv X = rotate_x(reg, shift, left, 16);
3776 rotate_x_flags(reg, X, 16);
3777 }
3778 gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
3779 set_cc_op(s, CC_OP_FLAGS);
3780 }
3781
3782 DISAS_INSN(rotate_reg)
3783 {
3784 TCGv reg;
3785 TCGv src;
3786 TCGv t0, t1;
3787 int left = (insn & 0x100);
3788
3789 reg = DREG(insn, 0);
3790 src = DREG(insn, 9);
3791 /* shift in [0..63] */
3792 t0 = tcg_temp_new();
3793 tcg_gen_andi_i32(t0, src, 63);
3794 t1 = tcg_temp_new_i32();
3795 if (insn & 8) {
3796 tcg_gen_andi_i32(t1, src, 31);
3797 rotate(reg, t1, left, 32);
3798 /* if shift == 0, clear C */
3799 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3800 t0, QREG_CC_V /* 0 */,
3801 QREG_CC_V /* 0 */, QREG_CC_C);
3802 } else {
3803 TCGv X;
3804 /* modulo 33 */
3805 tcg_gen_movi_i32(t1, 33);
3806 tcg_gen_remu_i32(t1, t0, t1);
3807 X = rotate32_x(DREG(insn, 0), t1, left);
3808 rotate_x_flags(DREG(insn, 0), X, 32);
3809 }
3810 set_cc_op(s, CC_OP_FLAGS);
3811 }
3812
3813 DISAS_INSN(rotate8_reg)
3814 {
3815 TCGv reg;
3816 TCGv src;
3817 TCGv t0, t1;
3818 int left = (insn & 0x100);
3819
3820 reg = gen_extend(s, DREG(insn, 0), OS_BYTE, 0);
3821 src = DREG(insn, 9);
3822 /* shift in [0..63] */
3823 t0 = tcg_temp_new_i32();
3824 tcg_gen_andi_i32(t0, src, 63);
3825 t1 = tcg_temp_new_i32();
3826 if (insn & 8) {
3827 tcg_gen_andi_i32(t1, src, 7);
3828 rotate(reg, t1, left, 8);
3829 /* if shift == 0, clear C */
3830 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3831 t0, QREG_CC_V /* 0 */,
3832 QREG_CC_V /* 0 */, QREG_CC_C);
3833 } else {
3834 TCGv X;
3835 /* modulo 9 */
3836 tcg_gen_movi_i32(t1, 9);
3837 tcg_gen_remu_i32(t1, t0, t1);
3838 X = rotate_x(reg, t1, left, 8);
3839 rotate_x_flags(reg, X, 8);
3840 }
3841 gen_partset_reg(OS_BYTE, DREG(insn, 0), reg);
3842 set_cc_op(s, CC_OP_FLAGS);
3843 }
3844
3845 DISAS_INSN(rotate16_reg)
3846 {
3847 TCGv reg;
3848 TCGv src;
3849 TCGv t0, t1;
3850 int left = (insn & 0x100);
3851
3852 reg = gen_extend(s, DREG(insn, 0), OS_WORD, 0);
3853 src = DREG(insn, 9);
3854 /* shift in [0..63] */
3855 t0 = tcg_temp_new_i32();
3856 tcg_gen_andi_i32(t0, src, 63);
3857 t1 = tcg_temp_new_i32();
3858 if (insn & 8) {
3859 tcg_gen_andi_i32(t1, src, 15);
3860 rotate(reg, t1, left, 16);
3861 /* if shift == 0, clear C */
3862 tcg_gen_movcond_i32(TCG_COND_EQ, QREG_CC_C,
3863 t0, QREG_CC_V /* 0 */,
3864 QREG_CC_V /* 0 */, QREG_CC_C);
3865 } else {
3866 TCGv X;
3867 /* modulo 17 */
3868 tcg_gen_movi_i32(t1, 17);
3869 tcg_gen_remu_i32(t1, t0, t1);
3870 X = rotate_x(reg, t1, left, 16);
3871 rotate_x_flags(reg, X, 16);
3872 }
3873 gen_partset_reg(OS_WORD, DREG(insn, 0), reg);
3874 set_cc_op(s, CC_OP_FLAGS);
3875 }
3876
3877 DISAS_INSN(rotate_mem)
3878 {
3879 TCGv src;
3880 TCGv addr;
3881 TCGv shift;
3882 int left = (insn & 0x100);
3883
3884 SRC_EA(env, src, OS_WORD, 0, &addr);
3885
3886 shift = tcg_constant_i32(1);
3887 if (insn & 0x0200) {
3888 rotate(src, shift, left, 16);
3889 } else {
3890 TCGv X = rotate_x(src, shift, left, 16);
3891 rotate_x_flags(src, X, 16);
3892 }
3893 DEST_EA(env, insn, OS_WORD, src, &addr);
3894 set_cc_op(s, CC_OP_FLAGS);
3895 }
3896
3897 DISAS_INSN(bfext_reg)
3898 {
3899 int ext = read_im16(env, s);
3900 int is_sign = insn & 0x200;
3901 TCGv src = DREG(insn, 0);
3902 TCGv dst = DREG(ext, 12);
3903 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
3904 int ofs = extract32(ext, 6, 5); /* big bit-endian */
3905 int pos = 32 - ofs - len; /* little bit-endian */
3906 TCGv tmp = tcg_temp_new();
3907 TCGv shift;
3908
3909 /*
3910 * In general, we're going to rotate the field so that it's at the
3911 * top of the word and then right-shift by the complement of the
3912 * width to extend the field.
3913 */
3914 if (ext & 0x20) {
3915 /* Variable width. */
3916 if (ext & 0x800) {
3917 /* Variable offset. */
3918 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
3919 tcg_gen_rotl_i32(tmp, src, tmp);
3920 } else {
3921 tcg_gen_rotli_i32(tmp, src, ofs);
3922 }
3923
3924 shift = tcg_temp_new();
3925 tcg_gen_neg_i32(shift, DREG(ext, 0));
3926 tcg_gen_andi_i32(shift, shift, 31);
3927 tcg_gen_sar_i32(QREG_CC_N, tmp, shift);
3928 if (is_sign) {
3929 tcg_gen_mov_i32(dst, QREG_CC_N);
3930 } else {
3931 tcg_gen_shr_i32(dst, tmp, shift);
3932 }
3933 } else {
3934 /* Immediate width. */
3935 if (ext & 0x800) {
3936 /* Variable offset */
3937 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
3938 tcg_gen_rotl_i32(tmp, src, tmp);
3939 src = tmp;
3940 pos = 32 - len;
3941 } else {
3942 /*
3943 * Immediate offset. If the field doesn't wrap around the
3944 * end of the word, rely on (s)extract completely.
3945 */
3946 if (pos < 0) {
3947 tcg_gen_rotli_i32(tmp, src, ofs);
3948 src = tmp;
3949 pos = 32 - len;
3950 }
3951 }
3952
3953 tcg_gen_sextract_i32(QREG_CC_N, src, pos, len);
3954 if (is_sign) {
3955 tcg_gen_mov_i32(dst, QREG_CC_N);
3956 } else {
3957 tcg_gen_extract_i32(dst, src, pos, len);
3958 }
3959 }
3960
3961 set_cc_op(s, CC_OP_LOGIC);
3962 }
3963
3964 DISAS_INSN(bfext_mem)
3965 {
3966 int ext = read_im16(env, s);
3967 int is_sign = insn & 0x200;
3968 TCGv dest = DREG(ext, 12);
3969 TCGv addr, len, ofs;
3970
3971 addr = gen_lea(env, s, insn, OS_UNSIZED);
3972 if (IS_NULL_QREG(addr)) {
3973 gen_addr_fault(s);
3974 return;
3975 }
3976
3977 if (ext & 0x20) {
3978 len = DREG(ext, 0);
3979 } else {
3980 len = tcg_constant_i32(extract32(ext, 0, 5));
3981 }
3982 if (ext & 0x800) {
3983 ofs = DREG(ext, 6);
3984 } else {
3985 ofs = tcg_constant_i32(extract32(ext, 6, 5));
3986 }
3987
3988 if (is_sign) {
3989 gen_helper_bfexts_mem(dest, tcg_env, addr, ofs, len);
3990 tcg_gen_mov_i32(QREG_CC_N, dest);
3991 } else {
3992 TCGv_i64 tmp = tcg_temp_new_i64();
3993 gen_helper_bfextu_mem(tmp, tcg_env, addr, ofs, len);
3994 tcg_gen_extr_i64_i32(dest, QREG_CC_N, tmp);
3995 }
3996 set_cc_op(s, CC_OP_LOGIC);
3997 }
3998
3999 DISAS_INSN(bfop_reg)
4000 {
4001 int ext = read_im16(env, s);
4002 TCGv src = DREG(insn, 0);
4003 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4004 int ofs = extract32(ext, 6, 5); /* big bit-endian */
4005 TCGv mask, tofs = NULL, tlen = NULL;
4006 bool is_bfffo = (insn & 0x0f00) == 0x0d00;
4007
4008 if ((ext & 0x820) == 0) {
4009 /* Immediate width and offset. */
4010 uint32_t maski = 0x7fffffffu >> (len - 1);
4011 if (ofs + len <= 32) {
4012 tcg_gen_shli_i32(QREG_CC_N, src, ofs);
4013 } else {
4014 tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4015 }
4016 tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski);
4017
4018 mask = tcg_constant_i32(ror32(maski, ofs));
4019 if (is_bfffo) {
4020 tofs = tcg_constant_i32(ofs);
4021 tlen = tcg_constant_i32(len);
4022 }
4023 } else {
4024 TCGv tmp = tcg_temp_new();
4025
4026 mask = tcg_temp_new();
4027 if (ext & 0x20) {
4028 /* Variable width */
4029 tcg_gen_subi_i32(tmp, DREG(ext, 0), 1);
4030 tcg_gen_andi_i32(tmp, tmp, 31);
4031 tcg_gen_shr_i32(mask, tcg_constant_i32(0x7fffffffu), tmp);
4032 if (is_bfffo) {
4033 tlen = tcg_temp_new();
4034 tcg_gen_addi_i32(tlen, tmp, 1);
4035 }
4036 } else {
4037 /* Immediate width */
4038 tcg_gen_movi_i32(mask, 0x7fffffffu >> (len - 1));
4039 if (is_bfffo) {
4040 tlen = tcg_constant_i32(len);
4041 }
4042 }
4043
4044 if (ext & 0x800) {
4045 /* Variable offset */
4046 tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
4047 tcg_gen_rotl_i32(QREG_CC_N, src, tmp);
4048 tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4049 tcg_gen_rotr_i32(mask, mask, tmp);
4050 if (is_bfffo) {
4051 tofs = tmp;
4052 }
4053 } else {
4054 /* Immediate offset (and variable width) */
4055 tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
4056 tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
4057 tcg_gen_rotri_i32(mask, mask, ofs);
4058 if (is_bfffo) {
4059 tofs = tcg_constant_i32(ofs);
4060 }
4061 }
4062 }
4063 set_cc_op(s, CC_OP_LOGIC);
4064
4065 switch (insn & 0x0f00) {
4066 case 0x0a00: /* bfchg */
4067 tcg_gen_eqv_i32(src, src, mask);
4068 break;
4069 case 0x0c00: /* bfclr */
4070 tcg_gen_and_i32(src, src, mask);
4071 break;
4072 case 0x0d00: /* bfffo */
4073 gen_helper_bfffo_reg(DREG(ext, 12), QREG_CC_N, tofs, tlen);
4074 break;
4075 case 0x0e00: /* bfset */
4076 tcg_gen_orc_i32(src, src, mask);
4077 break;
4078 case 0x0800: /* bftst */
4079 /* flags already set; no other work to do. */
4080 break;
4081 default:
4082 g_assert_not_reached();
4083 }
4084 }
4085
4086 DISAS_INSN(bfop_mem)
4087 {
4088 int ext = read_im16(env, s);
4089 TCGv addr, len, ofs;
4090 TCGv_i64 t64;
4091
4092 addr = gen_lea(env, s, insn, OS_UNSIZED);
4093 if (IS_NULL_QREG(addr)) {
4094 gen_addr_fault(s);
4095 return;
4096 }
4097
4098 if (ext & 0x20) {
4099 len = DREG(ext, 0);
4100 } else {
4101 len = tcg_constant_i32(extract32(ext, 0, 5));
4102 }
4103 if (ext & 0x800) {
4104 ofs = DREG(ext, 6);
4105 } else {
4106 ofs = tcg_constant_i32(extract32(ext, 6, 5));
4107 }
4108
4109 switch (insn & 0x0f00) {
4110 case 0x0a00: /* bfchg */
4111 gen_helper_bfchg_mem(QREG_CC_N, tcg_env, addr, ofs, len);
4112 break;
4113 case 0x0c00: /* bfclr */
4114 gen_helper_bfclr_mem(QREG_CC_N, tcg_env, addr, ofs, len);
4115 break;
4116 case 0x0d00: /* bfffo */
4117 t64 = tcg_temp_new_i64();
4118 gen_helper_bfffo_mem(t64, tcg_env, addr, ofs, len);
4119 tcg_gen_extr_i64_i32(DREG(ext, 12), QREG_CC_N, t64);
4120 break;
4121 case 0x0e00: /* bfset */
4122 gen_helper_bfset_mem(QREG_CC_N, tcg_env, addr, ofs, len);
4123 break;
4124 case 0x0800: /* bftst */
4125 gen_helper_bfexts_mem(QREG_CC_N, tcg_env, addr, ofs, len);
4126 break;
4127 default:
4128 g_assert_not_reached();
4129 }
4130 set_cc_op(s, CC_OP_LOGIC);
4131 }
4132
4133 DISAS_INSN(bfins_reg)
4134 {
4135 int ext = read_im16(env, s);
4136 TCGv dst = DREG(insn, 0);
4137 TCGv src = DREG(ext, 12);
4138 int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
4139 int ofs = extract32(ext, 6, 5); /* big bit-endian */
4140 int pos = 32 - ofs - len; /* little bit-endian */
4141 TCGv tmp;
4142
4143 tmp = tcg_temp_new();
4144
4145 if (ext & 0x20) {
4146 /* Variable width */
4147 tcg_gen_neg_i32(tmp, DREG(ext, 0));
4148 tcg_gen_andi_i32(tmp, tmp, 31);
4149 tcg_gen_shl_i32(QREG_CC_N, src, tmp);
4150 } else {
4151 /* Immediate width */
4152 tcg_gen_shli_i32(QREG_CC_N, src, 32 - len);
4153 }
4154 set_cc_op(s, CC_OP_LOGIC);
4155
4156 /* Immediate width and offset */
4157 if ((ext & 0x820) == 0) {
4158 /* Check for suitability for deposit. */
4159 if (pos >= 0) {
4160 tcg_gen_deposit_i32(dst, dst, src, pos, len);
4161 } else {
4162 uint32_t maski = -2U << (len - 1);
4163 uint32_t roti = (ofs + len) & 31;
4164 tcg_gen_andi_i32(tmp, src, ~maski);
4165 tcg_gen_rotri_i32(tmp, tmp, roti);
4166 tcg_gen_andi_i32(dst, dst, ror32(maski, roti));
4167 tcg_gen_or_i32(dst, dst, tmp);
4168 }
4169 } else {
4170 TCGv mask = tcg_temp_new();
4171 TCGv rot = tcg_temp_new();
4172
4173 if (ext & 0x20) {
4174 /* Variable width */
4175 tcg_gen_subi_i32(rot, DREG(ext, 0), 1);
4176 tcg_gen_andi_i32(rot, rot, 31);
4177 tcg_gen_movi_i32(mask, -2);
4178 tcg_gen_shl_i32(mask, mask, rot);
4179 tcg_gen_mov_i32(rot, DREG(ext, 0));
4180 tcg_gen_andc_i32(tmp, src, mask);
4181 } else {
4182 /* Immediate width (variable offset) */
4183 uint32_t maski = -2U << (len - 1);
4184 tcg_gen_andi_i32(tmp, src, ~maski);
4185 tcg_gen_movi_i32(mask, maski);
4186 tcg_gen_movi_i32(rot, len & 31);
4187 }
4188 if (ext & 0x800) {
4189 /* Variable offset */
4190 tcg_gen_add_i32(rot, rot, DREG(ext, 6));
4191 } else {
4192 /* Immediate offset (variable width) */
4193 tcg_gen_addi_i32(rot, rot, ofs);
4194 }
4195 tcg_gen_andi_i32(rot, rot, 31);
4196 tcg_gen_rotr_i32(mask, mask, rot);
4197 tcg_gen_rotr_i32(tmp, tmp, rot);
4198 tcg_gen_and_i32(dst, dst, mask);
4199 tcg_gen_or_i32(dst, dst, tmp);
4200 }
4201 }
4202
4203 DISAS_INSN(bfins_mem)
4204 {
4205 int ext = read_im16(env, s);
4206 TCGv src = DREG(ext, 12);
4207 TCGv addr, len, ofs;
4208
4209 addr = gen_lea(env, s, insn, OS_UNSIZED);
4210 if (IS_NULL_QREG(addr)) {
4211 gen_addr_fault(s);
4212 return;
4213 }
4214
4215 if (ext & 0x20) {
4216 len = DREG(ext, 0);
4217 } else {
4218 len = tcg_constant_i32(extract32(ext, 0, 5));
4219 }
4220 if (ext & 0x800) {
4221 ofs = DREG(ext, 6);
4222 } else {
4223 ofs = tcg_constant_i32(extract32(ext, 6, 5));
4224 }
4225
4226 gen_helper_bfins_mem(QREG_CC_N, tcg_env, addr, src, ofs, len);
4227 set_cc_op(s, CC_OP_LOGIC);
4228 }
4229
4230 DISAS_INSN(ff1)
4231 {
4232 TCGv reg;
4233 reg = DREG(insn, 0);
4234 gen_logic_cc(s, reg, OS_LONG);
4235 gen_helper_ff1(reg, reg);
4236 }
4237
4238 DISAS_INSN(chk)
4239 {
4240 TCGv src, reg, ilen;
4241 int opsize;
4242
4243 switch ((insn >> 7) & 3) {
4244 case 3:
4245 opsize = OS_WORD;
4246 break;
4247 case 2:
4248 if (m68k_feature(env, M68K_FEATURE_CHK2)) {
4249 opsize = OS_LONG;
4250 break;
4251 }
4252 /* fallthru */
4253 default:
4254 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4255 return;
4256 }
4257 SRC_EA(env, src, opsize, 1, NULL);
4258 reg = gen_extend(s, DREG(insn, 9), opsize, 1);
4259
4260 gen_flush_flags(s);
4261 ilen = tcg_constant_i32(s->pc - s->base.pc_next);
4262 gen_helper_chk(tcg_env, reg, src, ilen);
4263 }
4264
4265 DISAS_INSN(chk2)
4266 {
4267 uint16_t ext;
4268 TCGv addr1, addr2, bound1, bound2, reg, ilen;
4269 int opsize;
4270
4271 switch ((insn >> 9) & 3) {
4272 case 0:
4273 opsize = OS_BYTE;
4274 break;
4275 case 1:
4276 opsize = OS_WORD;
4277 break;
4278 case 2:
4279 opsize = OS_LONG;
4280 break;
4281 default:
4282 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4283 return;
4284 }
4285
4286 ext = read_im16(env, s);
4287
4288 addr1 = gen_lea(env, s, insn, OS_UNSIZED);
4289 addr2 = tcg_temp_new();
4290 tcg_gen_addi_i32(addr2, addr1, opsize_bytes(opsize));
4291
4292 bound1 = gen_load(s, opsize, addr1, 1, IS_USER(s));
4293 bound2 = gen_load(s, opsize, addr2, 1, IS_USER(s));
4294
4295 reg = tcg_temp_new();
4296 if (ext & 0x8000) {
4297 tcg_gen_mov_i32(reg, AREG(ext, 12));
4298 } else {
4299 gen_ext(reg, DREG(ext, 12), opsize, 1);
4300 }
4301
4302 gen_flush_flags(s);
4303 if ((ext & 0x0800) == 0) {
4304 gen_helper_cmp2(tcg_env, reg, bound1, bound2);
4305 } else {
4306 ilen = tcg_constant_i32(s->pc - s->base.pc_next);
4307 gen_helper_chk2(tcg_env, reg, bound1, bound2, ilen);
4308 }
4309 }
4310
4311 static void m68k_copy_line(TCGv dst, TCGv src, int index)
4312 {
4313 TCGv addr;
4314 TCGv_i64 t0, t1;
4315
4316 addr = tcg_temp_new();
4317
4318 t0 = tcg_temp_new_i64();
4319 t1 = tcg_temp_new_i64();
4320
4321 tcg_gen_andi_i32(addr, src, ~15);
4322 tcg_gen_qemu_ld_i64(t0, addr, index, MO_TEUQ);
4323 tcg_gen_addi_i32(addr, addr, 8);
4324 tcg_gen_qemu_ld_i64(t1, addr, index, MO_TEUQ);
4325
4326 tcg_gen_andi_i32(addr, dst, ~15);
4327 tcg_gen_qemu_st_i64(t0, addr, index, MO_TEUQ);
4328 tcg_gen_addi_i32(addr, addr, 8);
4329 tcg_gen_qemu_st_i64(t1, addr, index, MO_TEUQ);
4330 }
4331
4332 DISAS_INSN(move16_reg)
4333 {
4334 int index = IS_USER(s);
4335 TCGv tmp;
4336 uint16_t ext;
4337
4338 ext = read_im16(env, s);
4339 if ((ext & (1 << 15)) == 0) {
4340 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4341 }
4342
4343 m68k_copy_line(AREG(ext, 12), AREG(insn, 0), index);
4344
4345 /* Ax can be Ay, so save Ay before incrementing Ax */
4346 tmp = tcg_temp_new();
4347 tcg_gen_mov_i32(tmp, AREG(ext, 12));
4348 tcg_gen_addi_i32(AREG(insn, 0), AREG(insn, 0), 16);
4349 tcg_gen_addi_i32(AREG(ext, 12), tmp, 16);
4350 }
4351
4352 DISAS_INSN(move16_mem)
4353 {
4354 int index = IS_USER(s);
4355 TCGv reg, addr;
4356
4357 reg = AREG(insn, 0);
4358 addr = tcg_constant_i32(read_im32(env, s));
4359
4360 if ((insn >> 3) & 1) {
4361 /* MOVE16 (xxx).L, (Ay) */
4362 m68k_copy_line(reg, addr, index);
4363 } else {
4364 /* MOVE16 (Ay), (xxx).L */
4365 m68k_copy_line(addr, reg, index);
4366 }
4367
4368 if (((insn >> 3) & 2) == 0) {
4369 /* (Ay)+ */
4370 tcg_gen_addi_i32(reg, reg, 16);
4371 }
4372 }
4373
4374 DISAS_INSN(strldsr)
4375 {
4376 uint16_t ext;
4377 uint32_t addr;
4378
4379 addr = s->pc - 2;
4380 ext = read_im16(env, s);
4381 if (ext != 0x46FC) {
4382 gen_exception(s, addr, EXCP_ILLEGAL);
4383 return;
4384 }
4385 ext = read_im16(env, s);
4386 if (IS_USER(s) || (ext & SR_S) == 0) {
4387 gen_exception(s, addr, EXCP_PRIVILEGE);
4388 return;
4389 }
4390 gen_push(s, gen_get_sr(s));
4391 gen_set_sr_im(s, ext, 0);
4392 gen_exit_tb(s);
4393 }
4394
4395 DISAS_INSN(move_from_sr)
4396 {
4397 TCGv sr;
4398
4399 if (IS_USER(s) && m68k_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV)) {
4400 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4401 return;
4402 }
4403 sr = gen_get_sr(s);
4404 DEST_EA(env, insn, OS_WORD, sr, NULL);
4405 }
4406
4407 #if !defined(CONFIG_USER_ONLY)
4408 DISAS_INSN(moves)
4409 {
4410 int opsize;
4411 uint16_t ext;
4412 TCGv reg;
4413 TCGv addr;
4414 int extend;
4415
4416 if (IS_USER(s)) {
4417 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4418 return;
4419 }
4420
4421 ext = read_im16(env, s);
4422
4423 opsize = insn_opsize(insn);
4424
4425 if (ext & 0x8000) {
4426 /* address register */
4427 reg = AREG(ext, 12);
4428 extend = 1;
4429 } else {
4430 /* data register */
4431 reg = DREG(ext, 12);
4432 extend = 0;
4433 }
4434
4435 addr = gen_lea(env, s, insn, opsize);
4436 if (IS_NULL_QREG(addr)) {
4437 gen_addr_fault(s);
4438 return;
4439 }
4440
4441 if (ext & 0x0800) {
4442 /* from reg to ea */
4443 gen_store(s, opsize, addr, reg, DFC_INDEX(s));
4444 } else {
4445 /* from ea to reg */
4446 TCGv tmp = gen_load(s, opsize, addr, 0, SFC_INDEX(s));
4447 if (extend) {
4448 gen_ext(reg, tmp, opsize, 1);
4449 } else {
4450 gen_partset_reg(opsize, reg, tmp);
4451 }
4452 }
4453 switch (extract32(insn, 3, 3)) {
4454 case 3: /* Indirect postincrement. */
4455 tcg_gen_addi_i32(AREG(insn, 0), addr,
4456 REG(insn, 0) == 7 && opsize == OS_BYTE
4457 ? 2
4458 : opsize_bytes(opsize));
4459 break;
4460 case 4: /* Indirect predecrememnt. */
4461 tcg_gen_mov_i32(AREG(insn, 0), addr);
4462 break;
4463 }
4464 }
4465
4466 DISAS_INSN(move_to_sr)
4467 {
4468 if (IS_USER(s)) {
4469 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4470 return;
4471 }
4472 gen_move_to_sr(env, s, insn, false);
4473 gen_exit_tb(s);
4474 }
4475
4476 DISAS_INSN(move_from_usp)
4477 {
4478 if (IS_USER(s)) {
4479 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4480 return;
4481 }
4482 tcg_gen_ld_i32(AREG(insn, 0), tcg_env,
4483 offsetof(CPUM68KState, sp[M68K_USP]));
4484 }
4485
4486 DISAS_INSN(move_to_usp)
4487 {
4488 if (IS_USER(s)) {
4489 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4490 return;
4491 }
4492 tcg_gen_st_i32(AREG(insn, 0), tcg_env,
4493 offsetof(CPUM68KState, sp[M68K_USP]));
4494 }
4495
4496 DISAS_INSN(halt)
4497 {
4498 if (IS_USER(s)) {
4499 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4500 return;
4501 }
4502 if (semihosting_test(s)) {
4503 gen_exception(s, s->pc, EXCP_SEMIHOSTING);
4504 return;
4505 }
4506 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
4507 offsetof(CPUState, halted) - offsetof(M68kCPU, env));
4508 gen_exception(s, s->pc, EXCP_HLT);
4509 }
4510
4511 DISAS_INSN(stop)
4512 {
4513 uint16_t ext;
4514
4515 if (IS_USER(s)) {
4516 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4517 return;
4518 }
4519
4520 ext = read_im16(env, s);
4521
4522 gen_set_sr_im(s, ext, 0);
4523 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
4524 offsetof(CPUState, halted) - offsetof(M68kCPU, env));
4525 gen_exception(s, s->pc, EXCP_HLT);
4526 }
4527
4528 DISAS_INSN(rte)
4529 {
4530 if (IS_USER(s)) {
4531 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4532 return;
4533 }
4534 gen_exception(s, s->base.pc_next, EXCP_RTE);
4535 }
4536
4537 DISAS_INSN(cf_movec)
4538 {
4539 uint16_t ext;
4540 TCGv reg;
4541
4542 if (IS_USER(s)) {
4543 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4544 return;
4545 }
4546
4547 ext = read_im16(env, s);
4548
4549 if (ext & 0x8000) {
4550 reg = AREG(ext, 12);
4551 } else {
4552 reg = DREG(ext, 12);
4553 }
4554 gen_helper_cf_movec_to(tcg_env, tcg_constant_i32(ext & 0xfff), reg);
4555 gen_exit_tb(s);
4556 }
4557
4558 DISAS_INSN(m68k_movec)
4559 {
4560 uint16_t ext;
4561 TCGv reg, creg;
4562
4563 if (IS_USER(s)) {
4564 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4565 return;
4566 }
4567
4568 ext = read_im16(env, s);
4569
4570 if (ext & 0x8000) {
4571 reg = AREG(ext, 12);
4572 } else {
4573 reg = DREG(ext, 12);
4574 }
4575 creg = tcg_constant_i32(ext & 0xfff);
4576 if (insn & 1) {
4577 gen_helper_m68k_movec_to(tcg_env, creg, reg);
4578 } else {
4579 gen_helper_m68k_movec_from(reg, tcg_env, creg);
4580 }
4581 gen_exit_tb(s);
4582 }
4583
4584 DISAS_INSN(intouch)
4585 {
4586 if (IS_USER(s)) {
4587 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4588 return;
4589 }
4590 /* ICache fetch. Implement as no-op. */
4591 }
4592
4593 DISAS_INSN(cpushl)
4594 {
4595 if (IS_USER(s)) {
4596 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4597 return;
4598 }
4599 /* Cache push/invalidate. Implement as no-op. */
4600 }
4601
4602 DISAS_INSN(cpush)
4603 {
4604 if (IS_USER(s)) {
4605 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4606 return;
4607 }
4608 /* Cache push/invalidate. Implement as no-op. */
4609 }
4610
4611 DISAS_INSN(cinv)
4612 {
4613 if (IS_USER(s)) {
4614 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4615 return;
4616 }
4617 /* Invalidate cache line. Implement as no-op. */
4618 }
4619
4620 #if !defined(CONFIG_USER_ONLY)
4621 DISAS_INSN(pflush)
4622 {
4623 TCGv opmode;
4624
4625 if (IS_USER(s)) {
4626 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4627 return;
4628 }
4629
4630 opmode = tcg_constant_i32((insn >> 3) & 3);
4631 gen_helper_pflush(tcg_env, AREG(insn, 0), opmode);
4632 }
4633
4634 DISAS_INSN(ptest)
4635 {
4636 TCGv is_read;
4637
4638 if (IS_USER(s)) {
4639 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4640 return;
4641 }
4642 is_read = tcg_constant_i32((insn >> 5) & 1);
4643 gen_helper_ptest(tcg_env, AREG(insn, 0), is_read);
4644 }
4645 #endif
4646
4647 DISAS_INSN(wddata)
4648 {
4649 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4650 }
4651
4652 DISAS_INSN(wdebug)
4653 {
4654 if (IS_USER(s)) {
4655 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
4656 return;
4657 }
4658 /* TODO: Implement wdebug. */
4659 cpu_abort(env_cpu(env), "WDEBUG not implemented");
4660 }
4661 #endif
4662
4663 DISAS_INSN(trap)
4664 {
4665 gen_exception(s, s->pc, EXCP_TRAP0 + (insn & 0xf));
4666 }
4667
4668 static void do_trapcc(DisasContext *s, DisasCompare *c)
4669 {
4670 if (c->tcond != TCG_COND_NEVER) {
4671 TCGLabel *over = NULL;
4672
4673 update_cc_op(s);
4674
4675 if (c->tcond != TCG_COND_ALWAYS) {
4676 /* Jump over if !c. */
4677 over = gen_new_label();
4678 tcg_gen_brcond_i32(tcg_invert_cond(c->tcond), c->v1, c->v2, over);
4679 }
4680
4681 tcg_gen_movi_i32(QREG_PC, s->pc);
4682 gen_raise_exception_format2(s, EXCP_TRAPCC, s->base.pc_next);
4683
4684 if (over != NULL) {
4685 gen_set_label(over);
4686 s->base.is_jmp = DISAS_NEXT;
4687 }
4688 }
4689 }
4690
4691 DISAS_INSN(trapcc)
4692 {
4693 DisasCompare c;
4694
4695 /* Consume and discard the immediate operand. */
4696 switch (extract32(insn, 0, 3)) {
4697 case 2: /* trapcc.w */
4698 (void)read_im16(env, s);
4699 break;
4700 case 3: /* trapcc.l */
4701 (void)read_im32(env, s);
4702 break;
4703 case 4: /* trapcc (no operand) */
4704 break;
4705 default:
4706 /* trapcc registered with only valid opmodes */
4707 g_assert_not_reached();
4708 }
4709
4710 gen_cc_cond(&c, s, extract32(insn, 8, 4));
4711 do_trapcc(s, &c);
4712 }
4713
4714 DISAS_INSN(trapv)
4715 {
4716 DisasCompare c;
4717
4718 gen_cc_cond(&c, s, 9); /* V set */
4719 do_trapcc(s, &c);
4720 }
4721
4722 static void gen_load_fcr(DisasContext *s, TCGv res, int reg)
4723 {
4724 switch (reg) {
4725 case M68K_FPIAR:
4726 tcg_gen_movi_i32(res, 0);
4727 break;
4728 case M68K_FPSR:
4729 gen_helper_get_fpsr(res, tcg_env);
4730 break;
4731 case M68K_FPCR:
4732 tcg_gen_ld_i32(res, tcg_env, offsetof(CPUM68KState, fpcr));
4733 break;
4734 }
4735 }
4736
4737 static void gen_store_fcr(DisasContext *s, TCGv val, int reg)
4738 {
4739 switch (reg) {
4740 case M68K_FPIAR:
4741 break;
4742 case M68K_FPSR:
4743 gen_helper_set_fpsr(tcg_env, val);
4744 break;
4745 case M68K_FPCR:
4746 gen_helper_set_fpcr(tcg_env, val);
4747 break;
4748 }
4749 }
4750
4751 static void gen_qemu_store_fcr(DisasContext *s, TCGv addr, int reg)
4752 {
4753 int index = IS_USER(s);
4754 TCGv tmp;
4755
4756 tmp = tcg_temp_new();
4757 gen_load_fcr(s, tmp, reg);
4758 tcg_gen_qemu_st_tl(tmp, addr, index, MO_TEUL);
4759 }
4760
4761 static void gen_qemu_load_fcr(DisasContext *s, TCGv addr, int reg)
4762 {
4763 int index = IS_USER(s);
4764 TCGv tmp;
4765
4766 tmp = tcg_temp_new();
4767 tcg_gen_qemu_ld_tl(tmp, addr, index, MO_TEUL);
4768 gen_store_fcr(s, tmp, reg);
4769 }
4770
4771
4772 static void gen_op_fmove_fcr(CPUM68KState *env, DisasContext *s,
4773 uint32_t insn, uint32_t ext)
4774 {
4775 int mask = (ext >> 10) & 7;
4776 int is_write = (ext >> 13) & 1;
4777 int mode = extract32(insn, 3, 3);
4778 int i;
4779 TCGv addr, tmp;
4780
4781 switch (mode) {
4782 case 0: /* Dn */
4783 if (mask != M68K_FPIAR && mask != M68K_FPSR && mask != M68K_FPCR) {
4784 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4785 return;
4786 }
4787 if (is_write) {
4788 gen_load_fcr(s, DREG(insn, 0), mask);
4789 } else {
4790 gen_store_fcr(s, DREG(insn, 0), mask);
4791 }
4792 return;
4793 case 1: /* An, only with FPIAR */
4794 if (mask != M68K_FPIAR) {
4795 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4796 return;
4797 }
4798 if (is_write) {
4799 gen_load_fcr(s, AREG(insn, 0), mask);
4800 } else {
4801 gen_store_fcr(s, AREG(insn, 0), mask);
4802 }
4803 return;
4804 case 7: /* Immediate */
4805 if (REG(insn, 0) == 4) {
4806 if (is_write ||
4807 (mask != M68K_FPIAR && mask != M68K_FPSR &&
4808 mask != M68K_FPCR)) {
4809 gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);
4810 return;
4811 }
4812 tmp = tcg_constant_i32(read_im32(env, s));
4813 gen_store_fcr(s, tmp, mask);
4814 return;
4815 }
4816 break;
4817 default:
4818 break;
4819 }
4820
4821 tmp = gen_lea(env, s, insn, OS_LONG);
4822 if (IS_NULL_QREG(tmp)) {
4823 gen_addr_fault(s);
4824 return;
4825 }
4826
4827 addr = tcg_temp_new();
4828 tcg_gen_mov_i32(addr, tmp);
4829
4830 /*
4831 * mask:
4832 *
4833 * 0b100 Floating-Point Control Register
4834 * 0b010 Floating-Point Status Register
4835 * 0b001 Floating-Point Instruction Address Register
4836 *
4837 */
4838
4839 if (is_write && mode == 4) {
4840 for (i = 2; i >= 0; i--, mask >>= 1) {
4841 if (mask & 1) {
4842 gen_qemu_store_fcr(s, addr, 1 << i);
4843 if (mask != 1) {
4844 tcg_gen_subi_i32(addr, addr, opsize_bytes(OS_LONG));
4845 }
4846 }
4847 }
4848 tcg_gen_mov_i32(AREG(insn, 0), addr);
4849 } else {
4850 for (i = 0; i < 3; i++, mask >>= 1) {
4851 if (mask & 1) {
4852 if (is_write) {
4853 gen_qemu_store_fcr(s, addr, 1 << i);
4854 } else {
4855 gen_qemu_load_fcr(s, addr, 1 << i);
4856 }
4857 if (mask != 1 || mode == 3) {
4858 tcg_gen_addi_i32(addr, addr, opsize_bytes(OS_LONG));
4859 }
4860 }
4861 }
4862 if (mode == 3) {
4863 tcg_gen_mov_i32(AREG(insn, 0), addr);
4864 }
4865 }
4866 }
4867
4868 static void gen_op_fmovem(CPUM68KState *env, DisasContext *s,
4869 uint32_t insn, uint32_t ext)
4870 {
4871 int opsize;
4872 TCGv addr, tmp;
4873 int mode = (ext >> 11) & 0x3;
4874 int is_load = ((ext & 0x2000) == 0);
4875
4876 if (m68k_feature(s->env, M68K_FEATURE_FPU)) {
4877 opsize = OS_EXTENDED;
4878 } else {
4879 opsize = OS_DOUBLE; /* FIXME */
4880 }
4881
4882 addr = gen_lea(env, s, insn, opsize);
4883 if (IS_NULL_QREG(addr)) {
4884 gen_addr_fault(s);
4885 return;
4886 }
4887
4888 tmp = tcg_temp_new();
4889 if (mode & 0x1) {
4890 /* Dynamic register list */
4891 tcg_gen_ext8u_i32(tmp, DREG(ext, 4));
4892 } else {
4893 /* Static register list */
4894 tcg_gen_movi_i32(tmp, ext & 0xff);
4895 }
4896
4897 if (!is_load && (mode & 2) == 0) {
4898 /*
4899 * predecrement addressing mode
4900 * only available to store register to memory
4901 */
4902 if (opsize == OS_EXTENDED) {
4903 gen_helper_fmovemx_st_predec(tmp, tcg_env, addr, tmp);
4904 } else {
4905 gen_helper_fmovemd_st_predec(tmp, tcg_env, addr, tmp);
4906 }
4907 } else {
4908 /* postincrement addressing mode */
4909 if (opsize == OS_EXTENDED) {
4910 if (is_load) {
4911 gen_helper_fmovemx_ld_postinc(tmp, tcg_env, addr, tmp);
4912 } else {
4913 gen_helper_fmovemx_st_postinc(tmp, tcg_env, addr, tmp);
4914 }
4915 } else {
4916 if (is_load) {
4917 gen_helper_fmovemd_ld_postinc(tmp, tcg_env, addr, tmp);
4918 } else {
4919 gen_helper_fmovemd_st_postinc(tmp, tcg_env, addr, tmp);
4920 }
4921 }
4922 }
4923 if ((insn & 070) == 030 || (insn & 070) == 040) {
4924 tcg_gen_mov_i32(AREG(insn, 0), tmp);
4925 }
4926 }
4927
4928 /*
4929 * ??? FP exceptions are not implemented. Most exceptions are deferred until
4930 * immediately before the next FP instruction is executed.
4931 */
4932 DISAS_INSN(fpu)
4933 {
4934 uint16_t ext;
4935 int opmode;
4936 int opsize;
4937 TCGv_ptr cpu_src, cpu_dest;
4938
4939 ext = read_im16(env, s);
4940 opmode = ext & 0x7f;
4941 switch ((ext >> 13) & 7) {
4942 case 0:
4943 break;
4944 case 1:
4945 goto undef;
4946 case 2:
4947 if (insn == 0xf200 && (ext & 0xfc00) == 0x5c00) {
4948 /* fmovecr */
4949 TCGv rom_offset = tcg_constant_i32(opmode);
4950 cpu_dest = gen_fp_ptr(REG(ext, 7));
4951 gen_helper_fconst(tcg_env, cpu_dest, rom_offset);
4952 return;
4953 }
4954 break;
4955 case 3: /* fmove out */
4956 cpu_src = gen_fp_ptr(REG(ext, 7));
4957 opsize = ext_opsize(ext, 10);
4958 if (gen_ea_fp(env, s, insn, opsize, cpu_src,
4959 EA_STORE, IS_USER(s)) == -1) {
4960 gen_addr_fault(s);
4961 }
4962 gen_helper_ftst(tcg_env, cpu_src);
4963 return;
4964 case 4: /* fmove to control register. */
4965 case 5: /* fmove from control register. */
4966 gen_op_fmove_fcr(env, s, insn, ext);
4967 return;
4968 case 6: /* fmovem */
4969 case 7:
4970 if ((ext & 0x1000) == 0 && !m68k_feature(s->env, M68K_FEATURE_FPU)) {
4971 goto undef;
4972 }
4973 gen_op_fmovem(env, s, insn, ext);
4974 return;
4975 }
4976 if (ext & (1 << 14)) {
4977 /* Source effective address. */
4978 opsize = ext_opsize(ext, 10);
4979 cpu_src = gen_fp_result_ptr();
4980 if (gen_ea_fp(env, s, insn, opsize, cpu_src,
4981 EA_LOADS, IS_USER(s)) == -1) {
4982 gen_addr_fault(s);
4983 return;
4984 }
4985 } else {
4986 /* Source register. */
4987 opsize = OS_EXTENDED;
4988 cpu_src = gen_fp_ptr(REG(ext, 10));
4989 }
4990 cpu_dest = gen_fp_ptr(REG(ext, 7));
4991 switch (opmode) {
4992 case 0: /* fmove */
4993 gen_fp_move(cpu_dest, cpu_src);
4994 break;
4995 case 0x40: /* fsmove */
4996 gen_helper_fsround(tcg_env, cpu_dest, cpu_src);
4997 break;
4998 case 0x44: /* fdmove */
4999 gen_helper_fdround(tcg_env, cpu_dest, cpu_src);
5000 break;
Showing first 5,000 of 6,214 lines. View raw