/*
* m68k translation
- *
+ *
* Copyright (c) 2005-2007 CodeSourcery
* Written by Paul Brook
*
#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
+#include "tcg-op.h"
#include "m68k-qreg.h"
//#define DEBUG_DISPATCH 1
uint32_t fpcr;
struct TranslationBlock *tb;
int singlestep_enabled;
+ int is_mem;
} DisasContext;
#define DISAS_JUMP_NEXT 4
static void *gen_throws_exception;
#define gen_last_qop NULL
-static uint16_t *gen_opc_ptr;
-static uint32_t *gen_opparam_ptr;
extern FILE *logfile;
extern int loglevel;
-enum {
-#define DEF(s, n, copy_size) INDEX_op_ ## s,
-#include "opc.h"
-#undef DEF
- NB_OPS,
-};
-
-#include "gen-op.h"
-
#if defined(CONFIG_USER_ONLY)
#define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
#define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
static inline int gen_load(DisasContext * s, int opsize, int addr, int sign)
{
int tmp;
+ s->is_mem = 1;
switch(opsize) {
case OS_BYTE:
tmp = gen_new_qreg(QMODE_I32);
/* Generate a store. */
static inline void gen_store(DisasContext *s, int opsize, int addr, int val)
{
+ s->is_mem = 1;
switch(opsize) {
case OS_BYTE:
gen_st(s, 8, addr, val);
{
if (s->cc_op == CC_OP_FLAGS)
return;
- gen_op_flush_flags(s->cc_op);
+ gen_flush_cc_op(s);
+ gen_op_flush_flags();
s->cc_op = CC_OP_FLAGS;
}
gen_flush_flags(s);
switch (cond) {
case 0: /* T */
- gen_op_jmp(l1);
+ gen_op_jmp_im(l1);
break;
case 1: /* F */
break;
gen_op_xor32(tmp, tmp, QREG_CC_DEST);
gen_op_and32(tmp, tmp, gen_im32(CCF_V));
gen_op_jmp_nz32(tmp, l2);
- gen_op_jmp(l1);
+ gen_op_jmp_im(l1);
gen_set_label(l2);
}
break;
gen_exception(s, dest, EXCP_DEBUG);
} else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
(s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
- gen_op_goto_tb(0, n, (long)tb);
+ tcg_gen_goto_tb(n);
gen_op_mov32(QREG_PC, gen_im32(dest));
- gen_op_mov32(QREG_T0, gen_im32((long)tb + n));
- gen_op_exit_tb();
+ tcg_gen_exit_tb((long)tb + n);
} else {
gen_jmp(s, gen_im32(dest));
- gen_op_mov32(QREG_T0, gen_im32(0));
- gen_op_exit_tb();
+ tcg_gen_exit_tb(0);
}
s->is_jmp = DISAS_TB_JUMP;
}
gen_op_logic_cc(gen_im32(val & 0xf));
gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4));
if (!ccr_only) {
- gen_op_mov32(QREG_SR, gen_im32(val & 0xff00));
+ gen_op_set_sr(gen_im32(val & 0xff00));
}
}
gen_op_and32(src1, src1, gen_im32(1));
gen_op_update_xflag_tst(src1);
if (!ccr_only) {
- gen_op_and32(QREG_SR, reg, gen_im32(0xff00));
+ gen_op_set_sr(reg);
}
}
else if ((insn & 0x3f) == 0x3c)
uint32_t base;
int op;
int l1;
-
+
base = s->pc;
op = (insn >> 8) & 0xf;
offset = (int8_t)insn;
}
DEST_EA(insn, OS_LONG, res, NULL);
break;
- case 6: /* fmovem */
+ case 6: /* fmovem */
case 7:
{
int addr;
dest = QREG_F0;
while (mask) {
if (ext & mask) {
+ s->is_mem = 1;
if (ext & (1 << 13)) {
/* store */
gen_st(s, f64, addr, dest);
tmp = gen_new_qreg(QMODE_F32);
gen_op_f64_to_f32(tmp, res);
gen_op_f32_to_f64(res, tmp);
- }
+ }
gen_op_fp_result(res);
if (dest) {
gen_op_movf64(dest, res);
acc = ((insn >> 7) & 1) | ((ext >> 3) & 2);
dual = ((insn & 0x30) != 0 && (ext & 3) != 0);
+ if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) {
+ disas_undef(s, insn);
+ return;
+ }
if (insn & 0x30) {
/* MAC with load. */
tmp = gen_lea(s, insn, OS_LONG);
Later insn override earlier ones. */
void register_m68k_insns (CPUM68KState *env)
{
-#define INSN(name, opcode, mask, feature) \
+#define INSN(name, opcode, mask, feature) do { \
if (m68k_feature(env, M68K_FEATURE_##feature)) \
- register_opcode(disas_##name, 0x##opcode, 0x##mask)
+ register_opcode(disas_##name, 0x##opcode, 0x##mask); \
+ } while(0)
INSN(undef, 0000, 0000, CF_ISA_A);
INSN(arith_im, 0080, fff8, CF_ISA_A);
- INSN(bitrev, 00c0, fff8, CF_ISA_C);
+ INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC);
INSN(bitop_reg, 0100, f1c0, CF_ISA_A);
INSN(bitop_reg, 0140, f1c0, CF_ISA_A);
INSN(bitop_reg, 0180, f1c0, CF_ISA_A);
INSN(bitop_reg, 01c0, f1c0, CF_ISA_A);
INSN(arith_im, 0280, fff8, CF_ISA_A);
- INSN(byterev, 02c0, fff8, CF_ISA_A);
+ INSN(byterev, 02c0, fff8, CF_ISA_APLUSC);
INSN(arith_im, 0480, fff8, CF_ISA_A);
- INSN(ff1, 04c0, fff8, CF_ISA_C);
+ INSN(ff1, 04c0, fff8, CF_ISA_APLUSC);
INSN(arith_im, 0680, fff8, CF_ISA_A);
INSN(bitop_im, 0800, ffc0, CF_ISA_A);
INSN(bitop_im, 0840, ffc0, CF_ISA_A);
INSN(move, 1000, f000, CF_ISA_A);
INSN(move, 2000, f000, CF_ISA_A);
INSN(move, 3000, f000, CF_ISA_A);
- INSN(strldsr, 40e7, ffff, CF_ISA_A);
+ INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC);
INSN(negx, 4080, fff8, CF_ISA_A);
INSN(move_from_sr, 40c0, fff8, CF_ISA_A);
INSN(lea, 41c0, f1c0, CF_ISA_A);
INSN(trap, 4e40, fff0, CF_ISA_A);
INSN(link, 4e50, fff8, CF_ISA_A);
INSN(unlk, 4e58, fff8, CF_ISA_A);
- INSN(move_to_usp, 4e60, fff8, CF_ISA_B);
- INSN(move_from_usp, 4e68, fff8, CF_ISA_B);
+ INSN(move_to_usp, 4e60, fff8, USP);
+ INSN(move_from_usp, 4e68, fff8, USP);
INSN(nop, 4e71, ffff, CF_ISA_A);
INSN(stop, 4e72, ffff, CF_ISA_A);
INSN(rte, 4e73, ffff, CF_ISA_A);
INSN(scc, 50c0, f0f8, CF_ISA_A);
INSN(addsubq, 5080, f1c0, CF_ISA_A);
INSN(tpf, 51f8, fff8, CF_ISA_A);
+
+ /* Branch instructions. */
INSN(branch, 6000, f000, CF_ISA_A);
+ /* Disable long branch instructions, then add back the ones we want. */
+ INSN(undef, 60ff, f0ff, CF_ISA_A); /* All long branches. */
+ INSN(branch, 60ff, f0ff, CF_ISA_B);
+ INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */
+ INSN(branch, 60ff, ffff, BRAL);
+
INSN(moveq, 7000, f100, CF_ISA_A);
INSN(mvzs, 7100, f100, CF_ISA_B);
INSN(or, 8000, f000, CF_ISA_A);
int arg0 = qop->args[0];
int arg1 = qop->args[1];
int l1, l2;
-
+
gen_op_add32 (arg0, arg0, arg1);
l1 = gen_new_label();
l2 = gen_new_label();
gen_op_add32(arg0, arg0, gen_im32(1));
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
gen_op_set_leu32(QREG_CC_X, arg0, arg1);
- gen_op_jmp(l2);
+ gen_op_jmp_im(l2);
gen_set_label(l1);
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
gen_op_set_leu32(QREG_CC_X, arg0, arg1);
gen_op_sub32(arg0, arg0, gen_im32(1));
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
- gen_op_jmp(l2);
+ gen_op_jmp_im(l2);
gen_set_label(l1);
gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
/* generate intermediate code */
pc_start = tb->pc;
-
+
dc->tb = tb;
- gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
- gen_opparam_ptr = gen_opparam_buf;
dc->env = env;
dc->is_jmp = DISAS_NEXT;
dc->singlestep_enabled = env->singlestep_enabled;
dc->fpcr = env->fpcr;
dc->user = (env->sr & SR_S) == 0;
- nb_gen_labels = 0;
+ dc->is_mem = 0;
lj = -1;
do {
free_qreg = 0;
last_cc_op = dc->cc_op;
dc->insn_pc = dc->pc;
disas_m68k_insn(env, dc);
+
+ /* Terminate the TB on memory ops if watchpoints are present. */
+ /* FIXME: This should be replacd by the deterministic execution
+ * IRQ raising bits. */
+ if (dc->is_mem && env->nb_watchpoints)
+ break;
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
!env->singlestep_enabled &&
(pc_offset) < (TARGET_PAGE_SIZE - 32));
case DISAS_UPDATE:
gen_flush_cc_op(dc);
/* indicate that the hash table must be used to find the next TB */
- gen_op_mov32(QREG_T0, gen_im32(0));
- gen_op_exit_tb();
+ tcg_gen_exit_tb(0);
break;
case DISAS_TB_JUMP:
/* nothing more to generate */
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, dc->pc - pc_start, 0);
fprintf(logfile, "\n");
- if (loglevel & (CPU_LOG_TB_OP)) {
- fprintf(logfile, "OP:\n");
- dump_ops(gen_opc_buf, gen_opparam_buf);
- fprintf(logfile, "\n");
- }
}
#endif
if (search_pc) {
lj++;
while (lj <= j)
gen_opc_instr_start[lj++] = 0;
- tb->size = 0;
} else {
tb->size = dc->pc - pc_start;
}
return gen_intermediate_code_internal(env, tb, 1);
}
-void cpu_reset(CPUM68KState *env)
-{
- memset(env, 0, offsetof(CPUM68KState, breakpoints));
-#if !defined (CONFIG_USER_ONLY)
- env->sr = 0x2700;
-#endif
- /* ??? FP regs should be initialized to NaN. */
- env->cc_op = CC_OP_FLAGS;
- /* TODO: We should set PC from the interrupt vector. */
- env->pc = 0;
- tlb_flush(env, 1);
-}
-
-CPUM68KState *cpu_m68k_init(void)
-{
- CPUM68KState *env;
-
- env = malloc(sizeof(CPUM68KState));
- if (!env)
- return NULL;
- cpu_exec_init(env);
-
- cpu_reset(env);
- return env;
-}
-
-void cpu_m68k_close(CPUM68KState *env)
-{
- free(env);
-}
-
-void cpu_dump_state(CPUState *env, FILE *f,
+void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags)
{
u.d = env->fregs[i];
cpu_fprintf (f, "D%d = %08x A%d = %08x F%d = %08x%08x (%12g)\n",
i, env->dregs[i], i, env->aregs[i],
- i, u.l.upper, u.l.lower, u.d);
+ i, u.l.upper, u.l.lower, *(double *)&u.d);
}
cpu_fprintf (f, "PC = %08x ", env->pc);
sr = env->sr;
cpu_fprintf (f, "SR = %04x %c%c%c%c%c ", sr, (sr & 0x10) ? 'X' : '-',
(sr & CCF_N) ? 'N' : '-', (sr & CCF_Z) ? 'Z' : '-',
(sr & CCF_V) ? 'V' : '-', (sr & CCF_C) ? 'C' : '-');
- cpu_fprintf (f, "FPRESULT = %12g\n", env->fp_result);
+ cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}