|
|
1.1 root 1: /*
2: * m68k translation
1.1.1.2 root 3: *
4: * Copyright (c) 2005-2007 CodeSourcery
1.1 root 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 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: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU Lesser General Public
1.1.1.4 ! root 18: * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
20: #include <stdarg.h>
21: #include <stdlib.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <inttypes.h>
25:
26: #include "config.h"
27: #include "cpu.h"
28: #include "exec-all.h"
29: #include "disas.h"
1.1.1.3 root 30: #include "tcg-op.h"
31: #include "qemu-log.h"
32:
33: #include "helpers.h"
34: #define GEN_HELPER 1
35: #include "helpers.h"
1.1 root 36:
1.1.1.2 root 37: //#define DEBUG_DISPATCH 1
38:
1.1.1.3 root 39: /* Fake floating point. */
40: #define tcg_gen_mov_f64 tcg_gen_mov_i64
41: #define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
42: #define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
43:
44: #define DEFO32(name, offset) static TCGv QREG_##name;
45: #define DEFO64(name, offset) static TCGv_i64 QREG_##name;
46: #define DEFF64(name, offset) static TCGv_i64 QREG_##name;
47: #include "qregs.def"
48: #undef DEFO32
49: #undef DEFO64
50: #undef DEFF64
51:
52: static TCGv_ptr cpu_env;
53:
54: static char cpu_reg_names[3*8*3 + 5*4];
55: static TCGv cpu_dregs[8];
56: static TCGv cpu_aregs[8];
57: static TCGv_i64 cpu_fregs[8];
58: static TCGv_i64 cpu_macc[4];
59:
60: #define DREG(insn, pos) cpu_dregs[((insn) >> (pos)) & 7]
61: #define AREG(insn, pos) cpu_aregs[((insn) >> (pos)) & 7]
62: #define FREG(insn, pos) cpu_fregs[((insn) >> (pos)) & 7]
63: #define MACREG(acc) cpu_macc[acc]
64: #define QREG_SP cpu_aregs[7]
65:
66: static TCGv NULL_QREG;
67: #define IS_NULL_QREG(t) (TCGV_EQUAL(t, NULL_QREG))
68: /* Used to distinguish stores from bad addressing modes. */
69: static TCGv store_dummy;
70:
71: #include "gen-icount.h"
72:
73: void m68k_tcg_init(void)
74: {
75: char *p;
76: int i;
77:
78: #define DEFO32(name, offset) QREG_##name = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUState, offset), #name);
79: #define DEFO64(name, offset) QREG_##name = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, offset), #name);
80: #define DEFF64(name, offset) DEFO64(name, offset)
81: #include "qregs.def"
82: #undef DEFO32
83: #undef DEFO64
84: #undef DEFF64
85:
86: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
87:
88: p = cpu_reg_names;
89: for (i = 0; i < 8; i++) {
90: sprintf(p, "D%d", i);
91: cpu_dregs[i] = tcg_global_mem_new(TCG_AREG0,
92: offsetof(CPUM68KState, dregs[i]), p);
93: p += 3;
94: sprintf(p, "A%d", i);
95: cpu_aregs[i] = tcg_global_mem_new(TCG_AREG0,
96: offsetof(CPUM68KState, aregs[i]), p);
97: p += 3;
98: sprintf(p, "F%d", i);
99: cpu_fregs[i] = tcg_global_mem_new_i64(TCG_AREG0,
100: offsetof(CPUM68KState, fregs[i]), p);
101: p += 3;
102: }
103: for (i = 0; i < 4; i++) {
104: sprintf(p, "ACC%d", i);
105: cpu_macc[i] = tcg_global_mem_new_i64(TCG_AREG0,
106: offsetof(CPUM68KState, macc[i]), p);
107: p += 5;
108: }
109:
110: NULL_QREG = tcg_global_mem_new(TCG_AREG0, -4, "NULL");
111: store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
112:
113: #define GEN_HELPER 2
114: #include "helpers.h"
115: }
116:
1.1 root 117: static inline void qemu_assert(int cond, const char *msg)
118: {
119: if (!cond) {
120: fprintf (stderr, "badness: %s\n", msg);
121: abort();
122: }
123: }
124:
125: /* internal defines */
126: typedef struct DisasContext {
1.1.1.2 root 127: CPUM68KState *env;
128: target_ulong insn_pc; /* Start of the current instruction. */
1.1 root 129: target_ulong pc;
130: int is_jmp;
131: int cc_op;
1.1.1.2 root 132: int user;
1.1 root 133: uint32_t fpcr;
134: struct TranslationBlock *tb;
135: int singlestep_enabled;
1.1.1.2 root 136: int is_mem;
1.1.1.3 root 137: TCGv_i64 mactmp;
138: int done_mac;
1.1 root 139: } DisasContext;
140:
141: #define DISAS_JUMP_NEXT 4
142:
1.1.1.2 root 143: #if defined(CONFIG_USER_ONLY)
144: #define IS_USER(s) 1
145: #else
146: #define IS_USER(s) s->user
147: #endif
148:
1.1 root 149: /* XXX: move that elsewhere */
150: /* ??? Fix exceptions. */
151: static void *gen_throws_exception;
152: #define gen_last_qop NULL
153:
154: #define OS_BYTE 0
155: #define OS_WORD 1
156: #define OS_LONG 2
157: #define OS_SINGLE 4
158: #define OS_DOUBLE 5
159:
160: typedef void (*disas_proc)(DisasContext *, uint16_t);
161:
1.1.1.2 root 162: #ifdef DEBUG_DISPATCH
163: #define DISAS_INSN(name) \
164: static void real_disas_##name (DisasContext *s, uint16_t insn); \
165: static void disas_##name (DisasContext *s, uint16_t insn) { \
1.1.1.3 root 166: qemu_log("Dispatch " #name "\n"); \
1.1.1.2 root 167: real_disas_##name(s, insn); } \
168: static void real_disas_##name (DisasContext *s, uint16_t insn)
169: #else
1.1 root 170: #define DISAS_INSN(name) \
171: static void disas_##name (DisasContext *s, uint16_t insn)
1.1.1.2 root 172: #endif
1.1 root 173:
1.1.1.3 root 174: /* FIXME: Remove this. */
175: #define gen_im32(val) tcg_const_i32(val)
176:
1.1 root 177: /* Generate a load from the specified address. Narrow values are
178: sign extended to full register width. */
1.1.1.3 root 179: static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
1.1 root 180: {
1.1.1.3 root 181: TCGv tmp;
182: int index = IS_USER(s);
1.1.1.2 root 183: s->is_mem = 1;
1.1.1.3 root 184: tmp = tcg_temp_new_i32();
1.1 root 185: switch(opsize) {
186: case OS_BYTE:
187: if (sign)
1.1.1.3 root 188: tcg_gen_qemu_ld8s(tmp, addr, index);
1.1 root 189: else
1.1.1.3 root 190: tcg_gen_qemu_ld8u(tmp, addr, index);
1.1 root 191: break;
192: case OS_WORD:
193: if (sign)
1.1.1.3 root 194: tcg_gen_qemu_ld16s(tmp, addr, index);
1.1 root 195: else
1.1.1.3 root 196: tcg_gen_qemu_ld16u(tmp, addr, index);
1.1 root 197: break;
198: case OS_LONG:
199: case OS_SINGLE:
1.1.1.3 root 200: tcg_gen_qemu_ld32u(tmp, addr, index);
1.1 root 201: break;
202: default:
203: qemu_assert(0, "bad load size");
204: }
205: gen_throws_exception = gen_last_qop;
206: return tmp;
207: }
208:
1.1.1.3 root 209: static inline TCGv_i64 gen_load64(DisasContext * s, TCGv addr)
210: {
211: TCGv_i64 tmp;
212: int index = IS_USER(s);
213: s->is_mem = 1;
214: tmp = tcg_temp_new_i64();
215: tcg_gen_qemu_ldf64(tmp, addr, index);
216: gen_throws_exception = gen_last_qop;
217: return tmp;
218: }
219:
1.1 root 220: /* Generate a store. */
1.1.1.3 root 221: static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
1.1 root 222: {
1.1.1.3 root 223: int index = IS_USER(s);
1.1.1.2 root 224: s->is_mem = 1;
1.1 root 225: switch(opsize) {
226: case OS_BYTE:
1.1.1.3 root 227: tcg_gen_qemu_st8(val, addr, index);
1.1 root 228: break;
229: case OS_WORD:
1.1.1.3 root 230: tcg_gen_qemu_st16(val, addr, index);
1.1 root 231: break;
232: case OS_LONG:
233: case OS_SINGLE:
1.1.1.3 root 234: tcg_gen_qemu_st32(val, addr, index);
1.1 root 235: break;
236: default:
237: qemu_assert(0, "bad store size");
238: }
239: gen_throws_exception = gen_last_qop;
240: }
241:
1.1.1.3 root 242: static inline void gen_store64(DisasContext *s, TCGv addr, TCGv_i64 val)
243: {
244: int index = IS_USER(s);
245: s->is_mem = 1;
246: tcg_gen_qemu_stf64(val, addr, index);
247: gen_throws_exception = gen_last_qop;
248: }
249:
250: typedef enum {
251: EA_STORE,
252: EA_LOADU,
253: EA_LOADS
254: } ea_what;
255:
1.1 root 256: /* Generate an unsigned load if VAL is 0 a signed load if val is -1,
257: otherwise generate a store. */
1.1.1.3 root 258: static TCGv gen_ldst(DisasContext *s, int opsize, TCGv addr, TCGv val,
259: ea_what what)
1.1 root 260: {
1.1.1.3 root 261: if (what == EA_STORE) {
1.1.1.2 root 262: gen_store(s, opsize, addr, val);
1.1.1.3 root 263: return store_dummy;
1.1 root 264: } else {
1.1.1.3 root 265: return gen_load(s, opsize, addr, what == EA_LOADS);
1.1.1.2 root 266: }
267: }
268:
269: /* Read a 32-bit immediate constant. */
270: static inline uint32_t read_im32(DisasContext *s)
271: {
272: uint32_t im;
273: im = ((uint32_t)lduw_code(s->pc)) << 16;
274: s->pc += 2;
275: im |= lduw_code(s->pc);
276: s->pc += 2;
277: return im;
278: }
279:
280: /* Calculate and address index. */
1.1.1.3 root 281: static TCGv gen_addr_index(uint16_t ext, TCGv tmp)
1.1.1.2 root 282: {
1.1.1.3 root 283: TCGv add;
1.1.1.2 root 284: int scale;
285:
286: add = (ext & 0x8000) ? AREG(ext, 12) : DREG(ext, 12);
287: if ((ext & 0x800) == 0) {
1.1.1.3 root 288: tcg_gen_ext16s_i32(tmp, add);
1.1.1.2 root 289: add = tmp;
290: }
291: scale = (ext >> 9) & 3;
292: if (scale != 0) {
1.1.1.3 root 293: tcg_gen_shli_i32(tmp, add, scale);
1.1.1.2 root 294: add = tmp;
1.1 root 295: }
1.1.1.2 root 296: return add;
1.1 root 297: }
298:
1.1.1.3 root 299: /* Handle a base + index + displacement effective addresss.
300: A NULL_QREG base means pc-relative. */
301: static TCGv gen_lea_indexed(DisasContext *s, int opsize, TCGv base)
1.1 root 302: {
303: uint32_t offset;
304: uint16_t ext;
1.1.1.3 root 305: TCGv add;
306: TCGv tmp;
1.1.1.2 root 307: uint32_t bd, od;
1.1 root 308:
309: offset = s->pc;
1.1.1.2 root 310: ext = lduw_code(s->pc);
1.1 root 311: s->pc += 2;
1.1.1.2 root 312:
313: if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX))
1.1.1.3 root 314: return NULL_QREG;
1.1.1.2 root 315:
316: if (ext & 0x100) {
317: /* full extension word format */
318: if (!m68k_feature(s->env, M68K_FEATURE_EXT_FULL))
1.1.1.3 root 319: return NULL_QREG;
1.1.1.2 root 320:
321: if ((ext & 0x30) > 0x10) {
322: /* base displacement */
323: if ((ext & 0x30) == 0x20) {
324: bd = (int16_t)lduw_code(s->pc);
325: s->pc += 2;
326: } else {
327: bd = read_im32(s);
328: }
329: } else {
330: bd = 0;
331: }
1.1.1.3 root 332: tmp = tcg_temp_new();
1.1.1.2 root 333: if ((ext & 0x44) == 0) {
334: /* pre-index */
335: add = gen_addr_index(ext, tmp);
336: } else {
1.1.1.3 root 337: add = NULL_QREG;
1.1.1.2 root 338: }
339: if ((ext & 0x80) == 0) {
340: /* base not suppressed */
1.1.1.3 root 341: if (IS_NULL_QREG(base)) {
1.1.1.2 root 342: base = gen_im32(offset + bd);
343: bd = 0;
344: }
1.1.1.3 root 345: if (!IS_NULL_QREG(add)) {
346: tcg_gen_add_i32(tmp, add, base);
1.1.1.2 root 347: add = tmp;
348: } else {
349: add = base;
350: }
351: }
1.1.1.3 root 352: if (!IS_NULL_QREG(add)) {
1.1.1.2 root 353: if (bd != 0) {
1.1.1.3 root 354: tcg_gen_addi_i32(tmp, add, bd);
1.1.1.2 root 355: add = tmp;
356: }
357: } else {
358: add = gen_im32(bd);
359: }
360: if ((ext & 3) != 0) {
361: /* memory indirect */
362: base = gen_load(s, OS_LONG, add, 0);
363: if ((ext & 0x44) == 4) {
364: add = gen_addr_index(ext, tmp);
1.1.1.3 root 365: tcg_gen_add_i32(tmp, add, base);
1.1.1.2 root 366: add = tmp;
367: } else {
368: add = base;
369: }
370: if ((ext & 3) > 1) {
371: /* outer displacement */
372: if ((ext & 3) == 2) {
373: od = (int16_t)lduw_code(s->pc);
374: s->pc += 2;
375: } else {
376: od = read_im32(s);
377: }
378: } else {
379: od = 0;
380: }
381: if (od != 0) {
1.1.1.3 root 382: tcg_gen_addi_i32(tmp, add, od);
1.1.1.2 root 383: add = tmp;
384: }
385: }
1.1 root 386: } else {
1.1.1.2 root 387: /* brief extension word format */
1.1.1.3 root 388: tmp = tcg_temp_new();
1.1.1.2 root 389: add = gen_addr_index(ext, tmp);
1.1.1.3 root 390: if (!IS_NULL_QREG(base)) {
391: tcg_gen_add_i32(tmp, add, base);
1.1.1.2 root 392: if ((int8_t)ext)
1.1.1.3 root 393: tcg_gen_addi_i32(tmp, tmp, (int8_t)ext);
1.1.1.2 root 394: } else {
1.1.1.3 root 395: tcg_gen_addi_i32(tmp, add, offset + (int8_t)ext);
1.1.1.2 root 396: }
397: add = tmp;
1.1 root 398: }
1.1.1.2 root 399: return add;
1.1 root 400: }
401:
402: /* Update the CPU env CC_OP state. */
403: static inline void gen_flush_cc_op(DisasContext *s)
404: {
405: if (s->cc_op != CC_OP_DYNAMIC)
1.1.1.3 root 406: tcg_gen_movi_i32(QREG_CC_OP, s->cc_op);
1.1 root 407: }
408:
409: /* Evaluate all the CC flags. */
410: static inline void gen_flush_flags(DisasContext *s)
411: {
412: if (s->cc_op == CC_OP_FLAGS)
413: return;
1.1.1.2 root 414: gen_flush_cc_op(s);
1.1.1.3 root 415: gen_helper_flush_flags(cpu_env, QREG_CC_OP);
1.1 root 416: s->cc_op = CC_OP_FLAGS;
417: }
418:
1.1.1.3 root 419: static void gen_logic_cc(DisasContext *s, TCGv val)
420: {
421: tcg_gen_mov_i32(QREG_CC_DEST, val);
422: s->cc_op = CC_OP_LOGIC;
423: }
424:
425: static void gen_update_cc_add(TCGv dest, TCGv src)
426: {
427: tcg_gen_mov_i32(QREG_CC_DEST, dest);
428: tcg_gen_mov_i32(QREG_CC_SRC, src);
429: }
430:
1.1 root 431: static inline int opsize_bytes(int opsize)
432: {
433: switch (opsize) {
434: case OS_BYTE: return 1;
435: case OS_WORD: return 2;
436: case OS_LONG: return 4;
437: case OS_SINGLE: return 4;
438: case OS_DOUBLE: return 8;
439: default:
440: qemu_assert(0, "bad operand size");
1.1.1.3 root 441: return 0;
1.1 root 442: }
443: }
444:
445: /* Assign value to a register. If the width is less than the register width
446: only the low part of the register is set. */
1.1.1.3 root 447: static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
1.1 root 448: {
1.1.1.3 root 449: TCGv tmp;
1.1 root 450: switch (opsize) {
451: case OS_BYTE:
1.1.1.3 root 452: tcg_gen_andi_i32(reg, reg, 0xffffff00);
453: tmp = tcg_temp_new();
454: tcg_gen_ext8u_i32(tmp, val);
455: tcg_gen_or_i32(reg, reg, tmp);
1.1 root 456: break;
457: case OS_WORD:
1.1.1.3 root 458: tcg_gen_andi_i32(reg, reg, 0xffff0000);
459: tmp = tcg_temp_new();
460: tcg_gen_ext16u_i32(tmp, val);
461: tcg_gen_or_i32(reg, reg, tmp);
1.1 root 462: break;
463: case OS_LONG:
464: case OS_SINGLE:
1.1.1.3 root 465: tcg_gen_mov_i32(reg, val);
1.1 root 466: break;
467: default:
468: qemu_assert(0, "Bad operand size");
469: break;
470: }
471: }
472:
473: /* Sign or zero extend a value. */
1.1.1.3 root 474: static inline TCGv gen_extend(TCGv val, int opsize, int sign)
1.1 root 475: {
1.1.1.3 root 476: TCGv tmp;
1.1 root 477:
478: switch (opsize) {
479: case OS_BYTE:
1.1.1.3 root 480: tmp = tcg_temp_new();
1.1 root 481: if (sign)
1.1.1.3 root 482: tcg_gen_ext8s_i32(tmp, val);
1.1 root 483: else
1.1.1.3 root 484: tcg_gen_ext8u_i32(tmp, val);
1.1 root 485: break;
486: case OS_WORD:
1.1.1.3 root 487: tmp = tcg_temp_new();
1.1 root 488: if (sign)
1.1.1.3 root 489: tcg_gen_ext16s_i32(tmp, val);
1.1 root 490: else
1.1.1.3 root 491: tcg_gen_ext16u_i32(tmp, val);
1.1 root 492: break;
493: case OS_LONG:
494: case OS_SINGLE:
1.1.1.3 root 495: tmp = val;
1.1 root 496: break;
497: default:
498: qemu_assert(0, "Bad operand size");
499: }
500: return tmp;
501: }
502:
503: /* Generate code for an "effective address". Does not adjust the base
1.1.1.3 root 504: register for autoincrement addressing modes. */
505: static TCGv gen_lea(DisasContext *s, uint16_t insn, int opsize)
1.1 root 506: {
1.1.1.3 root 507: TCGv reg;
508: TCGv tmp;
1.1 root 509: uint16_t ext;
510: uint32_t offset;
511:
512: switch ((insn >> 3) & 7) {
513: case 0: /* Data register direct. */
514: case 1: /* Address register direct. */
1.1.1.3 root 515: return NULL_QREG;
1.1 root 516: case 2: /* Indirect register */
517: case 3: /* Indirect postincrement. */
1.1.1.3 root 518: return AREG(insn, 0);
1.1 root 519: case 4: /* Indirect predecrememnt. */
1.1.1.3 root 520: reg = AREG(insn, 0);
521: tmp = tcg_temp_new();
522: tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
1.1 root 523: return tmp;
524: case 5: /* Indirect displacement. */
1.1.1.3 root 525: reg = AREG(insn, 0);
526: tmp = tcg_temp_new();
1.1.1.2 root 527: ext = lduw_code(s->pc);
1.1 root 528: s->pc += 2;
1.1.1.3 root 529: tcg_gen_addi_i32(tmp, reg, (int16_t)ext);
1.1 root 530: return tmp;
531: case 6: /* Indirect index + displacement. */
1.1.1.3 root 532: reg = AREG(insn, 0);
1.1 root 533: return gen_lea_indexed(s, opsize, reg);
534: case 7: /* Other */
1.1.1.3 root 535: switch (insn & 7) {
1.1 root 536: case 0: /* Absolute short. */
1.1.1.2 root 537: offset = ldsw_code(s->pc);
1.1 root 538: s->pc += 2;
539: return gen_im32(offset);
540: case 1: /* Absolute long. */
541: offset = read_im32(s);
542: return gen_im32(offset);
543: case 2: /* pc displacement */
1.1.1.3 root 544: tmp = tcg_temp_new();
1.1 root 545: offset = s->pc;
1.1.1.2 root 546: offset += ldsw_code(s->pc);
1.1 root 547: s->pc += 2;
548: return gen_im32(offset);
549: case 3: /* pc index+displacement. */
1.1.1.3 root 550: return gen_lea_indexed(s, opsize, NULL_QREG);
1.1 root 551: case 4: /* Immediate. */
552: default:
1.1.1.3 root 553: return NULL_QREG;
1.1 root 554: }
555: }
556: /* Should never happen. */
1.1.1.3 root 557: return NULL_QREG;
1.1 root 558: }
559:
560: /* Helper function for gen_ea. Reuse the computed address between the
561: for read/write operands. */
1.1.1.3 root 562: static inline TCGv gen_ea_once(DisasContext *s, uint16_t insn, int opsize,
563: TCGv val, TCGv *addrp, ea_what what)
1.1 root 564: {
1.1.1.3 root 565: TCGv tmp;
1.1 root 566:
1.1.1.3 root 567: if (addrp && what == EA_STORE) {
1.1 root 568: tmp = *addrp;
569: } else {
570: tmp = gen_lea(s, insn, opsize);
1.1.1.3 root 571: if (IS_NULL_QREG(tmp))
572: return tmp;
1.1 root 573: if (addrp)
574: *addrp = tmp;
575: }
1.1.1.3 root 576: return gen_ldst(s, opsize, tmp, val, what);
1.1 root 577: }
578:
579: /* Generate code to load/store a value ito/from an EA. If VAL > 0 this is
580: a write otherwise it is a read (0 == sign extend, -1 == zero extend).
581: ADDRP is non-null for readwrite operands. */
1.1.1.3 root 582: static TCGv gen_ea(DisasContext *s, uint16_t insn, int opsize, TCGv val,
583: TCGv *addrp, ea_what what)
1.1 root 584: {
1.1.1.3 root 585: TCGv reg;
586: TCGv result;
1.1 root 587: uint32_t offset;
588:
589: switch ((insn >> 3) & 7) {
590: case 0: /* Data register direct. */
1.1.1.3 root 591: reg = DREG(insn, 0);
592: if (what == EA_STORE) {
1.1 root 593: gen_partset_reg(opsize, reg, val);
1.1.1.3 root 594: return store_dummy;
1.1 root 595: } else {
1.1.1.3 root 596: return gen_extend(reg, opsize, what == EA_LOADS);
1.1 root 597: }
598: case 1: /* Address register direct. */
1.1.1.3 root 599: reg = AREG(insn, 0);
600: if (what == EA_STORE) {
601: tcg_gen_mov_i32(reg, val);
602: return store_dummy;
1.1 root 603: } else {
1.1.1.3 root 604: return gen_extend(reg, opsize, what == EA_LOADS);
1.1 root 605: }
606: case 2: /* Indirect register */
1.1.1.3 root 607: reg = AREG(insn, 0);
608: return gen_ldst(s, opsize, reg, val, what);
1.1 root 609: case 3: /* Indirect postincrement. */
1.1.1.3 root 610: reg = AREG(insn, 0);
611: result = gen_ldst(s, opsize, reg, val, what);
1.1 root 612: /* ??? This is not exception safe. The instruction may still
613: fault after this point. */
1.1.1.3 root 614: if (what == EA_STORE || !addrp)
615: tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize));
1.1 root 616: return result;
617: case 4: /* Indirect predecrememnt. */
618: {
1.1.1.3 root 619: TCGv tmp;
620: if (addrp && what == EA_STORE) {
1.1 root 621: tmp = *addrp;
622: } else {
623: tmp = gen_lea(s, insn, opsize);
1.1.1.3 root 624: if (IS_NULL_QREG(tmp))
625: return tmp;
1.1 root 626: if (addrp)
627: *addrp = tmp;
628: }
1.1.1.3 root 629: result = gen_ldst(s, opsize, tmp, val, what);
1.1 root 630: /* ??? This is not exception safe. The instruction may still
631: fault after this point. */
1.1.1.3 root 632: if (what == EA_STORE || !addrp) {
633: reg = AREG(insn, 0);
634: tcg_gen_mov_i32(reg, tmp);
1.1 root 635: }
636: }
637: return result;
638: case 5: /* Indirect displacement. */
639: case 6: /* Indirect index + displacement. */
1.1.1.3 root 640: return gen_ea_once(s, insn, opsize, val, addrp, what);
1.1 root 641: case 7: /* Other */
1.1.1.3 root 642: switch (insn & 7) {
1.1 root 643: case 0: /* Absolute short. */
644: case 1: /* Absolute long. */
645: case 2: /* pc displacement */
646: case 3: /* pc index+displacement. */
1.1.1.3 root 647: return gen_ea_once(s, insn, opsize, val, addrp, what);
1.1 root 648: case 4: /* Immediate. */
649: /* Sign extend values for consistency. */
650: switch (opsize) {
651: case OS_BYTE:
1.1.1.3 root 652: if (what == EA_LOADS)
1.1.1.2 root 653: offset = ldsb_code(s->pc + 1);
1.1 root 654: else
1.1.1.2 root 655: offset = ldub_code(s->pc + 1);
1.1 root 656: s->pc += 2;
657: break;
658: case OS_WORD:
1.1.1.3 root 659: if (what == EA_LOADS)
1.1.1.2 root 660: offset = ldsw_code(s->pc);
1.1 root 661: else
1.1.1.2 root 662: offset = lduw_code(s->pc);
1.1 root 663: s->pc += 2;
664: break;
665: case OS_LONG:
666: offset = read_im32(s);
667: break;
668: default:
669: qemu_assert(0, "Bad immediate operand");
670: }
1.1.1.3 root 671: return tcg_const_i32(offset);
1.1 root 672: default:
1.1.1.3 root 673: return NULL_QREG;
1.1 root 674: }
675: }
676: /* Should never happen. */
1.1.1.3 root 677: return NULL_QREG;
1.1 root 678: }
679:
1.1.1.3 root 680: /* This generates a conditional branch, clobbering all temporaries. */
1.1 root 681: static void gen_jmpcc(DisasContext *s, int cond, int l1)
682: {
1.1.1.3 root 683: TCGv tmp;
1.1 root 684:
1.1.1.3 root 685: /* TODO: Optimize compare/branch pairs rather than always flushing
686: flag state to CC_OP_FLAGS. */
1.1 root 687: gen_flush_flags(s);
688: switch (cond) {
689: case 0: /* T */
1.1.1.3 root 690: tcg_gen_br(l1);
1.1 root 691: break;
692: case 1: /* F */
693: break;
694: case 2: /* HI (!C && !Z) */
1.1.1.3 root 695: tmp = tcg_temp_new();
696: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
697: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 698: break;
699: case 3: /* LS (C || Z) */
1.1.1.3 root 700: tmp = tcg_temp_new();
701: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C | CCF_Z);
702: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 703: break;
704: case 4: /* CC (!C) */
1.1.1.3 root 705: tmp = tcg_temp_new();
706: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
707: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 708: break;
709: case 5: /* CS (C) */
1.1.1.3 root 710: tmp = tcg_temp_new();
711: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_C);
712: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 713: break;
714: case 6: /* NE (!Z) */
1.1.1.3 root 715: tmp = tcg_temp_new();
716: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
717: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 718: break;
719: case 7: /* EQ (Z) */
1.1.1.3 root 720: tmp = tcg_temp_new();
721: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_Z);
722: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 723: break;
724: case 8: /* VC (!V) */
1.1.1.3 root 725: tmp = tcg_temp_new();
726: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
727: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 728: break;
729: case 9: /* VS (V) */
1.1.1.3 root 730: tmp = tcg_temp_new();
731: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_V);
732: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 733: break;
734: case 10: /* PL (!N) */
1.1.1.3 root 735: tmp = tcg_temp_new();
736: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
737: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 738: break;
739: case 11: /* MI (N) */
1.1.1.3 root 740: tmp = tcg_temp_new();
741: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
742: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 743: break;
744: case 12: /* GE (!(N ^ V)) */
1.1.1.3 root 745: tmp = tcg_temp_new();
746: assert(CCF_V == (CCF_N >> 2));
747: tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
748: tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
749: tcg_gen_andi_i32(tmp, tmp, CCF_V);
750: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 751: break;
752: case 13: /* LT (N ^ V) */
1.1.1.3 root 753: tmp = tcg_temp_new();
754: assert(CCF_V == (CCF_N >> 2));
755: tcg_gen_shri_i32(tmp, QREG_CC_DEST, 2);
756: tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
757: tcg_gen_andi_i32(tmp, tmp, CCF_V);
758: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 759: break;
760: case 14: /* GT (!(Z || (N ^ V))) */
1.1.1.3 root 761: tmp = tcg_temp_new();
762: assert(CCF_V == (CCF_N >> 2));
763: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
764: tcg_gen_shri_i32(tmp, tmp, 2);
765: tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
766: tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
767: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, l1);
1.1 root 768: break;
769: case 15: /* LE (Z || (N ^ V)) */
1.1.1.3 root 770: tmp = tcg_temp_new();
771: assert(CCF_V == (CCF_N >> 2));
772: tcg_gen_andi_i32(tmp, QREG_CC_DEST, CCF_N);
773: tcg_gen_shri_i32(tmp, tmp, 2);
774: tcg_gen_xor_i32(tmp, tmp, QREG_CC_DEST);
775: tcg_gen_andi_i32(tmp, tmp, CCF_V | CCF_Z);
776: tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, l1);
1.1 root 777: break;
778: default:
779: /* Should ever happen. */
780: abort();
781: }
782: }
783:
784: DISAS_INSN(scc)
785: {
786: int l1;
787: int cond;
1.1.1.3 root 788: TCGv reg;
1.1 root 789:
790: l1 = gen_new_label();
791: cond = (insn >> 8) & 0xf;
792: reg = DREG(insn, 0);
1.1.1.3 root 793: tcg_gen_andi_i32(reg, reg, 0xffffff00);
794: /* This is safe because we modify the reg directly, with no other values
795: live. */
1.1 root 796: gen_jmpcc(s, cond ^ 1, l1);
1.1.1.3 root 797: tcg_gen_ori_i32(reg, reg, 0xff);
1.1 root 798: gen_set_label(l1);
799: }
800:
1.1.1.2 root 801: /* Force a TB lookup after an instruction that changes the CPU state. */
802: static void gen_lookup_tb(DisasContext *s)
803: {
804: gen_flush_cc_op(s);
1.1.1.3 root 805: tcg_gen_movi_i32(QREG_PC, s->pc);
1.1.1.2 root 806: s->is_jmp = DISAS_UPDATE;
807: }
808:
1.1.1.3 root 809: /* Generate a jump to an immediate address. */
810: static void gen_jmp_im(DisasContext *s, uint32_t dest)
1.1 root 811: {
812: gen_flush_cc_op(s);
1.1.1.3 root 813: tcg_gen_movi_i32(QREG_PC, dest);
814: s->is_jmp = DISAS_JUMP;
815: }
816:
817: /* Generate a jump to the address in qreg DEST. */
818: static void gen_jmp(DisasContext *s, TCGv dest)
819: {
820: gen_flush_cc_op(s);
821: tcg_gen_mov_i32(QREG_PC, dest);
1.1 root 822: s->is_jmp = DISAS_JUMP;
823: }
824:
825: static void gen_exception(DisasContext *s, uint32_t where, int nr)
826: {
827: gen_flush_cc_op(s);
1.1.1.3 root 828: gen_jmp_im(s, where);
829: gen_helper_raise_exception(tcg_const_i32(nr));
1.1 root 830: }
831:
1.1.1.2 root 832: static inline void gen_addr_fault(DisasContext *s)
833: {
834: gen_exception(s, s->insn_pc, EXCP_ADDRESS);
835: }
836:
1.1.1.3 root 837: #define SRC_EA(result, opsize, op_sign, addrp) do { \
838: result = gen_ea(s, insn, opsize, NULL_QREG, addrp, op_sign ? EA_LOADS : EA_LOADU); \
839: if (IS_NULL_QREG(result)) { \
1.1.1.2 root 840: gen_addr_fault(s); \
841: return; \
842: } \
843: } while (0)
844:
845: #define DEST_EA(insn, opsize, val, addrp) do { \
1.1.1.3 root 846: TCGv ea_result = gen_ea(s, insn, opsize, val, addrp, EA_STORE); \
847: if (IS_NULL_QREG(ea_result)) { \
1.1.1.2 root 848: gen_addr_fault(s); \
849: return; \
850: } \
851: } while (0)
852:
1.1 root 853: /* Generate a jump to an immediate address. */
854: static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
855: {
856: TranslationBlock *tb;
857:
858: tb = s->tb;
1.1.1.3 root 859: if (unlikely(s->singlestep_enabled)) {
1.1 root 860: gen_exception(s, dest, EXCP_DEBUG);
861: } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
862: (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1.1.1.3 root 863: tcg_gen_goto_tb(n);
864: tcg_gen_movi_i32(QREG_PC, dest);
865: tcg_gen_exit_tb((long)tb + n);
866: } else {
867: gen_jmp_im(s, dest);
868: tcg_gen_exit_tb(0);
1.1 root 869: }
870: s->is_jmp = DISAS_TB_JUMP;
871: }
872:
873: DISAS_INSN(undef_mac)
874: {
875: gen_exception(s, s->pc - 2, EXCP_LINEA);
876: }
877:
878: DISAS_INSN(undef_fpu)
879: {
880: gen_exception(s, s->pc - 2, EXCP_LINEF);
881: }
882:
883: DISAS_INSN(undef)
884: {
885: gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
886: cpu_abort(cpu_single_env, "Illegal instruction: %04x @ %08x",
887: insn, s->pc - 2);
888: }
889:
890: DISAS_INSN(mulw)
891: {
1.1.1.3 root 892: TCGv reg;
893: TCGv tmp;
894: TCGv src;
1.1 root 895: int sign;
896:
897: sign = (insn & 0x100) != 0;
898: reg = DREG(insn, 9);
1.1.1.3 root 899: tmp = tcg_temp_new();
1.1 root 900: if (sign)
1.1.1.3 root 901: tcg_gen_ext16s_i32(tmp, reg);
1.1 root 902: else
1.1.1.3 root 903: tcg_gen_ext16u_i32(tmp, reg);
904: SRC_EA(src, OS_WORD, sign, NULL);
905: tcg_gen_mul_i32(tmp, tmp, src);
906: tcg_gen_mov_i32(reg, tmp);
1.1 root 907: /* Unlike m68k, coldfire always clears the overflow bit. */
908: gen_logic_cc(s, tmp);
909: }
910:
911: DISAS_INSN(divw)
912: {
1.1.1.3 root 913: TCGv reg;
914: TCGv tmp;
915: TCGv src;
1.1 root 916: int sign;
917:
918: sign = (insn & 0x100) != 0;
919: reg = DREG(insn, 9);
920: if (sign) {
1.1.1.3 root 921: tcg_gen_ext16s_i32(QREG_DIV1, reg);
1.1 root 922: } else {
1.1.1.3 root 923: tcg_gen_ext16u_i32(QREG_DIV1, reg);
1.1 root 924: }
1.1.1.3 root 925: SRC_EA(src, OS_WORD, sign, NULL);
926: tcg_gen_mov_i32(QREG_DIV2, src);
1.1 root 927: if (sign) {
1.1.1.3 root 928: gen_helper_divs(cpu_env, tcg_const_i32(1));
1.1 root 929: } else {
1.1.1.3 root 930: gen_helper_divu(cpu_env, tcg_const_i32(1));
1.1 root 931: }
932:
1.1.1.3 root 933: tmp = tcg_temp_new();
934: src = tcg_temp_new();
935: tcg_gen_ext16u_i32(tmp, QREG_DIV1);
936: tcg_gen_shli_i32(src, QREG_DIV2, 16);
937: tcg_gen_or_i32(reg, tmp, src);
1.1 root 938: s->cc_op = CC_OP_FLAGS;
939: }
940:
941: DISAS_INSN(divl)
942: {
1.1.1.3 root 943: TCGv num;
944: TCGv den;
945: TCGv reg;
1.1 root 946: uint16_t ext;
947:
1.1.1.2 root 948: ext = lduw_code(s->pc);
1.1 root 949: s->pc += 2;
950: if (ext & 0x87f8) {
951: gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
952: return;
953: }
954: num = DREG(ext, 12);
955: reg = DREG(ext, 0);
1.1.1.3 root 956: tcg_gen_mov_i32(QREG_DIV1, num);
1.1.1.2 root 957: SRC_EA(den, OS_LONG, 0, NULL);
1.1.1.3 root 958: tcg_gen_mov_i32(QREG_DIV2, den);
1.1 root 959: if (ext & 0x0800) {
1.1.1.3 root 960: gen_helper_divs(cpu_env, tcg_const_i32(0));
1.1 root 961: } else {
1.1.1.3 root 962: gen_helper_divu(cpu_env, tcg_const_i32(0));
1.1 root 963: }
1.1.1.3 root 964: if ((ext & 7) == ((ext >> 12) & 7)) {
1.1 root 965: /* div */
1.1.1.3 root 966: tcg_gen_mov_i32 (reg, QREG_DIV1);
1.1 root 967: } else {
968: /* rem */
1.1.1.3 root 969: tcg_gen_mov_i32 (reg, QREG_DIV2);
1.1 root 970: }
971: s->cc_op = CC_OP_FLAGS;
972: }
973:
974: DISAS_INSN(addsub)
975: {
1.1.1.3 root 976: TCGv reg;
977: TCGv dest;
978: TCGv src;
979: TCGv tmp;
980: TCGv addr;
1.1 root 981: int add;
982:
983: add = (insn & 0x4000) != 0;
984: reg = DREG(insn, 9);
1.1.1.3 root 985: dest = tcg_temp_new();
1.1 root 986: if (insn & 0x100) {
1.1.1.2 root 987: SRC_EA(tmp, OS_LONG, 0, &addr);
1.1 root 988: src = reg;
989: } else {
990: tmp = reg;
1.1.1.2 root 991: SRC_EA(src, OS_LONG, 0, NULL);
1.1 root 992: }
993: if (add) {
1.1.1.3 root 994: tcg_gen_add_i32(dest, tmp, src);
995: gen_helper_xflag_lt(QREG_CC_X, dest, src);
1.1 root 996: s->cc_op = CC_OP_ADD;
997: } else {
1.1.1.3 root 998: gen_helper_xflag_lt(QREG_CC_X, tmp, src);
999: tcg_gen_sub_i32(dest, tmp, src);
1.1 root 1000: s->cc_op = CC_OP_SUB;
1001: }
1.1.1.3 root 1002: gen_update_cc_add(dest, src);
1.1 root 1003: if (insn & 0x100) {
1.1.1.2 root 1004: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1005: } else {
1.1.1.3 root 1006: tcg_gen_mov_i32(reg, dest);
1.1 root 1007: }
1008: }
1009:
1010:
1011: /* Reverse the order of the bits in REG. */
1012: DISAS_INSN(bitrev)
1013: {
1.1.1.3 root 1014: TCGv reg;
1.1 root 1015: reg = DREG(insn, 0);
1.1.1.3 root 1016: gen_helper_bitrev(reg, reg);
1.1 root 1017: }
1018:
1019: DISAS_INSN(bitop_reg)
1020: {
1021: int opsize;
1022: int op;
1.1.1.3 root 1023: TCGv src1;
1024: TCGv src2;
1025: TCGv tmp;
1026: TCGv addr;
1027: TCGv dest;
1.1 root 1028:
1029: if ((insn & 0x38) != 0)
1030: opsize = OS_BYTE;
1031: else
1032: opsize = OS_LONG;
1033: op = (insn >> 6) & 3;
1.1.1.2 root 1034: SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1.1 root 1035: src2 = DREG(insn, 9);
1.1.1.3 root 1036: dest = tcg_temp_new();
1.1 root 1037:
1038: gen_flush_flags(s);
1.1.1.3 root 1039: tmp = tcg_temp_new();
1.1 root 1040: if (opsize == OS_BYTE)
1.1.1.3 root 1041: tcg_gen_andi_i32(tmp, src2, 7);
1.1 root 1042: else
1.1.1.3 root 1043: tcg_gen_andi_i32(tmp, src2, 31);
1.1 root 1044: src2 = tmp;
1.1.1.3 root 1045: tmp = tcg_temp_new();
1046: tcg_gen_shr_i32(tmp, src1, src2);
1047: tcg_gen_andi_i32(tmp, tmp, 1);
1048: tcg_gen_shli_i32(tmp, tmp, 2);
1049: /* Clear CCF_Z if bit set. */
1050: tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
1051: tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1.1 root 1052:
1.1.1.3 root 1053: tcg_gen_shl_i32(tmp, tcg_const_i32(1), src2);
1.1 root 1054: switch (op) {
1055: case 1: /* bchg */
1.1.1.3 root 1056: tcg_gen_xor_i32(dest, src1, tmp);
1.1 root 1057: break;
1058: case 2: /* bclr */
1.1.1.3 root 1059: tcg_gen_not_i32(tmp, tmp);
1060: tcg_gen_and_i32(dest, src1, tmp);
1.1 root 1061: break;
1062: case 3: /* bset */
1.1.1.3 root 1063: tcg_gen_or_i32(dest, src1, tmp);
1.1 root 1064: break;
1065: default: /* btst */
1066: break;
1067: }
1068: if (op)
1.1.1.2 root 1069: DEST_EA(insn, opsize, dest, &addr);
1.1 root 1070: }
1071:
1072: DISAS_INSN(sats)
1073: {
1.1.1.3 root 1074: TCGv reg;
1.1 root 1075: reg = DREG(insn, 0);
1076: gen_flush_flags(s);
1.1.1.3 root 1077: gen_helper_sats(reg, reg, QREG_CC_DEST);
1078: gen_logic_cc(s, reg);
1.1 root 1079: }
1080:
1.1.1.3 root 1081: static void gen_push(DisasContext *s, TCGv val)
1.1 root 1082: {
1.1.1.3 root 1083: TCGv tmp;
1.1 root 1084:
1.1.1.3 root 1085: tmp = tcg_temp_new();
1086: tcg_gen_subi_i32(tmp, QREG_SP, 4);
1.1.1.2 root 1087: gen_store(s, OS_LONG, tmp, val);
1.1.1.3 root 1088: tcg_gen_mov_i32(QREG_SP, tmp);
1.1 root 1089: }
1090:
1091: DISAS_INSN(movem)
1092: {
1.1.1.3 root 1093: TCGv addr;
1.1 root 1094: int i;
1095: uint16_t mask;
1.1.1.3 root 1096: TCGv reg;
1097: TCGv tmp;
1.1 root 1098: int is_load;
1099:
1.1.1.2 root 1100: mask = lduw_code(s->pc);
1.1 root 1101: s->pc += 2;
1102: tmp = gen_lea(s, insn, OS_LONG);
1.1.1.3 root 1103: if (IS_NULL_QREG(tmp)) {
1.1.1.2 root 1104: gen_addr_fault(s);
1105: return;
1106: }
1.1.1.3 root 1107: addr = tcg_temp_new();
1108: tcg_gen_mov_i32(addr, tmp);
1.1 root 1109: is_load = ((insn & 0x0400) != 0);
1110: for (i = 0; i < 16; i++, mask >>= 1) {
1111: if (mask & 1) {
1112: if (i < 8)
1113: reg = DREG(i, 0);
1114: else
1115: reg = AREG(i, 0);
1116: if (is_load) {
1.1.1.2 root 1117: tmp = gen_load(s, OS_LONG, addr, 0);
1.1.1.3 root 1118: tcg_gen_mov_i32(reg, tmp);
1.1 root 1119: } else {
1.1.1.2 root 1120: gen_store(s, OS_LONG, addr, reg);
1.1 root 1121: }
1122: if (mask != 1)
1.1.1.3 root 1123: tcg_gen_addi_i32(addr, addr, 4);
1.1 root 1124: }
1125: }
1126: }
1127:
1128: DISAS_INSN(bitop_im)
1129: {
1130: int opsize;
1131: int op;
1.1.1.3 root 1132: TCGv src1;
1.1 root 1133: uint32_t mask;
1134: int bitnum;
1.1.1.3 root 1135: TCGv tmp;
1136: TCGv addr;
1.1 root 1137:
1138: if ((insn & 0x38) != 0)
1139: opsize = OS_BYTE;
1140: else
1141: opsize = OS_LONG;
1142: op = (insn >> 6) & 3;
1143:
1.1.1.2 root 1144: bitnum = lduw_code(s->pc);
1.1 root 1145: s->pc += 2;
1146: if (bitnum & 0xff00) {
1147: disas_undef(s, insn);
1148: return;
1149: }
1150:
1.1.1.2 root 1151: SRC_EA(src1, opsize, 0, op ? &addr: NULL);
1.1 root 1152:
1153: gen_flush_flags(s);
1154: if (opsize == OS_BYTE)
1155: bitnum &= 7;
1156: else
1157: bitnum &= 31;
1158: mask = 1 << bitnum;
1159:
1.1.1.3 root 1160: tmp = tcg_temp_new();
1161: assert (CCF_Z == (1 << 2));
1162: if (bitnum > 2)
1163: tcg_gen_shri_i32(tmp, src1, bitnum - 2);
1164: else if (bitnum < 2)
1165: tcg_gen_shli_i32(tmp, src1, 2 - bitnum);
1.1 root 1166: else
1.1.1.3 root 1167: tcg_gen_mov_i32(tmp, src1);
1168: tcg_gen_andi_i32(tmp, tmp, CCF_Z);
1169: /* Clear CCF_Z if bit set. */
1170: tcg_gen_ori_i32(QREG_CC_DEST, QREG_CC_DEST, CCF_Z);
1171: tcg_gen_xor_i32(QREG_CC_DEST, QREG_CC_DEST, tmp);
1172: if (op) {
1173: switch (op) {
1174: case 1: /* bchg */
1175: tcg_gen_xori_i32(tmp, src1, mask);
1176: break;
1177: case 2: /* bclr */
1178: tcg_gen_andi_i32(tmp, src1, ~mask);
1179: break;
1180: case 3: /* bset */
1181: tcg_gen_ori_i32(tmp, src1, mask);
1182: break;
1183: default: /* btst */
1184: break;
1185: }
1186: DEST_EA(insn, opsize, tmp, &addr);
1.1 root 1187: }
1188: }
1189:
1190: DISAS_INSN(arith_im)
1191: {
1192: int op;
1.1.1.3 root 1193: uint32_t im;
1194: TCGv src1;
1195: TCGv dest;
1196: TCGv addr;
1.1 root 1197:
1198: op = (insn >> 9) & 7;
1.1.1.2 root 1199: SRC_EA(src1, OS_LONG, 0, (op == 6) ? NULL : &addr);
1.1.1.3 root 1200: im = read_im32(s);
1201: dest = tcg_temp_new();
1.1 root 1202: switch (op) {
1203: case 0: /* ori */
1.1.1.3 root 1204: tcg_gen_ori_i32(dest, src1, im);
1.1 root 1205: gen_logic_cc(s, dest);
1206: break;
1207: case 1: /* andi */
1.1.1.3 root 1208: tcg_gen_andi_i32(dest, src1, im);
1.1 root 1209: gen_logic_cc(s, dest);
1210: break;
1211: case 2: /* subi */
1.1.1.3 root 1212: tcg_gen_mov_i32(dest, src1);
1213: gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im));
1214: tcg_gen_subi_i32(dest, dest, im);
1215: gen_update_cc_add(dest, gen_im32(im));
1.1 root 1216: s->cc_op = CC_OP_SUB;
1217: break;
1218: case 3: /* addi */
1.1.1.3 root 1219: tcg_gen_mov_i32(dest, src1);
1220: tcg_gen_addi_i32(dest, dest, im);
1221: gen_update_cc_add(dest, gen_im32(im));
1222: gen_helper_xflag_lt(QREG_CC_X, dest, gen_im32(im));
1.1 root 1223: s->cc_op = CC_OP_ADD;
1224: break;
1225: case 5: /* eori */
1.1.1.3 root 1226: tcg_gen_xori_i32(dest, src1, im);
1.1 root 1227: gen_logic_cc(s, dest);
1228: break;
1229: case 6: /* cmpi */
1.1.1.3 root 1230: tcg_gen_mov_i32(dest, src1);
1231: tcg_gen_subi_i32(dest, dest, im);
1232: gen_update_cc_add(dest, gen_im32(im));
1.1 root 1233: s->cc_op = CC_OP_SUB;
1234: break;
1235: default:
1236: abort();
1237: }
1238: if (op != 6) {
1.1.1.2 root 1239: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1240: }
1241: }
1242:
1243: DISAS_INSN(byterev)
1244: {
1.1.1.3 root 1245: TCGv reg;
1.1 root 1246:
1247: reg = DREG(insn, 0);
1.1.1.4 ! root 1248: tcg_gen_bswap32_i32(reg, reg);
1.1 root 1249: }
1250:
1251: DISAS_INSN(move)
1252: {
1.1.1.3 root 1253: TCGv src;
1254: TCGv dest;
1.1 root 1255: int op;
1256: int opsize;
1257:
1258: switch (insn >> 12) {
1259: case 1: /* move.b */
1260: opsize = OS_BYTE;
1261: break;
1262: case 2: /* move.l */
1263: opsize = OS_LONG;
1264: break;
1265: case 3: /* move.w */
1266: opsize = OS_WORD;
1267: break;
1268: default:
1269: abort();
1270: }
1.1.1.3 root 1271: SRC_EA(src, opsize, 1, NULL);
1.1 root 1272: op = (insn >> 6) & 7;
1273: if (op == 1) {
1274: /* movea */
1275: /* The value will already have been sign extended. */
1276: dest = AREG(insn, 9);
1.1.1.3 root 1277: tcg_gen_mov_i32(dest, src);
1.1 root 1278: } else {
1279: /* normal move */
1280: uint16_t dest_ea;
1281: dest_ea = ((insn >> 9) & 7) | (op << 3);
1.1.1.2 root 1282: DEST_EA(dest_ea, opsize, src, NULL);
1.1 root 1283: /* This will be correct because loads sign extend. */
1284: gen_logic_cc(s, src);
1285: }
1286: }
1287:
1288: DISAS_INSN(negx)
1289: {
1.1.1.3 root 1290: TCGv reg;
1.1 root 1291:
1292: gen_flush_flags(s);
1293: reg = DREG(insn, 0);
1.1.1.3 root 1294: gen_helper_subx_cc(reg, cpu_env, tcg_const_i32(0), reg);
1.1 root 1295: }
1296:
1297: DISAS_INSN(lea)
1298: {
1.1.1.3 root 1299: TCGv reg;
1300: TCGv tmp;
1.1 root 1301:
1302: reg = AREG(insn, 9);
1303: tmp = gen_lea(s, insn, OS_LONG);
1.1.1.3 root 1304: if (IS_NULL_QREG(tmp)) {
1.1.1.2 root 1305: gen_addr_fault(s);
1306: return;
1307: }
1.1.1.3 root 1308: tcg_gen_mov_i32(reg, tmp);
1.1 root 1309: }
1310:
1311: DISAS_INSN(clr)
1312: {
1313: int opsize;
1314:
1315: switch ((insn >> 6) & 3) {
1316: case 0: /* clr.b */
1317: opsize = OS_BYTE;
1318: break;
1319: case 1: /* clr.w */
1320: opsize = OS_WORD;
1321: break;
1322: case 2: /* clr.l */
1323: opsize = OS_LONG;
1324: break;
1325: default:
1326: abort();
1327: }
1.1.1.2 root 1328: DEST_EA(insn, opsize, gen_im32(0), NULL);
1.1 root 1329: gen_logic_cc(s, gen_im32(0));
1330: }
1331:
1.1.1.3 root 1332: static TCGv gen_get_ccr(DisasContext *s)
1.1 root 1333: {
1.1.1.3 root 1334: TCGv dest;
1.1 root 1335:
1336: gen_flush_flags(s);
1.1.1.3 root 1337: dest = tcg_temp_new();
1338: tcg_gen_shli_i32(dest, QREG_CC_X, 4);
1339: tcg_gen_or_i32(dest, dest, QREG_CC_DEST);
1.1.1.2 root 1340: return dest;
1341: }
1342:
1343: DISAS_INSN(move_from_ccr)
1344: {
1.1.1.3 root 1345: TCGv reg;
1346: TCGv ccr;
1.1.1.2 root 1347:
1348: ccr = gen_get_ccr(s);
1.1 root 1349: reg = DREG(insn, 0);
1.1.1.2 root 1350: gen_partset_reg(OS_WORD, reg, ccr);
1.1 root 1351: }
1352:
1353: DISAS_INSN(neg)
1354: {
1.1.1.3 root 1355: TCGv reg;
1356: TCGv src1;
1.1 root 1357:
1358: reg = DREG(insn, 0);
1.1.1.3 root 1359: src1 = tcg_temp_new();
1360: tcg_gen_mov_i32(src1, reg);
1361: tcg_gen_neg_i32(reg, src1);
1.1 root 1362: s->cc_op = CC_OP_SUB;
1.1.1.3 root 1363: gen_update_cc_add(reg, src1);
1364: gen_helper_xflag_lt(QREG_CC_X, tcg_const_i32(0), src1);
1.1 root 1365: s->cc_op = CC_OP_SUB;
1366: }
1367:
1.1.1.2 root 1368: static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only)
1369: {
1.1.1.3 root 1370: tcg_gen_movi_i32(QREG_CC_DEST, val & 0xf);
1371: tcg_gen_movi_i32(QREG_CC_X, (val & 0x10) >> 4);
1.1.1.2 root 1372: if (!ccr_only) {
1.1.1.3 root 1373: gen_helper_set_sr(cpu_env, tcg_const_i32(val & 0xff00));
1.1.1.2 root 1374: }
1375: }
1376:
1377: static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only)
1.1 root 1378: {
1.1.1.3 root 1379: TCGv tmp;
1380: TCGv reg;
1.1 root 1381:
1382: s->cc_op = CC_OP_FLAGS;
1383: if ((insn & 0x38) == 0)
1384: {
1.1.1.3 root 1385: tmp = tcg_temp_new();
1.1 root 1386: reg = DREG(insn, 0);
1.1.1.3 root 1387: tcg_gen_andi_i32(QREG_CC_DEST, reg, 0xf);
1388: tcg_gen_shri_i32(tmp, reg, 4);
1389: tcg_gen_andi_i32(QREG_CC_X, tmp, 1);
1.1.1.2 root 1390: if (!ccr_only) {
1.1.1.3 root 1391: gen_helper_set_sr(cpu_env, reg);
1.1.1.2 root 1392: }
1.1 root 1393: }
1.1.1.2 root 1394: else if ((insn & 0x3f) == 0x3c)
1.1 root 1395: {
1.1.1.2 root 1396: uint16_t val;
1397: val = lduw_code(s->pc);
1.1 root 1398: s->pc += 2;
1.1.1.2 root 1399: gen_set_sr_im(s, val, ccr_only);
1.1 root 1400: }
1401: else
1402: disas_undef(s, insn);
1403: }
1404:
1.1.1.2 root 1405: DISAS_INSN(move_to_ccr)
1406: {
1407: gen_set_sr(s, insn, 1);
1408: }
1409:
1.1 root 1410: DISAS_INSN(not)
1411: {
1.1.1.3 root 1412: TCGv reg;
1.1 root 1413:
1414: reg = DREG(insn, 0);
1.1.1.3 root 1415: tcg_gen_not_i32(reg, reg);
1.1 root 1416: gen_logic_cc(s, reg);
1417: }
1418:
1419: DISAS_INSN(swap)
1420: {
1.1.1.3 root 1421: TCGv src1;
1422: TCGv src2;
1423: TCGv reg;
1424:
1425: src1 = tcg_temp_new();
1426: src2 = tcg_temp_new();
1.1 root 1427: reg = DREG(insn, 0);
1.1.1.3 root 1428: tcg_gen_shli_i32(src1, reg, 16);
1429: tcg_gen_shri_i32(src2, reg, 16);
1430: tcg_gen_or_i32(reg, src1, src2);
1431: gen_logic_cc(s, reg);
1.1 root 1432: }
1433:
1434: DISAS_INSN(pea)
1435: {
1.1.1.3 root 1436: TCGv tmp;
1.1 root 1437:
1438: tmp = gen_lea(s, insn, OS_LONG);
1.1.1.3 root 1439: if (IS_NULL_QREG(tmp)) {
1.1.1.2 root 1440: gen_addr_fault(s);
1441: return;
1442: }
1443: gen_push(s, tmp);
1.1 root 1444: }
1445:
1446: DISAS_INSN(ext)
1447: {
1448: int op;
1.1.1.3 root 1449: TCGv reg;
1450: TCGv tmp;
1.1 root 1451:
1452: reg = DREG(insn, 0);
1453: op = (insn >> 6) & 7;
1.1.1.3 root 1454: tmp = tcg_temp_new();
1.1 root 1455: if (op == 3)
1.1.1.3 root 1456: tcg_gen_ext16s_i32(tmp, reg);
1.1 root 1457: else
1.1.1.3 root 1458: tcg_gen_ext8s_i32(tmp, reg);
1.1 root 1459: if (op == 2)
1460: gen_partset_reg(OS_WORD, reg, tmp);
1461: else
1.1.1.3 root 1462: tcg_gen_mov_i32(reg, tmp);
1.1 root 1463: gen_logic_cc(s, tmp);
1464: }
1465:
1466: DISAS_INSN(tst)
1467: {
1468: int opsize;
1.1.1.3 root 1469: TCGv tmp;
1.1 root 1470:
1471: switch ((insn >> 6) & 3) {
1472: case 0: /* tst.b */
1473: opsize = OS_BYTE;
1474: break;
1475: case 1: /* tst.w */
1476: opsize = OS_WORD;
1477: break;
1478: case 2: /* tst.l */
1479: opsize = OS_LONG;
1480: break;
1481: default:
1482: abort();
1483: }
1.1.1.3 root 1484: SRC_EA(tmp, opsize, 1, NULL);
1.1 root 1485: gen_logic_cc(s, tmp);
1486: }
1487:
1488: DISAS_INSN(pulse)
1489: {
1490: /* Implemented as a NOP. */
1491: }
1492:
1493: DISAS_INSN(illegal)
1494: {
1495: gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1496: }
1497:
1498: /* ??? This should be atomic. */
1499: DISAS_INSN(tas)
1500: {
1.1.1.3 root 1501: TCGv dest;
1502: TCGv src1;
1503: TCGv addr;
1.1 root 1504:
1.1.1.3 root 1505: dest = tcg_temp_new();
1506: SRC_EA(src1, OS_BYTE, 1, &addr);
1.1 root 1507: gen_logic_cc(s, src1);
1.1.1.3 root 1508: tcg_gen_ori_i32(dest, src1, 0x80);
1.1.1.2 root 1509: DEST_EA(insn, OS_BYTE, dest, &addr);
1.1 root 1510: }
1511:
1512: DISAS_INSN(mull)
1513: {
1514: uint16_t ext;
1.1.1.3 root 1515: TCGv reg;
1516: TCGv src1;
1517: TCGv dest;
1.1 root 1518:
1519: /* The upper 32 bits of the product are discarded, so
1520: muls.l and mulu.l are functionally equivalent. */
1.1.1.2 root 1521: ext = lduw_code(s->pc);
1.1 root 1522: s->pc += 2;
1523: if (ext & 0x87ff) {
1524: gen_exception(s, s->pc - 4, EXCP_UNSUPPORTED);
1525: return;
1526: }
1527: reg = DREG(ext, 12);
1.1.1.2 root 1528: SRC_EA(src1, OS_LONG, 0, NULL);
1.1.1.3 root 1529: dest = tcg_temp_new();
1530: tcg_gen_mul_i32(dest, src1, reg);
1531: tcg_gen_mov_i32(reg, dest);
1.1 root 1532: /* Unlike m68k, coldfire always clears the overflow bit. */
1533: gen_logic_cc(s, dest);
1534: }
1535:
1536: DISAS_INSN(link)
1537: {
1538: int16_t offset;
1.1.1.3 root 1539: TCGv reg;
1540: TCGv tmp;
1.1 root 1541:
1.1.1.2 root 1542: offset = ldsw_code(s->pc);
1.1 root 1543: s->pc += 2;
1544: reg = AREG(insn, 0);
1.1.1.3 root 1545: tmp = tcg_temp_new();
1546: tcg_gen_subi_i32(tmp, QREG_SP, 4);
1.1.1.2 root 1547: gen_store(s, OS_LONG, tmp, reg);
1.1.1.3 root 1548: if ((insn & 7) != 7)
1549: tcg_gen_mov_i32(reg, tmp);
1550: tcg_gen_addi_i32(QREG_SP, tmp, offset);
1.1 root 1551: }
1552:
1553: DISAS_INSN(unlk)
1554: {
1.1.1.3 root 1555: TCGv src;
1556: TCGv reg;
1557: TCGv tmp;
1.1 root 1558:
1.1.1.3 root 1559: src = tcg_temp_new();
1.1 root 1560: reg = AREG(insn, 0);
1.1.1.3 root 1561: tcg_gen_mov_i32(src, reg);
1.1.1.2 root 1562: tmp = gen_load(s, OS_LONG, src, 0);
1.1.1.3 root 1563: tcg_gen_mov_i32(reg, tmp);
1564: tcg_gen_addi_i32(QREG_SP, src, 4);
1.1 root 1565: }
1566:
1567: DISAS_INSN(nop)
1568: {
1569: }
1570:
1571: DISAS_INSN(rts)
1572: {
1.1.1.3 root 1573: TCGv tmp;
1.1 root 1574:
1.1.1.2 root 1575: tmp = gen_load(s, OS_LONG, QREG_SP, 0);
1.1.1.3 root 1576: tcg_gen_addi_i32(QREG_SP, QREG_SP, 4);
1.1 root 1577: gen_jmp(s, tmp);
1578: }
1579:
1580: DISAS_INSN(jump)
1581: {
1.1.1.3 root 1582: TCGv tmp;
1.1 root 1583:
1584: /* Load the target address first to ensure correct exception
1585: behavior. */
1586: tmp = gen_lea(s, insn, OS_LONG);
1.1.1.3 root 1587: if (IS_NULL_QREG(tmp)) {
1.1.1.2 root 1588: gen_addr_fault(s);
1589: return;
1590: }
1.1 root 1591: if ((insn & 0x40) == 0) {
1592: /* jsr */
1.1.1.2 root 1593: gen_push(s, gen_im32(s->pc));
1.1 root 1594: }
1595: gen_jmp(s, tmp);
1596: }
1597:
1598: DISAS_INSN(addsubq)
1599: {
1.1.1.3 root 1600: TCGv src1;
1601: TCGv src2;
1602: TCGv dest;
1.1 root 1603: int val;
1.1.1.3 root 1604: TCGv addr;
1.1 root 1605:
1.1.1.2 root 1606: SRC_EA(src1, OS_LONG, 0, &addr);
1.1 root 1607: val = (insn >> 9) & 7;
1608: if (val == 0)
1609: val = 8;
1.1.1.3 root 1610: dest = tcg_temp_new();
1611: tcg_gen_mov_i32(dest, src1);
1.1 root 1612: if ((insn & 0x38) == 0x08) {
1613: /* Don't update condition codes if the destination is an
1614: address register. */
1615: if (insn & 0x0100) {
1.1.1.3 root 1616: tcg_gen_subi_i32(dest, dest, val);
1.1 root 1617: } else {
1.1.1.3 root 1618: tcg_gen_addi_i32(dest, dest, val);
1.1 root 1619: }
1620: } else {
1.1.1.3 root 1621: src2 = gen_im32(val);
1.1 root 1622: if (insn & 0x0100) {
1.1.1.3 root 1623: gen_helper_xflag_lt(QREG_CC_X, dest, src2);
1624: tcg_gen_subi_i32(dest, dest, val);
1.1 root 1625: s->cc_op = CC_OP_SUB;
1626: } else {
1.1.1.3 root 1627: tcg_gen_addi_i32(dest, dest, val);
1628: gen_helper_xflag_lt(QREG_CC_X, dest, src2);
1.1 root 1629: s->cc_op = CC_OP_ADD;
1630: }
1.1.1.3 root 1631: gen_update_cc_add(dest, src2);
1.1 root 1632: }
1.1.1.2 root 1633: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1634: }
1635:
1636: DISAS_INSN(tpf)
1637: {
1638: switch (insn & 7) {
1639: case 2: /* One extension word. */
1640: s->pc += 2;
1641: break;
1642: case 3: /* Two extension words. */
1643: s->pc += 4;
1644: break;
1645: case 4: /* No extension words. */
1646: break;
1647: default:
1648: disas_undef(s, insn);
1649: }
1650: }
1651:
1652: DISAS_INSN(branch)
1653: {
1654: int32_t offset;
1655: uint32_t base;
1656: int op;
1657: int l1;
1.1.1.2 root 1658:
1.1 root 1659: base = s->pc;
1660: op = (insn >> 8) & 0xf;
1661: offset = (int8_t)insn;
1662: if (offset == 0) {
1.1.1.2 root 1663: offset = ldsw_code(s->pc);
1.1 root 1664: s->pc += 2;
1665: } else if (offset == -1) {
1666: offset = read_im32(s);
1667: }
1668: if (op == 1) {
1669: /* bsr */
1.1.1.2 root 1670: gen_push(s, gen_im32(s->pc));
1.1 root 1671: }
1672: gen_flush_cc_op(s);
1673: if (op > 1) {
1674: /* Bcc */
1675: l1 = gen_new_label();
1676: gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
1677: gen_jmp_tb(s, 1, base + offset);
1678: gen_set_label(l1);
1679: gen_jmp_tb(s, 0, s->pc);
1680: } else {
1681: /* Unconditional branch. */
1682: gen_jmp_tb(s, 0, base + offset);
1683: }
1684: }
1685:
1686: DISAS_INSN(moveq)
1687: {
1.1.1.3 root 1688: uint32_t val;
1.1 root 1689:
1.1.1.3 root 1690: val = (int8_t)insn;
1691: tcg_gen_movi_i32(DREG(insn, 9), val);
1692: gen_logic_cc(s, tcg_const_i32(val));
1.1 root 1693: }
1694:
1695: DISAS_INSN(mvzs)
1696: {
1697: int opsize;
1.1.1.3 root 1698: TCGv src;
1699: TCGv reg;
1.1 root 1700:
1701: if (insn & 0x40)
1702: opsize = OS_WORD;
1703: else
1704: opsize = OS_BYTE;
1.1.1.3 root 1705: SRC_EA(src, opsize, (insn & 0x80) == 0, NULL);
1.1 root 1706: reg = DREG(insn, 9);
1.1.1.3 root 1707: tcg_gen_mov_i32(reg, src);
1.1 root 1708: gen_logic_cc(s, src);
1709: }
1710:
1711: DISAS_INSN(or)
1712: {
1.1.1.3 root 1713: TCGv reg;
1714: TCGv dest;
1715: TCGv src;
1716: TCGv addr;
1.1 root 1717:
1718: reg = DREG(insn, 9);
1.1.1.3 root 1719: dest = tcg_temp_new();
1.1 root 1720: if (insn & 0x100) {
1.1.1.2 root 1721: SRC_EA(src, OS_LONG, 0, &addr);
1.1.1.3 root 1722: tcg_gen_or_i32(dest, src, reg);
1.1.1.2 root 1723: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1724: } else {
1.1.1.2 root 1725: SRC_EA(src, OS_LONG, 0, NULL);
1.1.1.3 root 1726: tcg_gen_or_i32(dest, src, reg);
1727: tcg_gen_mov_i32(reg, dest);
1.1 root 1728: }
1729: gen_logic_cc(s, dest);
1730: }
1731:
1732: DISAS_INSN(suba)
1733: {
1.1.1.3 root 1734: TCGv src;
1735: TCGv reg;
1.1 root 1736:
1.1.1.2 root 1737: SRC_EA(src, OS_LONG, 0, NULL);
1.1 root 1738: reg = AREG(insn, 9);
1.1.1.3 root 1739: tcg_gen_sub_i32(reg, reg, src);
1.1 root 1740: }
1741:
1742: DISAS_INSN(subx)
1743: {
1.1.1.3 root 1744: TCGv reg;
1745: TCGv src;
1.1 root 1746:
1747: gen_flush_flags(s);
1748: reg = DREG(insn, 9);
1749: src = DREG(insn, 0);
1.1.1.3 root 1750: gen_helper_subx_cc(reg, cpu_env, reg, src);
1.1 root 1751: }
1752:
1753: DISAS_INSN(mov3q)
1754: {
1.1.1.3 root 1755: TCGv src;
1.1 root 1756: int val;
1757:
1758: val = (insn >> 9) & 7;
1759: if (val == 0)
1760: val = -1;
1761: src = gen_im32(val);
1762: gen_logic_cc(s, src);
1.1.1.2 root 1763: DEST_EA(insn, OS_LONG, src, NULL);
1.1 root 1764: }
1765:
1766: DISAS_INSN(cmp)
1767: {
1768: int op;
1.1.1.3 root 1769: TCGv src;
1770: TCGv reg;
1771: TCGv dest;
1.1 root 1772: int opsize;
1773:
1774: op = (insn >> 6) & 3;
1775: switch (op) {
1776: case 0: /* cmp.b */
1777: opsize = OS_BYTE;
1778: s->cc_op = CC_OP_CMPB;
1779: break;
1780: case 1: /* cmp.w */
1781: opsize = OS_WORD;
1782: s->cc_op = CC_OP_CMPW;
1783: break;
1784: case 2: /* cmp.l */
1785: opsize = OS_LONG;
1786: s->cc_op = CC_OP_SUB;
1787: break;
1788: default:
1789: abort();
1790: }
1.1.1.3 root 1791: SRC_EA(src, opsize, 1, NULL);
1.1 root 1792: reg = DREG(insn, 9);
1.1.1.3 root 1793: dest = tcg_temp_new();
1794: tcg_gen_sub_i32(dest, reg, src);
1795: gen_update_cc_add(dest, src);
1.1 root 1796: }
1797:
1798: DISAS_INSN(cmpa)
1799: {
1800: int opsize;
1.1.1.3 root 1801: TCGv src;
1802: TCGv reg;
1803: TCGv dest;
1.1 root 1804:
1805: if (insn & 0x100) {
1806: opsize = OS_LONG;
1807: } else {
1808: opsize = OS_WORD;
1809: }
1.1.1.3 root 1810: SRC_EA(src, opsize, 1, NULL);
1.1 root 1811: reg = AREG(insn, 9);
1.1.1.3 root 1812: dest = tcg_temp_new();
1813: tcg_gen_sub_i32(dest, reg, src);
1814: gen_update_cc_add(dest, src);
1.1 root 1815: s->cc_op = CC_OP_SUB;
1816: }
1817:
1818: DISAS_INSN(eor)
1819: {
1.1.1.3 root 1820: TCGv src;
1821: TCGv reg;
1822: TCGv dest;
1823: TCGv addr;
1.1 root 1824:
1.1.1.2 root 1825: SRC_EA(src, OS_LONG, 0, &addr);
1.1 root 1826: reg = DREG(insn, 9);
1.1.1.3 root 1827: dest = tcg_temp_new();
1828: tcg_gen_xor_i32(dest, src, reg);
1.1 root 1829: gen_logic_cc(s, dest);
1.1.1.2 root 1830: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1831: }
1832:
1833: DISAS_INSN(and)
1834: {
1.1.1.3 root 1835: TCGv src;
1836: TCGv reg;
1837: TCGv dest;
1838: TCGv addr;
1.1 root 1839:
1840: reg = DREG(insn, 9);
1.1.1.3 root 1841: dest = tcg_temp_new();
1.1 root 1842: if (insn & 0x100) {
1.1.1.2 root 1843: SRC_EA(src, OS_LONG, 0, &addr);
1.1.1.3 root 1844: tcg_gen_and_i32(dest, src, reg);
1.1.1.2 root 1845: DEST_EA(insn, OS_LONG, dest, &addr);
1.1 root 1846: } else {
1.1.1.2 root 1847: SRC_EA(src, OS_LONG, 0, NULL);
1.1.1.3 root 1848: tcg_gen_and_i32(dest, src, reg);
1849: tcg_gen_mov_i32(reg, dest);
1.1 root 1850: }
1851: gen_logic_cc(s, dest);
1852: }
1853:
1854: DISAS_INSN(adda)
1855: {
1.1.1.3 root 1856: TCGv src;
1857: TCGv reg;
1.1 root 1858:
1.1.1.2 root 1859: SRC_EA(src, OS_LONG, 0, NULL);
1.1 root 1860: reg = AREG(insn, 9);
1.1.1.3 root 1861: tcg_gen_add_i32(reg, reg, src);
1.1 root 1862: }
1863:
1864: DISAS_INSN(addx)
1865: {
1.1.1.3 root 1866: TCGv reg;
1867: TCGv src;
1.1 root 1868:
1869: gen_flush_flags(s);
1870: reg = DREG(insn, 9);
1871: src = DREG(insn, 0);
1.1.1.3 root 1872: gen_helper_addx_cc(reg, cpu_env, reg, src);
1.1 root 1873: s->cc_op = CC_OP_FLAGS;
1874: }
1875:
1.1.1.3 root 1876: /* TODO: This could be implemented without helper functions. */
1.1 root 1877: DISAS_INSN(shift_im)
1878: {
1.1.1.3 root 1879: TCGv reg;
1.1 root 1880: int tmp;
1.1.1.3 root 1881: TCGv shift;
1.1 root 1882:
1883: reg = DREG(insn, 0);
1884: tmp = (insn >> 9) & 7;
1885: if (tmp == 0)
1.1.1.3 root 1886: tmp = 8;
1887: shift = gen_im32(tmp);
1888: /* No need to flush flags becuse we know we will set C flag. */
1.1 root 1889: if (insn & 0x100) {
1.1.1.3 root 1890: gen_helper_shl_cc(reg, cpu_env, reg, shift);
1.1 root 1891: } else {
1892: if (insn & 8) {
1.1.1.3 root 1893: gen_helper_shr_cc(reg, cpu_env, reg, shift);
1.1 root 1894: } else {
1.1.1.3 root 1895: gen_helper_sar_cc(reg, cpu_env, reg, shift);
1.1 root 1896: }
1897: }
1.1.1.3 root 1898: s->cc_op = CC_OP_SHIFT;
1.1 root 1899: }
1900:
1901: DISAS_INSN(shift_reg)
1902: {
1.1.1.3 root 1903: TCGv reg;
1904: TCGv shift;
1.1 root 1905:
1906: reg = DREG(insn, 0);
1.1.1.3 root 1907: shift = DREG(insn, 9);
1908: /* Shift by zero leaves C flag unmodified. */
1909: gen_flush_flags(s);
1.1 root 1910: if (insn & 0x100) {
1.1.1.3 root 1911: gen_helper_shl_cc(reg, cpu_env, reg, shift);
1.1 root 1912: } else {
1913: if (insn & 8) {
1.1.1.3 root 1914: gen_helper_shr_cc(reg, cpu_env, reg, shift);
1.1 root 1915: } else {
1.1.1.3 root 1916: gen_helper_sar_cc(reg, cpu_env, reg, shift);
1.1 root 1917: }
1918: }
1.1.1.3 root 1919: s->cc_op = CC_OP_SHIFT;
1.1 root 1920: }
1921:
1922: DISAS_INSN(ff1)
1923: {
1.1.1.3 root 1924: TCGv reg;
1.1.1.2 root 1925: reg = DREG(insn, 0);
1926: gen_logic_cc(s, reg);
1.1.1.3 root 1927: gen_helper_ff1(reg, reg);
1.1.1.2 root 1928: }
1929:
1.1.1.3 root 1930: static TCGv gen_get_sr(DisasContext *s)
1.1.1.2 root 1931: {
1.1.1.3 root 1932: TCGv ccr;
1933: TCGv sr;
1.1.1.2 root 1934:
1935: ccr = gen_get_ccr(s);
1.1.1.3 root 1936: sr = tcg_temp_new();
1937: tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
1938: tcg_gen_or_i32(sr, sr, ccr);
1.1.1.2 root 1939: return sr;
1.1 root 1940: }
1941:
1942: DISAS_INSN(strldsr)
1943: {
1944: uint16_t ext;
1945: uint32_t addr;
1946:
1947: addr = s->pc - 2;
1.1.1.2 root 1948: ext = lduw_code(s->pc);
1.1 root 1949: s->pc += 2;
1.1.1.2 root 1950: if (ext != 0x46FC) {
1.1 root 1951: gen_exception(s, addr, EXCP_UNSUPPORTED);
1.1.1.2 root 1952: return;
1953: }
1954: ext = lduw_code(s->pc);
1955: s->pc += 2;
1956: if (IS_USER(s) || (ext & SR_S) == 0) {
1.1 root 1957: gen_exception(s, addr, EXCP_PRIVILEGE);
1.1.1.2 root 1958: return;
1959: }
1960: gen_push(s, gen_get_sr(s));
1961: gen_set_sr_im(s, ext, 0);
1.1 root 1962: }
1963:
1964: DISAS_INSN(move_from_sr)
1965: {
1.1.1.3 root 1966: TCGv reg;
1967: TCGv sr;
1.1.1.2 root 1968:
1969: if (IS_USER(s)) {
1970: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1971: return;
1972: }
1973: sr = gen_get_sr(s);
1974: reg = DREG(insn, 0);
1975: gen_partset_reg(OS_WORD, reg, sr);
1.1 root 1976: }
1977:
1978: DISAS_INSN(move_to_sr)
1979: {
1.1.1.2 root 1980: if (IS_USER(s)) {
1981: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1982: return;
1983: }
1984: gen_set_sr(s, insn, 0);
1985: gen_lookup_tb(s);
1.1 root 1986: }
1987:
1988: DISAS_INSN(move_from_usp)
1989: {
1.1.1.2 root 1990: if (IS_USER(s)) {
1991: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
1992: return;
1993: }
1994: /* TODO: Implement USP. */
1995: gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1.1 root 1996: }
1997:
1998: DISAS_INSN(move_to_usp)
1999: {
1.1.1.2 root 2000: if (IS_USER(s)) {
2001: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2002: return;
2003: }
2004: /* TODO: Implement USP. */
2005: gen_exception(s, s->pc - 2, EXCP_ILLEGAL);
1.1 root 2006: }
2007:
2008: DISAS_INSN(halt)
2009: {
1.1.1.3 root 2010: gen_exception(s, s->pc, EXCP_HALT_INSN);
1.1 root 2011: }
2012:
2013: DISAS_INSN(stop)
2014: {
1.1.1.2 root 2015: uint16_t ext;
2016:
2017: if (IS_USER(s)) {
2018: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2019: return;
2020: }
2021:
2022: ext = lduw_code(s->pc);
2023: s->pc += 2;
2024:
2025: gen_set_sr_im(s, ext, 0);
1.1.1.3 root 2026: tcg_gen_movi_i32(QREG_HALTED, 1);
2027: gen_exception(s, s->pc, EXCP_HLT);
1.1 root 2028: }
2029:
2030: DISAS_INSN(rte)
2031: {
1.1.1.2 root 2032: if (IS_USER(s)) {
2033: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2034: return;
2035: }
2036: gen_exception(s, s->pc - 2, EXCP_RTE);
1.1 root 2037: }
2038:
2039: DISAS_INSN(movec)
2040: {
1.1.1.2 root 2041: uint16_t ext;
1.1.1.3 root 2042: TCGv reg;
1.1.1.2 root 2043:
2044: if (IS_USER(s)) {
2045: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2046: return;
2047: }
2048:
2049: ext = lduw_code(s->pc);
2050: s->pc += 2;
2051:
2052: if (ext & 0x8000) {
2053: reg = AREG(ext, 12);
2054: } else {
2055: reg = DREG(ext, 12);
2056: }
1.1.1.3 root 2057: gen_helper_movec(cpu_env, tcg_const_i32(ext & 0xfff), reg);
1.1.1.2 root 2058: gen_lookup_tb(s);
1.1 root 2059: }
2060:
2061: DISAS_INSN(intouch)
2062: {
1.1.1.2 root 2063: if (IS_USER(s)) {
2064: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2065: return;
2066: }
2067: /* ICache fetch. Implement as no-op. */
1.1 root 2068: }
2069:
2070: DISAS_INSN(cpushl)
2071: {
1.1.1.2 root 2072: if (IS_USER(s)) {
2073: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2074: return;
2075: }
2076: /* Cache push/invalidate. Implement as no-op. */
1.1 root 2077: }
2078:
2079: DISAS_INSN(wddata)
2080: {
2081: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2082: }
2083:
2084: DISAS_INSN(wdebug)
2085: {
1.1.1.2 root 2086: if (IS_USER(s)) {
2087: gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
2088: return;
2089: }
2090: /* TODO: Implement wdebug. */
2091: qemu_assert(0, "WDEBUG not implemented");
1.1 root 2092: }
2093:
2094: DISAS_INSN(trap)
2095: {
2096: gen_exception(s, s->pc - 2, EXCP_TRAP0 + (insn & 0xf));
2097: }
2098:
2099: /* ??? FP exceptions are not implemented. Most exceptions are deferred until
2100: immediately before the next FP instruction is executed. */
2101: DISAS_INSN(fpu)
2102: {
2103: uint16_t ext;
1.1.1.3 root 2104: int32_t offset;
1.1 root 2105: int opmode;
1.1.1.3 root 2106: TCGv_i64 src;
2107: TCGv_i64 dest;
2108: TCGv_i64 res;
2109: TCGv tmp32;
1.1 root 2110: int round;
1.1.1.3 root 2111: int set_dest;
1.1 root 2112: int opsize;
2113:
1.1.1.2 root 2114: ext = lduw_code(s->pc);
1.1 root 2115: s->pc += 2;
2116: opmode = ext & 0x7f;
2117: switch ((ext >> 13) & 7) {
2118: case 0: case 2:
2119: break;
2120: case 1:
2121: goto undef;
2122: case 3: /* fmove out */
2123: src = FREG(ext, 7);
1.1.1.3 root 2124: tmp32 = tcg_temp_new_i32();
1.1 root 2125: /* fmove */
2126: /* ??? TODO: Proper behavior on overflow. */
2127: switch ((ext >> 10) & 7) {
2128: case 0:
2129: opsize = OS_LONG;
1.1.1.3 root 2130: gen_helper_f64_to_i32(tmp32, cpu_env, src);
1.1 root 2131: break;
2132: case 1:
2133: opsize = OS_SINGLE;
1.1.1.3 root 2134: gen_helper_f64_to_f32(tmp32, cpu_env, src);
1.1 root 2135: break;
2136: case 4:
2137: opsize = OS_WORD;
1.1.1.3 root 2138: gen_helper_f64_to_i32(tmp32, cpu_env, src);
1.1 root 2139: break;
1.1.1.3 root 2140: case 5: /* OS_DOUBLE */
2141: tcg_gen_mov_i32(tmp32, AREG(insn, 0));
2142: switch ((insn >> 3) & 7) {
2143: case 2:
2144: case 3:
2145: break;
2146: case 4:
2147: tcg_gen_addi_i32(tmp32, tmp32, -8);
2148: break;
2149: case 5:
2150: offset = ldsw_code(s->pc);
2151: s->pc += 2;
2152: tcg_gen_addi_i32(tmp32, tmp32, offset);
2153: break;
2154: default:
2155: goto undef;
2156: }
2157: gen_store64(s, tmp32, src);
2158: switch ((insn >> 3) & 7) {
2159: case 3:
2160: tcg_gen_addi_i32(tmp32, tmp32, 8);
2161: tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2162: break;
2163: case 4:
2164: tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2165: break;
2166: }
2167: tcg_temp_free_i32(tmp32);
2168: return;
1.1 root 2169: case 6:
2170: opsize = OS_BYTE;
1.1.1.3 root 2171: gen_helper_f64_to_i32(tmp32, cpu_env, src);
1.1 root 2172: break;
2173: default:
2174: goto undef;
2175: }
1.1.1.3 root 2176: DEST_EA(insn, opsize, tmp32, NULL);
2177: tcg_temp_free_i32(tmp32);
1.1 root 2178: return;
2179: case 4: /* fmove to control register. */
2180: switch ((ext >> 10) & 7) {
2181: case 4: /* FPCR */
2182: /* Not implemented. Ignore writes. */
2183: break;
2184: case 1: /* FPIAR */
2185: case 2: /* FPSR */
2186: default:
2187: cpu_abort(NULL, "Unimplemented: fmove to control %d",
2188: (ext >> 10) & 7);
2189: }
2190: break;
2191: case 5: /* fmove from control register. */
2192: switch ((ext >> 10) & 7) {
2193: case 4: /* FPCR */
2194: /* Not implemented. Always return zero. */
1.1.1.3 root 2195: tmp32 = gen_im32(0);
1.1 root 2196: break;
2197: case 1: /* FPIAR */
2198: case 2: /* FPSR */
2199: default:
2200: cpu_abort(NULL, "Unimplemented: fmove from control %d",
2201: (ext >> 10) & 7);
2202: goto undef;
2203: }
1.1.1.3 root 2204: DEST_EA(insn, OS_LONG, tmp32, NULL);
1.1 root 2205: break;
1.1.1.2 root 2206: case 6: /* fmovem */
1.1 root 2207: case 7:
2208: {
1.1.1.3 root 2209: TCGv addr;
2210: uint16_t mask;
2211: int i;
2212: if ((ext & 0x1f00) != 0x1000 || (ext & 0xff) == 0)
2213: goto undef;
2214: tmp32 = gen_lea(s, insn, OS_LONG);
2215: if (IS_NULL_QREG(tmp32)) {
2216: gen_addr_fault(s);
2217: return;
2218: }
2219: addr = tcg_temp_new_i32();
2220: tcg_gen_mov_i32(addr, tmp32);
2221: mask = 0x80;
2222: for (i = 0; i < 8; i++) {
2223: if (ext & mask) {
2224: s->is_mem = 1;
2225: dest = FREG(i, 0);
2226: if (ext & (1 << 13)) {
2227: /* store */
2228: tcg_gen_qemu_stf64(dest, addr, IS_USER(s));
2229: } else {
2230: /* load */
2231: tcg_gen_qemu_ldf64(dest, addr, IS_USER(s));
2232: }
2233: if (ext & (mask - 1))
2234: tcg_gen_addi_i32(addr, addr, 8);
1.1 root 2235: }
1.1.1.3 root 2236: mask >>= 1;
1.1 root 2237: }
1.1.1.3 root 2238: tcg_temp_free_i32(addr);
1.1 root 2239: }
2240: return;
2241: }
2242: if (ext & (1 << 14)) {
2243: /* Source effective address. */
2244: switch ((ext >> 10) & 7) {
2245: case 0: opsize = OS_LONG; break;
2246: case 1: opsize = OS_SINGLE; break;
2247: case 4: opsize = OS_WORD; break;
2248: case 5: opsize = OS_DOUBLE; break;
2249: case 6: opsize = OS_BYTE; break;
2250: default:
2251: goto undef;
2252: }
2253: if (opsize == OS_DOUBLE) {
1.1.1.3 root 2254: tmp32 = tcg_temp_new_i32();
2255: tcg_gen_mov_i32(tmp32, AREG(insn, 0));
2256: switch ((insn >> 3) & 7) {
2257: case 2:
2258: case 3:
2259: break;
2260: case 4:
2261: tcg_gen_addi_i32(tmp32, tmp32, -8);
2262: break;
2263: case 5:
2264: offset = ldsw_code(s->pc);
2265: s->pc += 2;
2266: tcg_gen_addi_i32(tmp32, tmp32, offset);
2267: break;
2268: case 7:
2269: offset = ldsw_code(s->pc);
2270: offset += s->pc - 2;
2271: s->pc += 2;
2272: tcg_gen_addi_i32(tmp32, tmp32, offset);
2273: break;
2274: default:
2275: goto undef;
2276: }
2277: src = gen_load64(s, tmp32);
2278: switch ((insn >> 3) & 7) {
2279: case 3:
2280: tcg_gen_addi_i32(tmp32, tmp32, 8);
2281: tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2282: break;
2283: case 4:
2284: tcg_gen_mov_i32(AREG(insn, 0), tmp32);
2285: break;
2286: }
2287: tcg_temp_free_i32(tmp32);
1.1 root 2288: } else {
1.1.1.3 root 2289: SRC_EA(tmp32, opsize, 1, NULL);
2290: src = tcg_temp_new_i64();
1.1 root 2291: switch (opsize) {
2292: case OS_LONG:
2293: case OS_WORD:
2294: case OS_BYTE:
1.1.1.3 root 2295: gen_helper_i32_to_f64(src, cpu_env, tmp32);
1.1 root 2296: break;
2297: case OS_SINGLE:
1.1.1.3 root 2298: gen_helper_f32_to_f64(src, cpu_env, tmp32);
1.1 root 2299: break;
2300: }
2301: }
2302: } else {
2303: /* Source register. */
2304: src = FREG(ext, 10);
2305: }
2306: dest = FREG(ext, 7);
1.1.1.3 root 2307: res = tcg_temp_new_i64();
1.1 root 2308: if (opmode != 0x3a)
1.1.1.3 root 2309: tcg_gen_mov_f64(res, dest);
1.1 root 2310: round = 1;
1.1.1.3 root 2311: set_dest = 1;
1.1 root 2312: switch (opmode) {
2313: case 0: case 0x40: case 0x44: /* fmove */
1.1.1.3 root 2314: tcg_gen_mov_f64(res, src);
1.1 root 2315: break;
2316: case 1: /* fint */
1.1.1.3 root 2317: gen_helper_iround_f64(res, cpu_env, src);
1.1 root 2318: round = 0;
2319: break;
2320: case 3: /* fintrz */
1.1.1.3 root 2321: gen_helper_itrunc_f64(res, cpu_env, src);
1.1 root 2322: round = 0;
2323: break;
2324: case 4: case 0x41: case 0x45: /* fsqrt */
1.1.1.3 root 2325: gen_helper_sqrt_f64(res, cpu_env, src);
1.1 root 2326: break;
2327: case 0x18: case 0x58: case 0x5c: /* fabs */
1.1.1.3 root 2328: gen_helper_abs_f64(res, src);
1.1 root 2329: break;
2330: case 0x1a: case 0x5a: case 0x5e: /* fneg */
1.1.1.3 root 2331: gen_helper_chs_f64(res, src);
1.1 root 2332: break;
2333: case 0x20: case 0x60: case 0x64: /* fdiv */
1.1.1.3 root 2334: gen_helper_div_f64(res, cpu_env, res, src);
1.1 root 2335: break;
2336: case 0x22: case 0x62: case 0x66: /* fadd */
1.1.1.3 root 2337: gen_helper_add_f64(res, cpu_env, res, src);
1.1 root 2338: break;
2339: case 0x23: case 0x63: case 0x67: /* fmul */
1.1.1.3 root 2340: gen_helper_mul_f64(res, cpu_env, res, src);
1.1 root 2341: break;
2342: case 0x28: case 0x68: case 0x6c: /* fsub */
1.1.1.3 root 2343: gen_helper_sub_f64(res, cpu_env, res, src);
1.1 root 2344: break;
2345: case 0x38: /* fcmp */
1.1.1.3 root 2346: gen_helper_sub_cmp_f64(res, cpu_env, res, src);
2347: set_dest = 0;
1.1 root 2348: round = 0;
2349: break;
2350: case 0x3a: /* ftst */
1.1.1.3 root 2351: tcg_gen_mov_f64(res, src);
2352: set_dest = 0;
1.1 root 2353: round = 0;
2354: break;
2355: default:
2356: goto undef;
2357: }
1.1.1.3 root 2358: if (ext & (1 << 14)) {
2359: tcg_temp_free_i64(src);
2360: }
1.1 root 2361: if (round) {
2362: if (opmode & 0x40) {
2363: if ((opmode & 0x4) != 0)
2364: round = 0;
2365: } else if ((s->fpcr & M68K_FPCR_PREC) == 0) {
2366: round = 0;
2367: }
2368: }
2369: if (round) {
1.1.1.3 root 2370: TCGv tmp = tcg_temp_new_i32();
2371: gen_helper_f64_to_f32(tmp, cpu_env, res);
2372: gen_helper_f32_to_f64(res, cpu_env, tmp);
2373: tcg_temp_free_i32(tmp);
2374: }
2375: tcg_gen_mov_f64(QREG_FP_RESULT, res);
2376: if (set_dest) {
2377: tcg_gen_mov_f64(dest, res);
1.1 root 2378: }
1.1.1.3 root 2379: tcg_temp_free_i64(res);
1.1 root 2380: return;
2381: undef:
1.1.1.3 root 2382: /* FIXME: Is this right for offset addressing modes? */
1.1 root 2383: s->pc -= 2;
2384: disas_undef_fpu(s, insn);
2385: }
2386:
2387: DISAS_INSN(fbcc)
2388: {
2389: uint32_t offset;
2390: uint32_t addr;
1.1.1.3 root 2391: TCGv flag;
1.1 root 2392: int l1;
2393:
2394: addr = s->pc;
1.1.1.2 root 2395: offset = ldsw_code(s->pc);
1.1 root 2396: s->pc += 2;
2397: if (insn & (1 << 6)) {
1.1.1.2 root 2398: offset = (offset << 16) | lduw_code(s->pc);
1.1 root 2399: s->pc += 2;
2400: }
2401:
2402: l1 = gen_new_label();
2403: /* TODO: Raise BSUN exception. */
1.1.1.3 root 2404: flag = tcg_temp_new();
2405: gen_helper_compare_f64(flag, cpu_env, QREG_FP_RESULT);
1.1 root 2406: /* Jump to l1 if condition is true. */
2407: switch (insn & 0xf) {
2408: case 0: /* f */
2409: break;
2410: case 1: /* eq (=0) */
1.1.1.3 root 2411: tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
1.1 root 2412: break;
2413: case 2: /* ogt (=1) */
1.1.1.3 root 2414: tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(1), l1);
1.1 root 2415: break;
2416: case 3: /* oge (=0 or =1) */
1.1.1.3 root 2417: tcg_gen_brcond_i32(TCG_COND_LEU, flag, tcg_const_i32(1), l1);
1.1 root 2418: break;
2419: case 4: /* olt (=-1) */
1.1.1.3 root 2420: tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(0), l1);
1.1 root 2421: break;
2422: case 5: /* ole (=-1 or =0) */
1.1.1.3 root 2423: tcg_gen_brcond_i32(TCG_COND_LE, flag, tcg_const_i32(0), l1);
1.1 root 2424: break;
2425: case 6: /* ogl (=-1 or =1) */
1.1.1.3 root 2426: tcg_gen_andi_i32(flag, flag, 1);
2427: tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
1.1 root 2428: break;
2429: case 7: /* or (=2) */
1.1.1.3 root 2430: tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(2), l1);
1.1 root 2431: break;
2432: case 8: /* un (<2) */
1.1.1.3 root 2433: tcg_gen_brcond_i32(TCG_COND_LT, flag, tcg_const_i32(2), l1);
1.1 root 2434: break;
2435: case 9: /* ueq (=0 or =2) */
1.1.1.3 root 2436: tcg_gen_andi_i32(flag, flag, 1);
2437: tcg_gen_brcond_i32(TCG_COND_EQ, flag, tcg_const_i32(0), l1);
1.1 root 2438: break;
2439: case 10: /* ugt (>0) */
1.1.1.3 root 2440: tcg_gen_brcond_i32(TCG_COND_GT, flag, tcg_const_i32(0), l1);
1.1 root 2441: break;
2442: case 11: /* uge (>=0) */
1.1.1.3 root 2443: tcg_gen_brcond_i32(TCG_COND_GE, flag, tcg_const_i32(0), l1);
1.1 root 2444: break;
2445: case 12: /* ult (=-1 or =2) */
1.1.1.3 root 2446: tcg_gen_brcond_i32(TCG_COND_GEU, flag, tcg_const_i32(2), l1);
1.1 root 2447: break;
2448: case 13: /* ule (!=1) */
1.1.1.3 root 2449: tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(1), l1);
1.1 root 2450: break;
2451: case 14: /* ne (!=0) */
1.1.1.3 root 2452: tcg_gen_brcond_i32(TCG_COND_NE, flag, tcg_const_i32(0), l1);
1.1 root 2453: break;
2454: case 15: /* t */
1.1.1.3 root 2455: tcg_gen_br(l1);
1.1 root 2456: break;
2457: }
2458: gen_jmp_tb(s, 0, s->pc);
2459: gen_set_label(l1);
2460: gen_jmp_tb(s, 1, addr + offset);
2461: }
2462:
1.1.1.2 root 2463: DISAS_INSN(frestore)
2464: {
2465: /* TODO: Implement frestore. */
2466: qemu_assert(0, "FRESTORE not implemented");
2467: }
2468:
2469: DISAS_INSN(fsave)
2470: {
2471: /* TODO: Implement fsave. */
2472: qemu_assert(0, "FSAVE not implemented");
2473: }
2474:
1.1.1.3 root 2475: static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
1.1.1.2 root 2476: {
1.1.1.3 root 2477: TCGv tmp = tcg_temp_new();
1.1.1.2 root 2478: if (s->env->macsr & MACSR_FI) {
2479: if (upper)
1.1.1.3 root 2480: tcg_gen_andi_i32(tmp, val, 0xffff0000);
1.1.1.2 root 2481: else
1.1.1.3 root 2482: tcg_gen_shli_i32(tmp, val, 16);
1.1.1.2 root 2483: } else if (s->env->macsr & MACSR_SU) {
2484: if (upper)
1.1.1.3 root 2485: tcg_gen_sari_i32(tmp, val, 16);
1.1.1.2 root 2486: else
1.1.1.3 root 2487: tcg_gen_ext16s_i32(tmp, val);
1.1.1.2 root 2488: } else {
2489: if (upper)
1.1.1.3 root 2490: tcg_gen_shri_i32(tmp, val, 16);
1.1.1.2 root 2491: else
1.1.1.3 root 2492: tcg_gen_ext16u_i32(tmp, val);
1.1.1.2 root 2493: }
2494: return tmp;
2495: }
2496:
1.1.1.3 root 2497: static void gen_mac_clear_flags(void)
2498: {
2499: tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR,
2500: ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV));
2501: }
2502:
1.1.1.2 root 2503: DISAS_INSN(mac)
2504: {
1.1.1.3 root 2505: TCGv rx;
2506: TCGv ry;
1.1.1.2 root 2507: uint16_t ext;
2508: int acc;
1.1.1.3 root 2509: TCGv tmp;
2510: TCGv addr;
2511: TCGv loadval;
1.1.1.2 root 2512: int dual;
1.1.1.3 root 2513: TCGv saved_flags;
2514:
2515: if (!s->done_mac) {
2516: s->mactmp = tcg_temp_new_i64();
2517: s->done_mac = 1;
2518: }
1.1.1.2 root 2519:
2520: ext = lduw_code(s->pc);
2521: s->pc += 2;
2522:
2523: acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
2524: dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
2525: if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
2526: disas_undef(s, insn);
2527: return;
2528: }
2529: if (insn & 0x30) {
2530: /* MAC with load. */
2531: tmp = gen_lea(s, insn, OS_LONG);
1.1.1.3 root 2532: addr = tcg_temp_new();
2533: tcg_gen_and_i32(addr, tmp, QREG_MAC_MASK);
1.1.1.2 root 2534: /* Load the value now to ensure correct exception behavior.
2535: Perform writeback after reading the MAC inputs. */
2536: loadval = gen_load(s, OS_LONG, addr, 0);
2537:
2538: acc ^= 1;
2539: rx = (ext & 0x8000) ? AREG(ext, 12) : DREG(insn, 12);
2540: ry = (ext & 8) ? AREG(ext, 0) : DREG(ext, 0);
2541: } else {
1.1.1.3 root 2542: loadval = addr = NULL_QREG;
1.1.1.2 root 2543: rx = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
2544: ry = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
2545: }
2546:
1.1.1.3 root 2547: gen_mac_clear_flags();
2548: #if 0
1.1.1.2 root 2549: l1 = -1;
1.1.1.3 root 2550: /* Disabled because conditional branches clobber temporary vars. */
1.1.1.2 root 2551: if ((s->env->macsr & MACSR_OMC) != 0 && !dual) {
2552: /* Skip the multiply if we know we will ignore it. */
2553: l1 = gen_new_label();
1.1.1.3 root 2554: tmp = tcg_temp_new();
2555: tcg_gen_andi_i32(tmp, QREG_MACSR, 1 << (acc + 8));
1.1.1.2 root 2556: gen_op_jmp_nz32(tmp, l1);
2557: }
1.1.1.3 root 2558: #endif
1.1.1.2 root 2559:
2560: if ((ext & 0x0800) == 0) {
2561: /* Word. */
2562: rx = gen_mac_extract_word(s, rx, (ext & 0x80) != 0);
2563: ry = gen_mac_extract_word(s, ry, (ext & 0x40) != 0);
2564: }
2565: if (s->env->macsr & MACSR_FI) {
1.1.1.3 root 2566: gen_helper_macmulf(s->mactmp, cpu_env, rx, ry);
1.1.1.2 root 2567: } else {
2568: if (s->env->macsr & MACSR_SU)
1.1.1.3 root 2569: gen_helper_macmuls(s->mactmp, cpu_env, rx, ry);
1.1.1.2 root 2570: else
1.1.1.3 root 2571: gen_helper_macmulu(s->mactmp, cpu_env, rx, ry);
1.1.1.2 root 2572: switch ((ext >> 9) & 3) {
2573: case 1:
1.1.1.3 root 2574: tcg_gen_shli_i64(s->mactmp, s->mactmp, 1);
1.1.1.2 root 2575: break;
2576: case 3:
1.1.1.3 root 2577: tcg_gen_shri_i64(s->mactmp, s->mactmp, 1);
1.1.1.2 root 2578: break;
2579: }
2580: }
2581:
2582: if (dual) {
2583: /* Save the overflow flag from the multiply. */
1.1.1.3 root 2584: saved_flags = tcg_temp_new();
2585: tcg_gen_mov_i32(saved_flags, QREG_MACSR);
2586: } else {
2587: saved_flags = NULL_QREG;
1.1.1.2 root 2588: }
2589:
1.1.1.3 root 2590: #if 0
2591: /* Disabled because conditional branches clobber temporary vars. */
1.1.1.2 root 2592: if ((s->env->macsr & MACSR_OMC) != 0 && dual) {
2593: /* Skip the accumulate if the value is already saturated. */
2594: l1 = gen_new_label();
1.1.1.3 root 2595: tmp = tcg_temp_new();
1.1.1.2 root 2596: gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2597: gen_op_jmp_nz32(tmp, l1);
2598: }
1.1.1.3 root 2599: #endif
1.1.1.2 root 2600:
2601: if (insn & 0x100)
1.1.1.3 root 2602: tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
1.1.1.2 root 2603: else
1.1.1.3 root 2604: tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
1.1.1.2 root 2605:
2606: if (s->env->macsr & MACSR_FI)
1.1.1.3 root 2607: gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2608: else if (s->env->macsr & MACSR_SU)
1.1.1.3 root 2609: gen_helper_macsats(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2610: else
1.1.1.3 root 2611: gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2612:
1.1.1.3 root 2613: #if 0
2614: /* Disabled because conditional branches clobber temporary vars. */
1.1.1.2 root 2615: if (l1 != -1)
2616: gen_set_label(l1);
1.1.1.3 root 2617: #endif
1.1.1.2 root 2618:
2619: if (dual) {
2620: /* Dual accumulate variant. */
2621: acc = (ext >> 2) & 3;
2622: /* Restore the overflow flag from the multiplier. */
1.1.1.3 root 2623: tcg_gen_mov_i32(QREG_MACSR, saved_flags);
2624: #if 0
2625: /* Disabled because conditional branches clobber temporary vars. */
1.1.1.2 root 2626: if ((s->env->macsr & MACSR_OMC) != 0) {
2627: /* Skip the accumulate if the value is already saturated. */
2628: l1 = gen_new_label();
1.1.1.3 root 2629: tmp = tcg_temp_new();
1.1.1.2 root 2630: gen_op_and32(tmp, QREG_MACSR, gen_im32(MACSR_PAV0 << acc));
2631: gen_op_jmp_nz32(tmp, l1);
2632: }
1.1.1.3 root 2633: #endif
1.1.1.2 root 2634: if (ext & 2)
1.1.1.3 root 2635: tcg_gen_sub_i64(MACREG(acc), MACREG(acc), s->mactmp);
1.1.1.2 root 2636: else
1.1.1.3 root 2637: tcg_gen_add_i64(MACREG(acc), MACREG(acc), s->mactmp);
1.1.1.2 root 2638: if (s->env->macsr & MACSR_FI)
1.1.1.3 root 2639: gen_helper_macsatf(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2640: else if (s->env->macsr & MACSR_SU)
1.1.1.3 root 2641: gen_helper_macsats(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2642: else
1.1.1.3 root 2643: gen_helper_macsatu(cpu_env, tcg_const_i32(acc));
2644: #if 0
2645: /* Disabled because conditional branches clobber temporary vars. */
1.1.1.2 root 2646: if (l1 != -1)
2647: gen_set_label(l1);
1.1.1.3 root 2648: #endif
1.1.1.2 root 2649: }
1.1.1.3 root 2650: gen_helper_mac_set_flags(cpu_env, tcg_const_i32(acc));
1.1.1.2 root 2651:
2652: if (insn & 0x30) {
1.1.1.3 root 2653: TCGv rw;
1.1.1.2 root 2654: rw = (insn & 0x40) ? AREG(insn, 9) : DREG(insn, 9);
1.1.1.3 root 2655: tcg_gen_mov_i32(rw, loadval);
1.1.1.2 root 2656: /* FIXME: Should address writeback happen with the masked or
2657: unmasked value? */
2658: switch ((insn >> 3) & 7) {
2659: case 3: /* Post-increment. */
1.1.1.3 root 2660: tcg_gen_addi_i32(AREG(insn, 0), addr, 4);
1.1.1.2 root 2661: break;
2662: case 4: /* Pre-decrement. */
1.1.1.3 root 2663: tcg_gen_mov_i32(AREG(insn, 0), addr);
1.1.1.2 root 2664: }
2665: }
2666: }
2667:
2668: DISAS_INSN(from_mac)
2669: {
1.1.1.3 root 2670: TCGv rx;
2671: TCGv_i64 acc;
2672: int accnum;
1.1.1.2 root 2673:
2674: rx = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
1.1.1.3 root 2675: accnum = (insn >> 9) & 3;
2676: acc = MACREG(accnum);
1.1.1.2 root 2677: if (s->env->macsr & MACSR_FI) {
1.1.1.3 root 2678: gen_helper_get_macf(rx, cpu_env, acc);
1.1.1.2 root 2679: } else if ((s->env->macsr & MACSR_OMC) == 0) {
1.1.1.3 root 2680: tcg_gen_trunc_i64_i32(rx, acc);
1.1.1.2 root 2681: } else if (s->env->macsr & MACSR_SU) {
1.1.1.3 root 2682: gen_helper_get_macs(rx, acc);
1.1.1.2 root 2683: } else {
1.1.1.3 root 2684: gen_helper_get_macu(rx, acc);
2685: }
2686: if (insn & 0x40) {
2687: tcg_gen_movi_i64(acc, 0);
2688: tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
1.1.1.2 root 2689: }
2690: }
2691:
2692: DISAS_INSN(move_mac)
2693: {
1.1.1.3 root 2694: /* FIXME: This can be done without a helper. */
1.1.1.2 root 2695: int src;
1.1.1.3 root 2696: TCGv dest;
1.1.1.2 root 2697: src = insn & 3;
1.1.1.3 root 2698: dest = tcg_const_i32((insn >> 9) & 3);
2699: gen_helper_mac_move(cpu_env, dest, tcg_const_i32(src));
2700: gen_mac_clear_flags();
2701: gen_helper_mac_set_flags(cpu_env, dest);
1.1.1.2 root 2702: }
2703:
2704: DISAS_INSN(from_macsr)
2705: {
1.1.1.3 root 2706: TCGv reg;
1.1.1.2 root 2707:
2708: reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
1.1.1.3 root 2709: tcg_gen_mov_i32(reg, QREG_MACSR);
1.1.1.2 root 2710: }
2711:
2712: DISAS_INSN(from_mask)
2713: {
1.1.1.3 root 2714: TCGv reg;
1.1.1.2 root 2715: reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
1.1.1.3 root 2716: tcg_gen_mov_i32(reg, QREG_MAC_MASK);
1.1.1.2 root 2717: }
2718:
2719: DISAS_INSN(from_mext)
2720: {
1.1.1.3 root 2721: TCGv reg;
2722: TCGv acc;
1.1.1.2 root 2723: reg = (insn & 8) ? AREG(insn, 0) : DREG(insn, 0);
1.1.1.3 root 2724: acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
1.1.1.2 root 2725: if (s->env->macsr & MACSR_FI)
1.1.1.3 root 2726: gen_helper_get_mac_extf(reg, cpu_env, acc);
1.1.1.2 root 2727: else
1.1.1.3 root 2728: gen_helper_get_mac_exti(reg, cpu_env, acc);
1.1.1.2 root 2729: }
2730:
2731: DISAS_INSN(macsr_to_ccr)
2732: {
1.1.1.3 root 2733: tcg_gen_movi_i32(QREG_CC_X, 0);
2734: tcg_gen_andi_i32(QREG_CC_DEST, QREG_MACSR, 0xf);
1.1.1.2 root 2735: s->cc_op = CC_OP_FLAGS;
2736: }
2737:
2738: DISAS_INSN(to_mac)
2739: {
1.1.1.3 root 2740: TCGv_i64 acc;
2741: TCGv val;
2742: int accnum;
2743: accnum = (insn >> 9) & 3;
2744: acc = MACREG(accnum);
1.1.1.2 root 2745: SRC_EA(val, OS_LONG, 0, NULL);
2746: if (s->env->macsr & MACSR_FI) {
1.1.1.3 root 2747: tcg_gen_ext_i32_i64(acc, val);
2748: tcg_gen_shli_i64(acc, acc, 8);
1.1.1.2 root 2749: } else if (s->env->macsr & MACSR_SU) {
1.1.1.3 root 2750: tcg_gen_ext_i32_i64(acc, val);
1.1.1.2 root 2751: } else {
1.1.1.3 root 2752: tcg_gen_extu_i32_i64(acc, val);
1.1.1.2 root 2753: }
1.1.1.3 root 2754: tcg_gen_andi_i32(QREG_MACSR, QREG_MACSR, ~(MACSR_PAV0 << accnum));
2755: gen_mac_clear_flags();
2756: gen_helper_mac_set_flags(cpu_env, tcg_const_i32(accnum));
1.1.1.2 root 2757: }
2758:
2759: DISAS_INSN(to_macsr)
2760: {
1.1.1.3 root 2761: TCGv val;
1.1.1.2 root 2762: SRC_EA(val, OS_LONG, 0, NULL);
1.1.1.3 root 2763: gen_helper_set_macsr(cpu_env, val);
1.1.1.2 root 2764: gen_lookup_tb(s);
2765: }
2766:
2767: DISAS_INSN(to_mask)
2768: {
1.1.1.3 root 2769: TCGv val;
1.1.1.2 root 2770: SRC_EA(val, OS_LONG, 0, NULL);
1.1.1.3 root 2771: tcg_gen_ori_i32(QREG_MAC_MASK, val, 0xffff0000);
1.1.1.2 root 2772: }
2773:
2774: DISAS_INSN(to_mext)
2775: {
1.1.1.3 root 2776: TCGv val;
2777: TCGv acc;
1.1.1.2 root 2778: SRC_EA(val, OS_LONG, 0, NULL);
1.1.1.3 root 2779: acc = tcg_const_i32((insn & 0x400) ? 2 : 0);
1.1.1.2 root 2780: if (s->env->macsr & MACSR_FI)
1.1.1.3 root 2781: gen_helper_set_mac_extf(cpu_env, val, acc);
1.1.1.2 root 2782: else if (s->env->macsr & MACSR_SU)
1.1.1.3 root 2783: gen_helper_set_mac_exts(cpu_env, val, acc);
1.1.1.2 root 2784: else
1.1.1.3 root 2785: gen_helper_set_mac_extu(cpu_env, val, acc);
1.1.1.2 root 2786: }
2787:
1.1 root 2788: static disas_proc opcode_table[65536];
2789:
2790: static void
2791: register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask)
2792: {
2793: int i;
2794: int from;
2795: int to;
2796:
2797: /* Sanity check. All set bits must be included in the mask. */
1.1.1.2 root 2798: if (opcode & ~mask) {
2799: fprintf(stderr,
2800: "qemu internal error: bogus opcode definition %04x/%04x\n",
2801: opcode, mask);
1.1 root 2802: abort();
1.1.1.2 root 2803: }
1.1 root 2804: /* This could probably be cleverer. For now just optimize the case where
2805: the top bits are known. */
2806: /* Find the first zero bit in the mask. */
2807: i = 0x8000;
2808: while ((i & mask) != 0)
2809: i >>= 1;
2810: /* Iterate over all combinations of this and lower bits. */
2811: if (i == 0)
2812: i = 1;
2813: else
2814: i <<= 1;
2815: from = opcode & ~(i - 1);
2816: to = from + i;
1.1.1.2 root 2817: for (i = from; i < to; i++) {
1.1 root 2818: if ((i & mask) == opcode)
2819: opcode_table[i] = proc;
1.1.1.2 root 2820: }
1.1 root 2821: }
2822:
2823: /* Register m68k opcode handlers. Order is important.
2824: Later insn override earlier ones. */
1.1.1.2 root 2825: void register_m68k_insns (CPUM68KState *env)
1.1 root 2826: {
1.1.1.2 root 2827: #define INSN(name, opcode, mask, feature) do { \
2828: if (m68k_feature(env, M68K_FEATURE_##feature)) \
2829: register_opcode(disas_##name, 0x##opcode, 0x##mask); \
2830: } while(0)
2831: INSN(undef, 0000, 0000, CF_ISA_A);
2832: INSN(arith_im, 0080, fff8, CF_ISA_A);
2833: INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC);
2834: INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
2835: INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
2836: INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
2837: INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
2838: INSN(arith_im, 0280, fff8, CF_ISA_A);
2839: INSN(byterev, 02c0, fff8, CF_ISA_APLUSC);
2840: INSN(arith_im, 0480, fff8, CF_ISA_A);
2841: INSN(ff1, 04c0, fff8, CF_ISA_APLUSC);
2842: INSN(arith_im, 0680, fff8, CF_ISA_A);
2843: INSN(bitop_im, 0800, ffc0, CF_ISA_A);
2844: INSN(bitop_im, 0840, ffc0, CF_ISA_A);
2845: INSN(bitop_im, 0880, ffc0, CF_ISA_A);
2846: INSN(bitop_im, 08c0, ffc0, CF_ISA_A);
2847: INSN(arith_im, 0a80, fff8, CF_ISA_A);
2848: INSN(arith_im, 0c00, ff38, CF_ISA_A);
2849: INSN(move, 1000, f000, CF_ISA_A);
2850: INSN(move, 2000, f000, CF_ISA_A);
2851: INSN(move, 3000, f000, CF_ISA_A);
2852: INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC);
2853: INSN(negx, 4080, fff8, CF_ISA_A);
2854: INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
2855: INSN(lea, 41c0, f1c0, CF_ISA_A);
2856: INSN(clr, 4200, ff00, CF_ISA_A);
2857: INSN(undef, 42c0, ffc0, CF_ISA_A);
2858: INSN(move_from_ccr, 42c0, fff8, CF_ISA_A);
2859: INSN(neg, 4480, fff8, CF_ISA_A);
2860: INSN(move_to_ccr, 44c0, ffc0, CF_ISA_A);
2861: INSN(not, 4680, fff8, CF_ISA_A);
2862: INSN(move_to_sr, 46c0, ffc0, CF_ISA_A);
2863: INSN(pea, 4840, ffc0, CF_ISA_A);
2864: INSN(swap, 4840, fff8, CF_ISA_A);
2865: INSN(movem, 48c0, fbc0, CF_ISA_A);
2866: INSN(ext, 4880, fff8, CF_ISA_A);
2867: INSN(ext, 48c0, fff8, CF_ISA_A);
2868: INSN(ext, 49c0, fff8, CF_ISA_A);
2869: INSN(tst, 4a00, ff00, CF_ISA_A);
2870: INSN(tas, 4ac0, ffc0, CF_ISA_B);
2871: INSN(halt, 4ac8, ffff, CF_ISA_A);
2872: INSN(pulse, 4acc, ffff, CF_ISA_A);
2873: INSN(illegal, 4afc, ffff, CF_ISA_A);
2874: INSN(mull, 4c00, ffc0, CF_ISA_A);
2875: INSN(divl, 4c40, ffc0, CF_ISA_A);
2876: INSN(sats, 4c80, fff8, CF_ISA_B);
2877: INSN(trap, 4e40, fff0, CF_ISA_A);
2878: INSN(link, 4e50, fff8, CF_ISA_A);
2879: INSN(unlk, 4e58, fff8, CF_ISA_A);
2880: INSN(move_to_usp, 4e60, fff8, USP);
2881: INSN(move_from_usp, 4e68, fff8, USP);
2882: INSN(nop, 4e71, ffff, CF_ISA_A);
2883: INSN(stop, 4e72, ffff, CF_ISA_A);
2884: INSN(rte, 4e73, ffff, CF_ISA_A);
2885: INSN(rts, 4e75, ffff, CF_ISA_A);
2886: INSN(movec, 4e7b, ffff, CF_ISA_A);
2887: INSN(jump, 4e80, ffc0, CF_ISA_A);
2888: INSN(jump, 4ec0, ffc0, CF_ISA_A);
2889: INSN(addsubq, 5180, f1c0, CF_ISA_A);
2890: INSN(scc, 50c0, f0f8, CF_ISA_A);
2891: INSN(addsubq, 5080, f1c0, CF_ISA_A);
2892: INSN(tpf, 51f8, fff8, CF_ISA_A);
2893:
2894: /* Branch instructions. */
2895: INSN(branch, 6000, f000, CF_ISA_A);
2896: /* Disable long branch instructions, then add back the ones we want. */
2897: INSN(undef, 60ff, f0ff, CF_ISA_A); /* All long branches. */
2898: INSN(branch, 60ff, f0ff, CF_ISA_B);
2899: INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */
2900: INSN(branch, 60ff, ffff, BRAL);
2901:
2902: INSN(moveq, 7000, f100, CF_ISA_A);
2903: INSN(mvzs, 7100, f100, CF_ISA_B);
2904: INSN(or, 8000, f000, CF_ISA_A);
2905: INSN(divw, 80c0, f0c0, CF_ISA_A);
2906: INSN(addsub, 9000, f000, CF_ISA_A);
2907: INSN(subx, 9180, f1f8, CF_ISA_A);
2908: INSN(suba, 91c0, f1c0, CF_ISA_A);
2909:
2910: INSN(undef_mac, a000, f000, CF_ISA_A);
2911: INSN(mac, a000, f100, CF_EMAC);
2912: INSN(from_mac, a180, f9b0, CF_EMAC);
2913: INSN(move_mac, a110, f9fc, CF_EMAC);
2914: INSN(from_macsr,a980, f9f0, CF_EMAC);
2915: INSN(from_mask, ad80, fff0, CF_EMAC);
2916: INSN(from_mext, ab80, fbf0, CF_EMAC);
2917: INSN(macsr_to_ccr, a9c0, ffff, CF_EMAC);
2918: INSN(to_mac, a100, f9c0, CF_EMAC);
2919: INSN(to_macsr, a900, ffc0, CF_EMAC);
2920: INSN(to_mext, ab00, fbc0, CF_EMAC);
2921: INSN(to_mask, ad00, ffc0, CF_EMAC);
2922:
2923: INSN(mov3q, a140, f1c0, CF_ISA_B);
2924: INSN(cmp, b000, f1c0, CF_ISA_B); /* cmp.b */
2925: INSN(cmp, b040, f1c0, CF_ISA_B); /* cmp.w */
2926: INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */
2927: INSN(cmp, b080, f1c0, CF_ISA_A);
2928: INSN(cmpa, b1c0, f1c0, CF_ISA_A);
2929: INSN(eor, b180, f1c0, CF_ISA_A);
2930: INSN(and, c000, f000, CF_ISA_A);
2931: INSN(mulw, c0c0, f0c0, CF_ISA_A);
2932: INSN(addsub, d000, f000, CF_ISA_A);
2933: INSN(addx, d180, f1f8, CF_ISA_A);
2934: INSN(adda, d1c0, f1c0, CF_ISA_A);
2935: INSN(shift_im, e080, f0f0, CF_ISA_A);
2936: INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
2937: INSN(undef_fpu, f000, f000, CF_ISA_A);
1.1 root 2938: INSN(fpu, f200, ffc0, CF_FPU);
2939: INSN(fbcc, f280, ffc0, CF_FPU);
1.1.1.2 root 2940: INSN(frestore, f340, ffc0, CF_FPU);
2941: INSN(fsave, f340, ffc0, CF_FPU);
2942: INSN(intouch, f340, ffc0, CF_ISA_A);
2943: INSN(cpushl, f428, ff38, CF_ISA_A);
2944: INSN(wddata, fb00, ff00, CF_ISA_A);
2945: INSN(wdebug, fbc0, ffc0, CF_ISA_A);
1.1 root 2946: #undef INSN
2947: }
2948:
2949: /* ??? Some of this implementation is not exception safe. We should always
2950: write back the result to memory before setting the condition codes. */
2951: static void disas_m68k_insn(CPUState * env, DisasContext *s)
2952: {
2953: uint16_t insn;
2954:
1.1.1.2 root 2955: insn = lduw_code(s->pc);
1.1 root 2956: s->pc += 2;
2957:
2958: opcode_table[insn](s, insn);
2959: }
2960:
2961: /* generate intermediate code for basic block 'tb'. */
1.1.1.3 root 2962: static inline void
1.1.1.2 root 2963: gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2964: int search_pc)
1.1 root 2965: {
2966: DisasContext dc1, *dc = &dc1;
2967: uint16_t *gen_opc_end;
1.1.1.3 root 2968: CPUBreakpoint *bp;
1.1 root 2969: int j, lj;
2970: target_ulong pc_start;
2971: int pc_offset;
2972: int last_cc_op;
1.1.1.3 root 2973: int num_insns;
2974: int max_insns;
1.1 root 2975:
2976: /* generate intermediate code */
2977: pc_start = tb->pc;
1.1.1.2 root 2978:
1.1 root 2979: dc->tb = tb;
2980:
2981: gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2982:
1.1.1.2 root 2983: dc->env = env;
1.1 root 2984: dc->is_jmp = DISAS_NEXT;
2985: dc->pc = pc_start;
2986: dc->cc_op = CC_OP_DYNAMIC;
2987: dc->singlestep_enabled = env->singlestep_enabled;
2988: dc->fpcr = env->fpcr;
1.1.1.2 root 2989: dc->user = (env->sr & SR_S) == 0;
2990: dc->is_mem = 0;
1.1.1.3 root 2991: dc->done_mac = 0;
1.1 root 2992: lj = -1;
1.1.1.3 root 2993: num_insns = 0;
2994: max_insns = tb->cflags & CF_COUNT_MASK;
2995: if (max_insns == 0)
2996: max_insns = CF_COUNT_MASK;
2997:
2998: gen_icount_start();
1.1 root 2999: do {
3000: pc_offset = dc->pc - pc_start;
3001: gen_throws_exception = NULL;
1.1.1.3 root 3002: if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
3003: TAILQ_FOREACH(bp, &env->breakpoints, entry) {
3004: if (bp->pc == dc->pc) {
1.1 root 3005: gen_exception(dc, dc->pc, EXCP_DEBUG);
3006: dc->is_jmp = DISAS_JUMP;
3007: break;
3008: }
3009: }
3010: if (dc->is_jmp)
3011: break;
3012: }
3013: if (search_pc) {
3014: j = gen_opc_ptr - gen_opc_buf;
3015: if (lj < j) {
3016: lj++;
3017: while (lj < j)
3018: gen_opc_instr_start[lj++] = 0;
3019: }
3020: gen_opc_pc[lj] = dc->pc;
3021: gen_opc_instr_start[lj] = 1;
1.1.1.3 root 3022: gen_opc_icount[lj] = num_insns;
1.1 root 3023: }
1.1.1.3 root 3024: if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
3025: gen_io_start();
1.1 root 3026: last_cc_op = dc->cc_op;
1.1.1.2 root 3027: dc->insn_pc = dc->pc;
1.1 root 3028: disas_m68k_insn(env, dc);
1.1.1.3 root 3029: num_insns++;
1.1 root 3030: } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3031: !env->singlestep_enabled &&
1.1.1.4 ! root 3032: !singlestep &&
1.1.1.3 root 3033: (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
3034: num_insns < max_insns);
1.1 root 3035:
1.1.1.3 root 3036: if (tb->cflags & CF_LAST_IO)
3037: gen_io_end();
3038: if (unlikely(env->singlestep_enabled)) {
1.1 root 3039: /* Make sure the pc is updated, and raise a debug exception. */
3040: if (!dc->is_jmp) {
3041: gen_flush_cc_op(dc);
1.1.1.3 root 3042: tcg_gen_movi_i32(QREG_PC, dc->pc);
1.1 root 3043: }
1.1.1.3 root 3044: gen_helper_raise_exception(tcg_const_i32(EXCP_DEBUG));
1.1 root 3045: } else {
3046: switch(dc->is_jmp) {
3047: case DISAS_NEXT:
3048: gen_flush_cc_op(dc);
3049: gen_jmp_tb(dc, 0, dc->pc);
3050: break;
3051: default:
3052: case DISAS_JUMP:
3053: case DISAS_UPDATE:
3054: gen_flush_cc_op(dc);
3055: /* indicate that the hash table must be used to find the next TB */
1.1.1.3 root 3056: tcg_gen_exit_tb(0);
1.1 root 3057: break;
3058: case DISAS_TB_JUMP:
3059: /* nothing more to generate */
3060: break;
3061: }
3062: }
1.1.1.3 root 3063: gen_icount_end(tb, num_insns);
1.1 root 3064: *gen_opc_ptr = INDEX_op_end;
3065:
3066: #ifdef DEBUG_DISAS
1.1.1.3 root 3067: if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
3068: qemu_log("----------------\n");
3069: qemu_log("IN: %s\n", lookup_symbol(pc_start));
3070: log_target_disas(pc_start, dc->pc - pc_start, 0);
3071: qemu_log("\n");
1.1 root 3072: }
3073: #endif
3074: if (search_pc) {
3075: j = gen_opc_ptr - gen_opc_buf;
3076: lj++;
3077: while (lj <= j)
3078: gen_opc_instr_start[lj++] = 0;
3079: } else {
3080: tb->size = dc->pc - pc_start;
1.1.1.3 root 3081: tb->icount = num_insns;
1.1 root 3082: }
3083:
3084: //optimize_flags();
3085: //expand_target_qops();
3086: }
3087:
1.1.1.3 root 3088: void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1.1 root 3089: {
1.1.1.3 root 3090: gen_intermediate_code_internal(env, tb, 0);
1.1 root 3091: }
3092:
1.1.1.3 root 3093: void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1.1 root 3094: {
1.1.1.3 root 3095: gen_intermediate_code_internal(env, tb, 1);
1.1 root 3096: }
3097:
1.1.1.2 root 3098: void cpu_dump_state(CPUState *env, FILE *f,
1.1 root 3099: int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
3100: int flags)
3101: {
3102: int i;
3103: uint16_t sr;
3104: CPU_DoubleU u;
3105: for (i = 0; i < 8; i++)
3106: {
3107: u.d = env->fregs[i];
3108: cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
3109: i, env->dregs[i], i, env->aregs[i],
1.1.1.2 root 3110: i, u.l.upper, u.l.lower, *(double *)&u.d);
1.1 root 3111: }
3112: cpu_fprintf (f, "PC = %08x ", env->pc);
3113: sr = env->sr;
3114: cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
3115: (sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
3116: (sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
1.1.1.2 root 3117: cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
1.1 root 3118: }
3119:
1.1.1.3 root 3120: void gen_pc_load(CPUState *env, TranslationBlock *tb,
3121: unsigned long searched_pc, int pc_pos, void *puc)
3122: {
3123: env->pc = gen_opc_pc[pc_pos];
3124: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.