* Xilinx MicroBlaze emulation for qemu: main translation routines.
*
* Copyright (c) 2009 Edgar E. Iglesias.
+ * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <assert.h>
-
#include "cpu.h"
#include "disas.h"
#include "tcg-op.h"
#include "helper.h"
#include "microblaze-decode.h"
-#include "qemu-common.h"
#define GEN_HELPER 1
#include "helper.h"
/* This is the state at translation time. */
typedef struct DisasContext {
- CPUState *env;
+ CPUMBState *env;
target_ulong pc;
/* Decoder. */
static inline void t_sync_flags(DisasContext *dc)
{
- /* Synch the tb dependant flags between translator and runtime. */
+ /* Synch the tb dependent flags between translator and runtime. */
if (dc->tb_flags != dc->synced_flags) {
tcg_gen_movi_tl(env_iflags, dc->tb_flags);
dc->synced_flags = dc->tb_flags;
t_sync_flags(dc);
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
dc->is_jmp = DISAS_UPDATE;
}
tcg_temp_free(t0);
}
+static void write_carryi(DisasContext *dc, int carry)
+{
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_movi_tl(t0, carry ? 1 : 0);
+ write_carry(dc, t0);
+ tcg_temp_free(t0);
+}
+
/* True if ALU operand b is a small immediate that may deserve
faster treatment. */
static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
sr &= 7;
LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm);
if (to)
- gen_helper_mmu_write(tcg_const_tl(sr), cpu_R[dc->ra]);
+ gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]);
else
- gen_helper_mmu_read(cpu_R[dc->rd], tcg_const_tl(sr));
+ gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr));
return;
}
#endif
case 0x7:
tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31);
break;
+ case 0x800:
+ tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr));
+ break;
+ case 0x802:
+ 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);
break;
case 0xb:
tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]);
break;
+ case 0x800:
+ tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr));
+ break;
+ case 0x802:
+ tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr));
+ break;
case 0x2000:
case 0x2001:
case 0x2002:
case 0x200c:
rn = sr & 0xf;
tcg_gen_ld_tl(cpu_R[dc->rd],
- cpu_env, offsetof(CPUState, pvr.regs[rn]));
+ cpu_env, offsetof(CPUMBState, pvr.regs[rn]));
break;
default:
cpu_abort(dc->env, "unknown mfs reg %x\n", sr);
}
if (u)
- gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+ gen_helper_divu(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
+ cpu_R[dc->ra]);
else
- gen_helper_divs(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+ gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)),
+ cpu_R[dc->ra]);
if (!dc->rd)
tcg_gen_movi_tl(cpu_R[dc->rd], 0);
}
unsigned int op;
int mem_index = cpu_mmu_index(dc->env);
- op = dc->ir & ((1 << 8) - 1);
+ op = dc->ir & ((1 << 9) - 1);
switch (op) {
case 0x21:
/* src. */
return;
}
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))) {
+ 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) {
+ gen_helper_clz(cpu_R[dc->rd], cpu_R[dc->ra]);
+ }
+ break;
+ case 0x1e0:
+ /* swapb */
+ LOG_DIS("swapb r%d r%d\n", dc->rd, dc->ra);
+ tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
+ break;
+ case 0x1e2:
+ /*swaph */
+ LOG_DIS("swaph r%d r%d\n", dc->rd, dc->ra);
+ 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);
static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
{
unsigned int extimm = dc->tb_flags & IMM_FLAG;
+ /* Should be set to one if r1 is used by loadstores. */
+ int stackprot = 0;
+
+ /* All load/stores use ra. */
+ if (dc->ra == 1) {
+ stackprot = 1;
+ }
/* Treat the common cases first. */
if (!dc->type_b) {
return &cpu_R[dc->ra];
}
+ if (dc->rb == 1) {
+ stackprot = 1;
+ }
+
*t = tcg_temp_new();
tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]);
+
+ if (stackprot) {
+ gen_helper_stackprot(cpu_env, *t);
+ }
return t;
}
/* Immediate. */
tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
}
+ if (stackprot) {
+ gen_helper_stackprot(cpu_env, *t);
+ }
return t;
}
static void dec_load(DisasContext *dc)
{
TCGv t, *addr;
- unsigned int size, rev = 0;
+ unsigned int size, rev = 0, ex = 0;
size = 1 << (dc->opcode & 3);
if (!dc->type_b) {
rev = (dc->ir >> 9) & 1;
+ ex = (dc->ir >> 10) & 1;
}
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
return;
}
- LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+ LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
+ ex ? "x" : "");
t_sync_flags(dc);
addr = compute_ldst_addr(dc, &t);
}
}
+ /* lwx does not throw unaligned access errors, so force alignment */
+ if (ex) {
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_mov_tl(t, *addr);
+ addr = &t;
+ }
+ tcg_gen_andi_tl(t, t, ~3);
+ }
+
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
gen_load(dc, v, *addr, size);
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
- gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
+ 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) {
}
}
+ if (ex) { /* lwx */
+ /* no support for for AXI exclusive so always clear C */
+ write_carryi(dc, 0);
+ tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr));
+ }
+
if (addr == &t)
tcg_temp_free(t);
}
static void dec_store(DisasContext *dc)
{
- TCGv t, *addr;
- unsigned int size, rev = 0;
+ TCGv t, *addr, swx_addr, r_check;
+ int swx_skip = 0;
+ unsigned int size, rev = 0, ex = 0;
size = 1 << (dc->opcode & 3);
if (!dc->type_b) {
rev = (dc->ir >> 9) & 1;
+ ex = (dc->ir >> 10) & 1;
}
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
return;
}
- LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+ LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "",
+ ex ? "x" : "");
t_sync_flags(dc);
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
addr = compute_ldst_addr(dc, &t);
+ r_check = tcg_temp_new();
+ swx_addr = tcg_temp_local_new();
+ if (ex) { /* swx */
+
+ /* Force addr into the swx_addr. */
+ tcg_gen_mov_tl(swx_addr, *addr);
+ addr = &swx_addr;
+ /* swx does not throw unaligned access errors, so force alignment */
+ tcg_gen_andi_tl(swx_addr, swx_addr, ~3);
+
+ tcg_gen_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr));
+ write_carryi(dc, 1);
+ swx_skip = gen_new_label();
+ tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip);
+ write_carryi(dc, 0);
+ }
+
if (rev && size != 4) {
/* Endian reverse the address. t is addr. */
switch (size) {
if ((dc->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 acheive this is to probe
+ * in memory. One possible way to achieve this is to probe
* the MMU prior to the memaccess, thay way we could put
* the alignment checks in between the probe and the mem
* access.
*/
- gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
+ gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd),
tcg_const_tl(1), tcg_const_tl(size - 1));
}
+ if (ex) {
+ gen_set_label(swx_skip);
+ }
+ tcg_temp_free(r_check);
+ tcg_temp_free(swx_addr);
+
if (addr == &t)
tcg_temp_free(t);
}
dc->delayed_branch = 2;
dc->tb_flags |= D_FLAG;
tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
- cpu_env, offsetof(CPUState, bimm));
+ cpu_env, offsetof(CPUMBState, bimm));
}
if (dec_alu_op_b_is_small_imm(dc)) {
static void dec_br(DisasContext *dc)
{
- unsigned int dslot, link, abs;
+ unsigned int dslot, link, abs, mbar;
int mem_index = cpu_mmu_index(dc->env);
dslot = dc->ir & (1 << 20);
abs = dc->ir & (1 << 19);
link = dc->ir & (1 << 18);
+
+ /* Memory barrier. */
+ mbar = (dc->ir >> 16) & 31;
+ if (mbar == 2 && dc->imm == 4) {
+ LOG_DIS("mbar %d\n", dc->rd);
+ /* Break the TB. */
+ dc->cpustate_changed = 1;
+ return;
+ }
+
LOG_DIS("br%s%s%s%s imm=%x\n",
abs ? "a" : "", link ? "l" : "",
dc->type_b ? "i" : "", dslot ? "d" : "",
dc->delayed_branch = 2;
dc->tb_flags |= D_FLAG;
tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
- cpu_env, offsetof(CPUState, bimm));
+ cpu_env, offsetof(CPUMBState, bimm));
}
if (link && dc->rd)
tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc);
dc->delayed_branch = 2;
dc->tb_flags |= D_FLAG;
tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)),
- cpu_env, offsetof(CPUState, bimm));
+ cpu_env, offsetof(CPUMBState, bimm));
if (i_bit) {
LOG_DIS("rtid ir=%x\n", dc->ir);
switch (fpu_insn) {
case 0:
- gen_helper_fadd(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fadd(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 1:
- gen_helper_frsub(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_frsub(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 2:
- gen_helper_fmul(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fmul(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 3:
- gen_helper_fdiv(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
+ gen_helper_fdiv(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra],
+ cpu_R[dc->rb]);
break;
case 4:
switch ((dc->ir >> 4) & 7) {
case 0:
- gen_helper_fcmp_un(cpu_R[dc->rd],
+ gen_helper_fcmp_un(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 1:
- gen_helper_fcmp_lt(cpu_R[dc->rd],
+ gen_helper_fcmp_lt(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 2:
- gen_helper_fcmp_eq(cpu_R[dc->rd],
+ gen_helper_fcmp_eq(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 3:
- gen_helper_fcmp_le(cpu_R[dc->rd],
+ gen_helper_fcmp_le(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 4:
- gen_helper_fcmp_gt(cpu_R[dc->rd],
+ gen_helper_fcmp_gt(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 5:
- gen_helper_fcmp_ne(cpu_R[dc->rd],
+ gen_helper_fcmp_ne(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
case 6:
- gen_helper_fcmp_ge(cpu_R[dc->rd],
+ gen_helper_fcmp_ge(cpu_R[dc->rd], cpu_env,
cpu_R[dc->ra], cpu_R[dc->rb]);
break;
default:
- qemu_log ("unimplemented fcmp fpu_insn=%x pc=%x opc=%x\n",
- fpu_insn, dc->pc, dc->opcode);
+ qemu_log_mask(LOG_UNIMP,
+ "unimplemented fcmp fpu_insn=%x pc=%x"
+ " opc=%x\n",
+ fpu_insn, dc->pc, dc->opcode);
dc->abort_at_next_insn = 1;
break;
}
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_flt(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_flt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
case 6:
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_fint(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_fint(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
case 7:
if (!dec_check_fpuv2(dc)) {
return;
}
- gen_helper_fsqrt(cpu_R[dc->rd], cpu_R[dc->ra]);
+ gen_helper_fsqrt(cpu_R[dc->rd], cpu_env, cpu_R[dc->ra]);
break;
default:
- qemu_log ("unimplemented FPU insn fpu_insn=%x pc=%x opc=%x\n",
- fpu_insn, dc->pc, dc->opcode);
+ qemu_log_mask(LOG_UNIMP, "unimplemented FPU insn fpu_insn=%x pc=%x"
+ " opc=%x\n",
+ fpu_insn, dc->pc, dc->opcode);
dc->abort_at_next_insn = 1;
break;
}
{{0, 0}, dec_null}
};
-static inline void decode(DisasContext *dc)
+static inline void decode(DisasContext *dc, uint32_t ir)
{
- uint32_t ir;
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
tcg_gen_debug_insn_start(dc->pc);
+ }
- dc->ir = ir = ldl_code(dc->pc);
+ dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
if (dc->ir)
}
}
-static void check_breakpoint(CPUState *env, DisasContext *dc)
+static void check_breakpoint(CPUMBState *env, DisasContext *dc)
{
CPUBreakpoint *bp;
/* generate intermediate code for basic block 'tb'. */
static void
-gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
+gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb,
int search_pc)
{
uint16_t *gen_opc_end;
dc->tb = tb;
org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
- gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
+ gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT;
dc->jmp = 0;
check_breakpoint(env, dc);
if (search_pc) {
- j = gen_opc_ptr - gen_opc_buf;
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
if (lj < j) {
lj++;
while (lj < j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
- gen_opc_pc[lj] = dc->pc;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
+ tcg_ctx.gen_opc_pc[lj] = dc->pc;
+ tcg_ctx.gen_opc_instr_start[lj] = 1;
+ tcg_ctx.gen_opc_icount[lj] = num_insns;
}
/* Pretty disas. */
gen_io_start();
dc->clear_imm = 1;
- decode(dc);
+ decode(dc, cpu_ldl_code(env, dc->pc));
if (dc->clear_imm)
dc->tb_flags &= ~IMM_FLAG;
dc->pc += 4;
if (env->singlestep_enabled)
break;
} while (!dc->is_jmp && !dc->cpustate_changed
- && gen_opc_ptr < gen_opc_end
+ && tcg_ctx.gen_opc_ptr < gen_opc_end
&& !singlestep
&& (dc->pc < next_page_start)
&& num_insns < max_insns);
if (dc->is_jmp != DISAS_JUMP) {
tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
}
- gen_helper_raise_exception(tmp);
+ gen_helper_raise_exception(cpu_env, tmp);
tcg_temp_free_i32(tmp);
} else {
switch(dc->is_jmp) {
}
}
gen_icount_end(tb, num_insns);
- *gen_opc_ptr = INDEX_op_end;
+ *tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) {
- j = gen_opc_ptr - gen_opc_buf;
+ j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
lj++;
while (lj <= j)
- gen_opc_instr_start[lj++] = 0;
+ tcg_ctx.gen_opc_instr_start[lj++] = 0;
} else {
tb->size = dc->pc - pc_start;
tb->icount = num_insns;
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n");
#if DISAS_GNU
- log_target_disas(pc_start, dc->pc - pc_start, 0);
+ log_target_disas(env, pc_start, dc->pc - pc_start, 0);
#endif
qemu_log("\nisize=%d osize=%td\n",
- dc->pc - pc_start, gen_opc_ptr - gen_opc_buf);
+ dc->pc - pc_start, tcg_ctx.gen_opc_ptr -
+ tcg_ctx.gen_opc_buf);
}
#endif
#endif
assert(!dc->abort_at_next_insn);
}
-void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
{
gen_intermediate_code_internal(env, tb, 0);
}
-void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
+void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
{
gen_intermediate_code_internal(env, tb, 1);
}
-void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+void cpu_dump_state (CPUMBState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
int i;
cpu_fprintf(f, "\n\n");
}
-CPUState *cpu_mb_init (const char *cpu_model)
+MicroBlazeCPU *cpu_mb_init(const char *cpu_model)
{
- CPUState *env;
+ MicroBlazeCPU *cpu;
static int tcg_initialized = 0;
int i;
- env = g_malloc0(sizeof(CPUState));
+ cpu = MICROBLAZE_CPU(object_new(TYPE_MICROBLAZE_CPU));
- cpu_exec_init(env);
- cpu_reset(env);
- qemu_init_vcpu(env);
- set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+ cpu_reset(CPU(cpu));
+ qemu_init_vcpu(&cpu->env);
- if (tcg_initialized)
- return env;
+ if (tcg_initialized) {
+ return cpu;
+ }
tcg_initialized = 1;
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
env_debug = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, debug),
+ offsetof(CPUMBState, debug),
"debug0");
env_iflags = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, iflags),
+ offsetof(CPUMBState, iflags),
"iflags");
env_imm = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, imm),
+ offsetof(CPUMBState, imm),
"imm");
env_btarget = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, btarget),
+ offsetof(CPUMBState, btarget),
"btarget");
env_btaken = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, btaken),
+ offsetof(CPUMBState, btaken),
"btaken");
for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, regs[i]),
+ offsetof(CPUMBState, regs[i]),
regnames[i]);
}
for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) {
cpu_SR[i] = tcg_global_mem_new(TCG_AREG0,
- offsetof(CPUState, sregs[i]),
+ offsetof(CPUMBState, sregs[i]),
special_regnames[i]);
}
#define GEN_HELPER 2
#include "helper.h"
- return env;
-}
-
-void cpu_reset (CPUState *env)
-{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- memset(env, 0, offsetof(CPUMBState, breakpoints));
- tlb_flush(env, 1);
-
- env->pvr.regs[0] = PVR0_PVR_FULL_MASK \
- | PVR0_USE_BARREL_MASK \
- | PVR0_USE_DIV_MASK \
- | PVR0_USE_HW_MUL_MASK \
- | PVR0_USE_EXC_MASK \
- | PVR0_USE_ICACHE_MASK \
- | PVR0_USE_DCACHE_MASK \
- | PVR0_USE_MMU \
- | (0xb << 8);
- env->pvr.regs[2] = PVR2_D_OPB_MASK \
- | PVR2_D_LMB_MASK \
- | PVR2_I_OPB_MASK \
- | PVR2_I_LMB_MASK \
- | PVR2_USE_MSR_INSTR \
- | PVR2_USE_PCMP_INSTR \
- | PVR2_USE_BARREL_MASK \
- | PVR2_USE_DIV_MASK \
- | PVR2_USE_HW_MUL_MASK \
- | PVR2_USE_MUL64_MASK \
- | PVR2_USE_FPU_MASK \
- | PVR2_USE_FPU2_MASK \
- | PVR2_FPU_EXC_MASK \
- | 0;
- env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */
- env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17);
-
-#if defined(CONFIG_USER_ONLY)
- /* start in user mode with interrupts enabled. */
- env->sregs[SR_MSR] = MSR_EE | MSR_IE | MSR_VM | MSR_UM;
- env->pvr.regs[10] = 0x0c000000; /* Spartan 3a dsp. */
-#else
- env->sregs[SR_MSR] = 0;
- mmu_init(&env->mmu);
- env->mmu.c_mmu = 3;
- env->mmu.c_mmu_tlb_access = 3;
- env->mmu.c_mmu_zones = 16;
-#endif
+ return cpu;
}
-void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
{
- env->sregs[SR_PC] = gen_opc_pc[pc_pos];
+ env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
}