#include "cpu.h"
#include "disas/disas.h"
#include "tcg-op.h"
-#include "helper.h"
+#include "exec/helper-proto.h"
#include "microblaze-decode.h"
+#include "exec/cpu_ldst.h"
+#include "exec/helper-gen.h"
+
+#include "trace-tcg.h"
-#define GEN_HELPER 1
-#include "helper.h"
#define SIM_COMPAT 0
#define DISAS_GNU 1
/* This is the state at translation time. */
typedef struct DisasContext {
- CPUMBState *env;
+ MicroBlazeCPU *cpu;
target_ulong pc;
/* Decoder. */
"sr16", "sr17", "sr18"
};
-/* Sign extend at translation time. */
-static inline int sign_extend(unsigned int val, unsigned int width)
-{
- int sval;
-
- /* LSL. */
- val <<= 31 - width;
- sval = val;
- /* ASR. */
- sval >>= 31 - width;
- return sval;
-}
-
static inline void t_sync_flags(DisasContext *dc)
{
/* Synch the tb dependent flags between translator and runtime. */
static void dec_pattern(DisasContext *dc)
{
unsigned int mode;
- int l1;
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
}
case 2:
LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
if (dc->rd) {
- TCGv t0 = tcg_temp_local_new();
- l1 = gen_new_label();
- tcg_gen_movi_tl(t0, 1);
- tcg_gen_brcond_tl(TCG_COND_EQ,
- cpu_R[dc->ra], cpu_R[dc->rb], l1);
- tcg_gen_movi_tl(t0, 0);
- gen_set_label(l1);
- tcg_gen_mov_tl(cpu_R[dc->rd], t0);
- tcg_temp_free(t0);
+ tcg_gen_setcond_tl(TCG_COND_EQ, cpu_R[dc->rd],
+ cpu_R[dc->ra], cpu_R[dc->rb]);
}
break;
case 3:
LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
- l1 = gen_new_label();
if (dc->rd) {
- TCGv t0 = tcg_temp_local_new();
- tcg_gen_movi_tl(t0, 1);
- tcg_gen_brcond_tl(TCG_COND_NE,
- cpu_R[dc->ra], cpu_R[dc->rb], l1);
- tcg_gen_movi_tl(t0, 0);
- gen_set_label(l1);
- tcg_gen_mov_tl(cpu_R[dc->rd], t0);
- tcg_temp_free(t0);
+ tcg_gen_setcond_tl(TCG_COND_NE, cpu_R[dc->rd],
+ cpu_R[dc->ra], cpu_R[dc->rb]);
}
break;
default:
- cpu_abort(dc->env,
+ cpu_abort(CPU(dc->cpu),
"unsupported pattern insn opcode=%x\n", dc->opcode);
break;
}
static void dec_msr(DisasContext *dc)
{
+ CPUState *cs = CPU(dc->cpu);
TCGv t0, t1;
unsigned int sr, to, rn;
- int mem_index = cpu_mmu_index(dc->env);
+ int mem_index = cpu_mmu_index(&dc->cpu->env, false);
sr = dc->imm & ((1 << 14) - 1);
to = dc->imm & (1 << 14);
LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
dc->rd, dc->imm);
- if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
+ if (!(dc->cpu->env.pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
/* nop??? */
return;
}
tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr));
break;
default:
- cpu_abort(dc->env, "unknown mts reg %x\n", sr);
+ cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr);
break;
}
} else {
cpu_env, offsetof(CPUMBState, pvr.regs[rn]));
break;
default:
- cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
+ cpu_abort(cs, "unknown mfs reg %x\n", sr);
break;
}
}
tcg_gen_ext_i32_i64(t1, b);
tcg_gen_mul_i64(t0, t0, t1);
- tcg_gen_trunc_i64_i32(d, t0);
+ tcg_gen_extrl_i64_i32(d, t0);
tcg_gen_shri_i64(t0, t0, 32);
- tcg_gen_trunc_i64_i32(d2, t0);
+ tcg_gen_extrl_i64_i32(d2, t0);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
tcg_gen_extu_i32_i64(t1, b);
tcg_gen_mul_i64(t0, t0, t1);
- tcg_gen_trunc_i64_i32(d, t0);
+ tcg_gen_extrl_i64_i32(d, t0);
tcg_gen_shri_i64(t0, t0, 32);
- tcg_gen_trunc_i64_i32(d2, t0);
+ tcg_gen_extrl_i64_i32(d2, t0);
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
unsigned int subcode;
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !(dc->cpu->env.pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
/* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
if (subcode >= 1 && subcode <= 3
- && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
+ && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
/* nop??? */
}
t_gen_mulu(d[0], cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
break;
default:
- cpu_abort(dc->env, "unknown MUL insn %x\n", subcode);
+ cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode);
break;
}
done:
u = dc->imm & 2;
LOG_DIS("div\n");
- if ((dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
+ if ((dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->cpu->env.pvr.regs[0] & PVR0_USE_DIV_MASK))) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
}
unsigned int s, t;
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !(dc->cpu->env.pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
static void dec_bit(DisasContext *dc)
{
+ CPUState *cs = CPU(dc->cpu);
TCGv t0;
unsigned int op;
- int mem_index = cpu_mmu_index(dc->env);
+ int mem_index = cpu_mmu_index(&dc->cpu->env, false);
op = dc->ir & ((1 << 9) - 1);
switch (op) {
break;
case 0xe0:
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
}
- if (dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR) {
+ if (dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR) {
gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
}
break;
tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
break;
default:
- cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
- dc->pc, op, dc->rd, dc->ra, dc->rb);
+ cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
+ dc->pc, op, dc->rd, dc->ra, dc->rb);
break;
}
}
dc->clear_imm = 0;
}
-static inline void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
- unsigned int size, bool exclusive)
-{
- int mem_index = cpu_mmu_index(dc->env);
-
- if (size == 1) {
- tcg_gen_qemu_ld8u(dst, addr, mem_index);
- } else if (size == 2) {
- tcg_gen_qemu_ld16u(dst, addr, mem_index);
- } else if (size == 4) {
- tcg_gen_qemu_ld32u(dst, addr, mem_index);
- } else
- cpu_abort(dc->env, "Incorrect load size %d\n", size);
-
- if (exclusive) {
- tcg_gen_mov_tl(env_res_addr, addr);
- tcg_gen_mov_tl(env_res_val, dst);
- }
-}
-
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
{
unsigned int extimm = dc->tb_flags & IMM_FLAG;
int stackprot = 0;
/* All load/stores use ra. */
- if (dc->ra == 1) {
+ if (dc->ra == 1 && dc->cpu->cfg.stackprot) {
stackprot = 1;
}
return &cpu_R[dc->ra];
}
- if (dc->rb == 1) {
+ if (dc->rb == 1 && dc->cpu->cfg.stackprot) {
stackprot = 1;
}
return t;
}
-static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
-{
- if (size == 4) {
- tcg_gen_bswap32_tl(dst, src);
- } else if (size == 2) {
- TCGv t = tcg_temp_new();
-
- /* bswap16 assumes the high bits are zero. */
- tcg_gen_andi_tl(t, src, 0xffff);
- tcg_gen_bswap16_tl(dst, t);
- tcg_temp_free(t);
- } else {
- /* Ignore.
- cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
- */
- }
-}
-
static void dec_load(DisasContext *dc)
{
- TCGv t, *addr;
+ TCGv t, v, *addr;
unsigned int size, rev = 0, ex = 0;
+ TCGMemOp mop;
- size = 1 << (dc->opcode & 3);
-
+ mop = dc->opcode & 3;
+ size = 1 << mop;
if (!dc->type_b) {
rev = (dc->ir >> 9) & 1;
ex = (dc->ir >> 10) & 1;
}
+ mop |= MO_TE;
+ if (rev) {
+ mop ^= MO_BSWAP;
+ }
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
}
break;
default:
- cpu_abort(dc->env, "Invalid reverse size\n");
+ cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
break;
}
}
sync_jmpstate(dc);
/* Verify alignment if needed. */
- if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
- TCGv v = tcg_temp_new();
-
- /*
- * Microblaze gives MMU faults priority over faults due to
- * unaligned addresses. That's why we speculatively do the load
- * into v. If the load succeeds, we verify alignment of the
- * address and if that succeeds we write into the destination reg.
- */
- gen_load(dc, v, *addr, size, ex);
+ /*
+ * Microblaze gives MMU faults priority over faults due to
+ * unaligned addresses. That's why we speculatively do the load
+ * into v. If the load succeeds, we verify alignment of the
+ * address and if that succeeds we write into the destination reg.
+ */
+ v = tcg_temp_new();
+ tcg_gen_qemu_ld_tl(v, *addr, cpu_mmu_index(&dc->cpu->env, false), mop);
+ if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
tcg_const_tl(0), tcg_const_tl(size - 1));
- if (dc->rd) {
- if (rev) {
- dec_byteswap(dc, cpu_R[dc->rd], v, size);
- } else {
- tcg_gen_mov_tl(cpu_R[dc->rd], v);
- }
- }
- tcg_temp_free(v);
- } else {
- if (dc->rd) {
- gen_load(dc, cpu_R[dc->rd], *addr, size, ex);
- if (rev) {
- dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
- }
- } else {
- /* We are loading into r0, no need to reverse. */
- gen_load(dc, env_imm, *addr, size, ex);
- }
}
+ if (ex) {
+ tcg_gen_mov_tl(env_res_addr, *addr);
+ tcg_gen_mov_tl(env_res_val, v);
+ }
+ if (dc->rd) {
+ tcg_gen_mov_tl(cpu_R[dc->rd], v);
+ }
+ tcg_temp_free(v);
+
if (ex) { /* lwx */
- /* no support for for AXI exclusive so always clear C */
+ /* no support for AXI exclusive so always clear C */
write_carryi(dc, 0);
}
tcg_temp_free(t);
}
-static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
- unsigned int size)
-{
- int mem_index = cpu_mmu_index(dc->env);
-
- if (size == 1)
- tcg_gen_qemu_st8(val, addr, mem_index);
- else if (size == 2) {
- tcg_gen_qemu_st16(val, addr, mem_index);
- } else if (size == 4) {
- tcg_gen_qemu_st32(val, addr, mem_index);
- } else
- cpu_abort(dc->env, "Incorrect store size %d\n", size);
-}
-
static void dec_store(DisasContext *dc)
{
TCGv t, *addr, swx_addr;
- int swx_skip = 0;
+ TCGLabel *swx_skip = NULL;
unsigned int size, rev = 0, ex = 0;
+ TCGMemOp mop;
- size = 1 << (dc->opcode & 3);
+ mop = dc->opcode & 3;
+ size = 1 << mop;
if (!dc->type_b) {
rev = (dc->ir >> 9) & 1;
ex = (dc->ir >> 10) & 1;
}
+ mop |= MO_TE;
+ if (rev) {
+ mop ^= MO_BSWAP;
+ }
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
this compare and the following write to be atomic. For user
emulation we need to add atomicity between threads. */
tval = tcg_temp_new();
- gen_load(dc, tval, swx_addr, 4, false);
+ tcg_gen_qemu_ld_tl(tval, swx_addr, cpu_mmu_index(&dc->cpu->env, false),
+ MO_TEUL);
tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip);
write_carryi(dc, 0);
tcg_temp_free(tval);
}
break;
default:
- cpu_abort(dc->env, "Invalid reverse size\n");
+ cpu_abort(CPU(dc->cpu), "Invalid reverse size\n");
break;
}
-
- if (size != 1) {
- TCGv bs_data = tcg_temp_new();
- dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
- gen_store(dc, *addr, bs_data, size);
- tcg_temp_free(bs_data);
- } else {
- gen_store(dc, *addr, cpu_R[dc->rd], size);
- }
- } else {
- if (rev) {
- TCGv bs_data = tcg_temp_new();
- dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
- gen_store(dc, *addr, bs_data, size);
- tcg_temp_free(bs_data);
- } else {
- gen_store(dc, *addr, cpu_R[dc->rd], size);
- }
}
+ tcg_gen_qemu_st_tl(cpu_R[dc->rd], *addr, cpu_mmu_index(&dc->cpu->env, false), mop);
/* Verify alignment if needed. */
- if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
+ if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
/* FIXME: if the alignment is wrong, we should restore the value
* in memory. One possible way to achieve this is to probe
tcg_gen_setcond_tl(TCG_COND_GT, d, a, b);
break;
default:
- cpu_abort(dc->env, "Unknown condition code %x.\n", cc);
+ cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc);
break;
}
}
static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false)
{
- int l1;
-
- l1 = gen_new_label();
+ TCGLabel *l1 = gen_new_label();
/* Conditional jmp. */
tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false);
tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
static void dec_br(DisasContext *dc)
{
unsigned int dslot, link, abs, mbar;
- int mem_index = cpu_mmu_index(dc->env);
+ int mem_index = cpu_mmu_index(&dc->cpu->env, false);
dslot = dc->ir & (1 << 20);
abs = dc->ir & (1 << 19);
static void dec_rts(DisasContext *dc)
{
unsigned int b_bit, i_bit, e_bit;
- int mem_index = cpu_mmu_index(dc->env);
+ int mem_index = cpu_mmu_index(&dc->cpu->env, false);
i_bit = dc->ir & (1 << 21);
b_bit = dc->ir & (1 << 22);
static int dec_check_fpuv2(DisasContext *dc)
{
- int r;
-
- r = dc->env->pvr.regs[2] & PVR2_USE_FPU2_MASK;
-
- if (!r && (dc->tb_flags & MSR_EE_FLAG)) {
+ if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
}
- return r;
+ return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK;
}
static void dec_fpu(DisasContext *dc)
unsigned int fpu_insn;
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && (dc->cpu->cfg.use_fpu != 1)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
static void dec_null(DisasContext *dc)
{
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
}
- qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
+ qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
dc->abort_at_next_insn = 1;
}
/* Insns connected to FSL or AXI stream attached devices. */
static void dec_stream(DisasContext *dc)
{
- int mem_index = cpu_mmu_index(dc->env);
+ int mem_index = cpu_mmu_index(&dc->cpu->env, false);
TCGv_i32 t_id, t_ctrl;
int ctrl;
{
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
dc->nr_nops = 0;
else {
if ((dc->tb_flags & MSR_EE_FLAG)
- && (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
- && (dc->env->pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
+ && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && (dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
return;
LOG_DIS("nr_nops=%d\t", dc->nr_nops);
dc->nr_nops++;
- if (dc->nr_nops > 4)
- cpu_abort(dc->env, "fetching nop sequence\n");
+ if (dc->nr_nops > 4) {
+ cpu_abort(CPU(dc->cpu), "fetching nop sequence\n");
+ }
}
/* bit 2 seems to indicate insn type. */
dc->type_b = ir & (1 << 29);
}
}
-static void check_breakpoint(CPUMBState *env, DisasContext *dc)
-{
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- t_gen_raise_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
{
+ MicroBlazeCPU *cpu = mb_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUMBState *env = &cpu->env;
- uint16_t *gen_opc_end;
uint32_t pc_start;
- int j, lj;
struct DisasContext ctx;
struct DisasContext *dc = &ctx;
uint32_t next_page_start, org_flags;
int max_insns;
pc_start = tb->pc;
- dc->env = env;
+ dc->cpu = cpu;
dc->tb = tb;
org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
- gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
-
dc->is_jmp = DISAS_NEXT;
dc->jmp = 0;
dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
dc->abort_at_next_insn = 0;
dc->nr_nops = 0;
- if (pc_start & 3)
- cpu_abort(env, "Microblaze: unaligned PC=%x\n", pc_start);
+ if (pc_start & 3) {
+ cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start);
+ }
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
#if !SIM_COMPAT
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
- gen_tb_start();
+ gen_tb_start(tb);
do
{
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
#if SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_debug();
}
#endif
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ t_gen_raise_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ /* The address covered by the breakpoint must be included in
+ [tb->pc, tb->pc + tb->size) in order to for it to be
+ properly cleared -- thus we increment the PC here so that
+ the logic setting tb->size below does the right thing. */
+ dc->pc += 4;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
dc->clear_imm = 1;
decode(dc, cpu_ldl_code(env, dc->pc));
if (dc->clear_imm)
dc->tb_flags &= ~IMM_FLAG;
dc->pc += 4;
- num_insns++;
if (dc->delayed_branch) {
dc->delayed_branch--;
gen_goto_tb(dc, 0, dc->jmp_pc);
dc->is_jmp = DISAS_TB_JUMP;
} else if (dc->jmp == JMP_DIRECT_CC) {
- int l1;
-
+ TCGLabel *l1 = gen_new_label();
t_sync_flags(dc);
- l1 = gen_new_label();
/* Conditional jmp. */
tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
gen_goto_tb(dc, 1, dc->pc);
break;
}
} while (!dc->is_jmp && !dc->cpustate_changed
- && tcg_ctx.gen_opc_ptr < gen_opc_end
- && !singlestep
- && (dc->pc < next_page_start)
- && num_insns < max_insns);
+ && !tcg_op_buf_full()
+ && !singlestep
+ && (dc->pc < next_page_start)
+ && num_insns < max_insns);
npc = dc->pc;
if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
}
}
gen_tb_end(tb, num_insns);
- *tcg_ctx.gen_opc_ptr = INDEX_op_end;
- if (search_pc) {
- j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n");
#if DISAS_GNU
- log_target_disas(env, pc_start, dc->pc - pc_start, 0);
+ log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
#endif
- qemu_log("\nisize=%d osize=%td\n",
- dc->pc - pc_start, tcg_ctx.gen_opc_ptr -
- tcg_ctx.gen_opc_buf);
+ qemu_log("\nisize=%d osize=%d\n",
+ dc->pc - pc_start, tcg_op_buf_count());
}
#endif
#endif
assert(!dc->abort_at_next_insn);
}
-void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true);
-}
-
void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
}
}
-void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
+ env->sregs[SR_PC] = data[0];
}