mirror of https://github.com/xemu-project/xemu.git
target/nios2: Split control registers away from general registers
Place the control registers into their own array, env->ctrl[]. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220421151735.31996-23-richard.henderson@linaro.org>
This commit is contained in:
parent
e237ac34db
commit
b8f036a9fa
|
@ -48,14 +48,15 @@ static void nios2_cpu_reset(DeviceState *dev)
|
|||
|
||||
ncc->parent_reset(dev);
|
||||
|
||||
memset(env->regs, 0, sizeof(uint32_t) * NUM_CORE_REGS);
|
||||
memset(env->regs, 0, sizeof(env->regs));
|
||||
memset(env->ctrl, 0, sizeof(env->ctrl));
|
||||
env->pc = cpu->reset_addr;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* Start in user mode with interrupts enabled. */
|
||||
env->regs[CR_STATUS] = CR_STATUS_U | CR_STATUS_PIE;
|
||||
env->ctrl[CR_STATUS] = CR_STATUS_U | CR_STATUS_PIE;
|
||||
#else
|
||||
env->regs[CR_STATUS] = 0;
|
||||
env->ctrl[CR_STATUS] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -66,9 +67,9 @@ static void nios2_cpu_set_irq(void *opaque, int irq, int level)
|
|||
CPUNios2State *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
env->regs[CR_IPENDING] = deposit32(env->regs[CR_IPENDING], irq, 1, !!level);
|
||||
env->ctrl[CR_IPENDING] = deposit32(env->ctrl[CR_IPENDING], irq, 1, !!level);
|
||||
|
||||
if (env->regs[CR_IPENDING]) {
|
||||
if (env->ctrl[CR_IPENDING]) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
|
@ -126,8 +127,8 @@ static bool nios2_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||
CPUNios2State *env = &cpu->env;
|
||||
|
||||
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
|
||||
(env->regs[CR_STATUS] & CR_STATUS_PIE) &&
|
||||
(env->regs[CR_IPENDING] & env->regs[CR_IENABLE])) {
|
||||
(env->ctrl[CR_STATUS] & CR_STATUS_PIE) &&
|
||||
(env->ctrl[CR_IPENDING] & env->ctrl[CR_IENABLE])) {
|
||||
cs->exception_index = EXCP_IRQ;
|
||||
nios2_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
|
@ -158,7 +159,7 @@ static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
|||
} else if (n == 32) { /* PC */
|
||||
return gdb_get_reg32(mem_buf, env->pc);
|
||||
} else if (n < 49) { /* Status regs */
|
||||
return gdb_get_reg32(mem_buf, env->regs[n - 1]);
|
||||
return gdb_get_reg32(mem_buf, env->ctrl[n - 33]);
|
||||
}
|
||||
|
||||
/* Invalid regs */
|
||||
|
@ -180,7 +181,7 @@ static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||
} else if (n == 32) { /* PC */
|
||||
env->pc = ldl_p(mem_buf);
|
||||
} else if (n < 49) { /* Status regs */
|
||||
env->regs[n - 1] = ldl_p(mem_buf);
|
||||
env->ctrl[n - 33] = ldl_p(mem_buf);
|
||||
}
|
||||
|
||||
return 4;
|
||||
|
|
|
@ -59,9 +59,6 @@ struct Nios2CPUClass {
|
|||
#define NUM_GP_REGS 32
|
||||
#define NUM_CR_REGS 32
|
||||
|
||||
/* GP regs + CR regs */
|
||||
#define NUM_CORE_REGS (NUM_GP_REGS + NUM_CR_REGS)
|
||||
|
||||
/* General purpose register aliases */
|
||||
#define R_ZERO 0
|
||||
#define R_AT 1
|
||||
|
@ -81,8 +78,7 @@ struct Nios2CPUClass {
|
|||
#define R_RA 31
|
||||
|
||||
/* Control register aliases */
|
||||
#define CR_BASE NUM_GP_REGS
|
||||
#define CR_STATUS (CR_BASE + 0)
|
||||
#define CR_STATUS 0
|
||||
#define CR_STATUS_PIE (1 << 0)
|
||||
#define CR_STATUS_U (1 << 1)
|
||||
#define CR_STATUS_EH (1 << 2)
|
||||
|
@ -92,19 +88,19 @@ struct Nios2CPUClass {
|
|||
#define CR_STATUS_PRS (63 << 16)
|
||||
#define CR_STATUS_NMI (1 << 22)
|
||||
#define CR_STATUS_RSIE (1 << 23)
|
||||
#define CR_ESTATUS (CR_BASE + 1)
|
||||
#define CR_BSTATUS (CR_BASE + 2)
|
||||
#define CR_IENABLE (CR_BASE + 3)
|
||||
#define CR_IPENDING (CR_BASE + 4)
|
||||
#define CR_CPUID (CR_BASE + 5)
|
||||
#define CR_CTL6 (CR_BASE + 6)
|
||||
#define CR_EXCEPTION (CR_BASE + 7)
|
||||
#define CR_PTEADDR (CR_BASE + 8)
|
||||
#define CR_ESTATUS 1
|
||||
#define CR_BSTATUS 2
|
||||
#define CR_IENABLE 3
|
||||
#define CR_IPENDING 4
|
||||
#define CR_CPUID 5
|
||||
#define CR_CTL6 6
|
||||
#define CR_EXCEPTION 7
|
||||
#define CR_PTEADDR 8
|
||||
#define CR_PTEADDR_PTBASE_SHIFT 22
|
||||
#define CR_PTEADDR_PTBASE_MASK (0x3FF << CR_PTEADDR_PTBASE_SHIFT)
|
||||
#define CR_PTEADDR_VPN_SHIFT 2
|
||||
#define CR_PTEADDR_VPN_MASK (0xFFFFF << CR_PTEADDR_VPN_SHIFT)
|
||||
#define CR_TLBACC (CR_BASE + 9)
|
||||
#define CR_TLBACC 9
|
||||
#define CR_TLBACC_IGN_SHIFT 25
|
||||
#define CR_TLBACC_IGN_MASK (0x7F << CR_TLBACC_IGN_SHIFT)
|
||||
#define CR_TLBACC_C (1 << 24)
|
||||
|
@ -113,7 +109,7 @@ struct Nios2CPUClass {
|
|||
#define CR_TLBACC_X (1 << 21)
|
||||
#define CR_TLBACC_G (1 << 20)
|
||||
#define CR_TLBACC_PFN_MASK 0x000FFFFF
|
||||
#define CR_TLBMISC (CR_BASE + 10)
|
||||
#define CR_TLBMISC 10
|
||||
#define CR_TLBMISC_WAY_SHIFT 20
|
||||
#define CR_TLBMISC_WAY_MASK (0xF << CR_TLBMISC_WAY_SHIFT)
|
||||
#define CR_TLBMISC_RD (1 << 19)
|
||||
|
@ -124,11 +120,11 @@ struct Nios2CPUClass {
|
|||
#define CR_TLBMISC_BAD (1 << 2)
|
||||
#define CR_TLBMISC_PERM (1 << 1)
|
||||
#define CR_TLBMISC_D (1 << 0)
|
||||
#define CR_ENCINJ (CR_BASE + 11)
|
||||
#define CR_BADADDR (CR_BASE + 12)
|
||||
#define CR_CONFIG (CR_BASE + 13)
|
||||
#define CR_MPUBASE (CR_BASE + 14)
|
||||
#define CR_MPUACC (CR_BASE + 15)
|
||||
#define CR_ENCINJ 11
|
||||
#define CR_BADADDR 12
|
||||
#define CR_CONFIG 13
|
||||
#define CR_MPUBASE 14
|
||||
#define CR_MPUACC 15
|
||||
|
||||
/* Exceptions */
|
||||
#define EXCP_BREAK 0x1000
|
||||
|
@ -154,7 +150,8 @@ struct Nios2CPUClass {
|
|||
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
|
||||
|
||||
struct CPUArchState {
|
||||
uint32_t regs[NUM_CORE_REGS];
|
||||
uint32_t regs[NUM_GP_REGS];
|
||||
uint32_t ctrl[NUM_CR_REGS];
|
||||
uint32_t pc;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
@ -212,7 +209,7 @@ void do_nios2_semihosting(CPUNios2State *env);
|
|||
|
||||
static inline int cpu_mmu_index(CPUNios2State *env, bool ifetch)
|
||||
{
|
||||
return (env->regs[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX :
|
||||
return (env->ctrl[CR_STATUS] & CR_STATUS_U) ? MMU_USER_IDX :
|
||||
MMU_SUPERVISOR_IDX;
|
||||
}
|
||||
|
||||
|
@ -232,7 +229,7 @@ static inline void cpu_get_tb_cpu_state(CPUNios2State *env, target_ulong *pc,
|
|||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = (env->regs[CR_STATUS] & (CR_STATUS_EH | CR_STATUS_U));
|
||||
*flags = env->ctrl[CR_STATUS] & (CR_STATUS_EH | CR_STATUS_U);
|
||||
}
|
||||
|
||||
#endif /* NIOS2_CPU_H */
|
||||
|
|
|
@ -36,38 +36,38 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_IRQ:
|
||||
assert(env->regs[CR_STATUS] & CR_STATUS_PIE);
|
||||
assert(env->ctrl[CR_STATUS] & CR_STATUS_PIE);
|
||||
|
||||
qemu_log_mask(CPU_LOG_INT, "interrupt at pc=%x\n", env->pc);
|
||||
|
||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
||||
env->regs[CR_STATUS] |= CR_STATUS_IH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_ESTATUS] = env->ctrl[CR_STATUS];
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_IH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->regs[R_EA] = env->pc + 4;
|
||||
env->pc = cpu->exception_addr;
|
||||
break;
|
||||
|
||||
case EXCP_TLBD:
|
||||
if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
if ((env->ctrl[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
qemu_log_mask(CPU_LOG_INT, "TLB MISS (fast) at pc=%x\n", env->pc);
|
||||
|
||||
/* Fast TLB miss */
|
||||
/* Variation from the spec. Table 3-35 of the cpu reference shows
|
||||
* estatus not being changed for TLB miss but this appears to
|
||||
* be incorrect. */
|
||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_ESTATUS] = env->ctrl[CR_STATUS];
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->regs[CR_TLBMISC] &= ~CR_TLBMISC_DBL;
|
||||
env->regs[CR_TLBMISC] |= CR_TLBMISC_WR;
|
||||
env->ctrl[CR_TLBMISC] &= ~CR_TLBMISC_DBL;
|
||||
env->ctrl[CR_TLBMISC] |= CR_TLBMISC_WR;
|
||||
|
||||
env->regs[R_EA] = env->pc + 4;
|
||||
env->pc = cpu->fast_tlb_miss_addr;
|
||||
|
@ -75,13 +75,13 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
qemu_log_mask(CPU_LOG_INT, "TLB MISS (double) at pc=%x\n", env->pc);
|
||||
|
||||
/* Double TLB miss */
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->regs[CR_TLBMISC] |= CR_TLBMISC_DBL;
|
||||
env->ctrl[CR_TLBMISC] |= CR_TLBMISC_DBL;
|
||||
|
||||
env->pc = cpu->exception_addr;
|
||||
}
|
||||
|
@ -92,15 +92,15 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
case EXCP_TLBX:
|
||||
qemu_log_mask(CPU_LOG_INT, "TLB PERM at pc=%x\n", env->pc);
|
||||
|
||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_ESTATUS] = env->ctrl[CR_STATUS];
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->regs[CR_TLBMISC] |= CR_TLBMISC_WR;
|
||||
if ((env->ctrl[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->ctrl[CR_TLBMISC] |= CR_TLBMISC_WR;
|
||||
}
|
||||
|
||||
env->regs[R_EA] = env->pc + 4;
|
||||
|
@ -112,16 +112,16 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
case EXCP_SUPERD:
|
||||
qemu_log_mask(CPU_LOG_INT, "SUPERVISOR exception at pc=%x\n", env->pc);
|
||||
|
||||
if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
||||
if ((env->ctrl[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->ctrl[CR_ESTATUS] = env->ctrl[CR_STATUS];
|
||||
env->regs[R_EA] = env->pc + 4;
|
||||
}
|
||||
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->pc = cpu->exception_addr;
|
||||
break;
|
||||
|
@ -130,16 +130,16 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
case EXCP_TRAP:
|
||||
qemu_log_mask(CPU_LOG_INT, "TRAP exception at pc=%x\n", env->pc);
|
||||
|
||||
if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
||||
if ((env->ctrl[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->ctrl[CR_ESTATUS] = env->ctrl[CR_STATUS];
|
||||
env->regs[R_EA] = env->pc + 4;
|
||||
}
|
||||
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->pc = cpu->exception_addr;
|
||||
break;
|
||||
|
@ -155,16 +155,16 @@ void nios2_cpu_do_interrupt(CPUState *cs)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((env->regs[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->regs[CR_BSTATUS] = env->regs[CR_STATUS];
|
||||
if ((env->ctrl[CR_STATUS] & CR_STATUS_EH) == 0) {
|
||||
env->ctrl[CR_BSTATUS] = env->ctrl[CR_STATUS];
|
||||
env->regs[R_BA] = env->pc + 4;
|
||||
}
|
||||
|
||||
env->regs[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->regs[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
env->ctrl[CR_STATUS] |= CR_STATUS_EH;
|
||||
env->ctrl[CR_STATUS] &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->regs[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->regs[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
env->ctrl[CR_EXCEPTION] &= ~(0x1F << 2);
|
||||
env->ctrl[CR_EXCEPTION] |= (cs->exception_index & 0x1F) << 2;
|
||||
|
||||
env->pc = cpu->exception_addr;
|
||||
break;
|
||||
|
@ -207,8 +207,8 @@ void nios2_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
|||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
|
||||
env->regs[CR_BADADDR] = addr;
|
||||
env->regs[CR_EXCEPTION] = EXCP_UNALIGN << 2;
|
||||
env->ctrl[CR_BADADDR] = addr;
|
||||
env->ctrl[CR_EXCEPTION] = EXCP_UNALIGN << 2;
|
||||
helper_raise_exception(env, EXCP_UNALIGN);
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
return false;
|
||||
}
|
||||
cs->exception_index = EXCP_SUPERA;
|
||||
env->regs[CR_BADADDR] = address;
|
||||
env->ctrl[CR_BADADDR] = address;
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
}
|
||||
|
@ -275,15 +275,15 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
}
|
||||
|
||||
if (access_type == MMU_INST_FETCH) {
|
||||
env->regs[CR_TLBMISC] &= ~CR_TLBMISC_D;
|
||||
env->ctrl[CR_TLBMISC] &= ~CR_TLBMISC_D;
|
||||
} else {
|
||||
env->regs[CR_TLBMISC] |= CR_TLBMISC_D;
|
||||
env->ctrl[CR_TLBMISC] |= CR_TLBMISC_D;
|
||||
}
|
||||
env->regs[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK;
|
||||
env->regs[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK;
|
||||
env->mmu.pteaddr_wr = env->regs[CR_PTEADDR];
|
||||
env->ctrl[CR_PTEADDR] &= CR_PTEADDR_PTBASE_MASK;
|
||||
env->ctrl[CR_PTEADDR] |= (address >> 10) & CR_PTEADDR_VPN_MASK;
|
||||
env->mmu.pteaddr_wr = env->ctrl[CR_PTEADDR];
|
||||
|
||||
cs->exception_index = excp;
|
||||
env->regs[CR_BADADDR] = address;
|
||||
env->ctrl[CR_BADADDR] = address;
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@ void helper_mmu_write_tlbacc(CPUNios2State *env, uint32_t v)
|
|||
v & CR_TLBACC_PFN_MASK);
|
||||
|
||||
/* if tlbmisc.WE == 1 then trigger a TLB write on writes to TLBACC */
|
||||
if (env->regs[CR_TLBMISC] & CR_TLBMISC_WR) {
|
||||
int way = (env->regs[CR_TLBMISC] >> CR_TLBMISC_WAY_SHIFT);
|
||||
if (env->ctrl[CR_TLBMISC] & CR_TLBMISC_WR) {
|
||||
int way = (env->ctrl[CR_TLBMISC] >> CR_TLBMISC_WAY_SHIFT);
|
||||
int vpn = (env->mmu.pteaddr_wr & CR_PTEADDR_VPN_MASK) >> 2;
|
||||
int pid = (env->mmu.tlbmisc_wr & CR_TLBMISC_PID_MASK) >> 4;
|
||||
int g = (v & CR_TLBACC_G) ? 1 : 0;
|
||||
|
@ -117,8 +117,8 @@ void helper_mmu_write_tlbacc(CPUNios2State *env, uint32_t v)
|
|||
entry->data = newData;
|
||||
}
|
||||
/* Auto-increment tlbmisc.WAY */
|
||||
env->regs[CR_TLBMISC] =
|
||||
(env->regs[CR_TLBMISC] & ~CR_TLBMISC_WAY_MASK) |
|
||||
env->ctrl[CR_TLBMISC] =
|
||||
(env->ctrl[CR_TLBMISC] & ~CR_TLBMISC_WAY_MASK) |
|
||||
(((way + 1) & (cpu->tlb_num_ways - 1)) <<
|
||||
CR_TLBMISC_WAY_SHIFT);
|
||||
}
|
||||
|
@ -153,17 +153,17 @@ void helper_mmu_write_tlbmisc(CPUNios2State *env, uint32_t v)
|
|||
&env->mmu.tlb[(way * cpu->tlb_num_ways) +
|
||||
(vpn & env->mmu.tlb_entry_mask)];
|
||||
|
||||
env->regs[CR_TLBACC] &= CR_TLBACC_IGN_MASK;
|
||||
env->regs[CR_TLBACC] |= entry->data;
|
||||
env->regs[CR_TLBACC] |= (entry->tag & (1 << 11)) ? CR_TLBACC_G : 0;
|
||||
env->regs[CR_TLBMISC] =
|
||||
env->ctrl[CR_TLBACC] &= CR_TLBACC_IGN_MASK;
|
||||
env->ctrl[CR_TLBACC] |= entry->data;
|
||||
env->ctrl[CR_TLBACC] |= (entry->tag & (1 << 11)) ? CR_TLBACC_G : 0;
|
||||
env->ctrl[CR_TLBMISC] =
|
||||
(v & ~CR_TLBMISC_PID_MASK) |
|
||||
((entry->tag & ((1 << cpu->pid_num_bits) - 1)) <<
|
||||
CR_TLBMISC_PID_SHIFT);
|
||||
env->regs[CR_PTEADDR] &= ~CR_PTEADDR_VPN_MASK;
|
||||
env->regs[CR_PTEADDR] |= (entry->tag >> 12) << CR_PTEADDR_VPN_SHIFT;
|
||||
env->ctrl[CR_PTEADDR] &= ~CR_PTEADDR_VPN_MASK;
|
||||
env->ctrl[CR_PTEADDR] |= (entry->tag >> 12) << CR_PTEADDR_VPN_SHIFT;
|
||||
} else {
|
||||
env->regs[CR_TLBMISC] = v;
|
||||
env->ctrl[CR_TLBMISC] = v;
|
||||
}
|
||||
|
||||
env->mmu.tlbmisc_wr = v;
|
||||
|
@ -175,8 +175,8 @@ void helper_mmu_write_pteaddr(CPUNios2State *env, uint32_t v)
|
|||
(v & CR_PTEADDR_VPN_MASK) >> CR_PTEADDR_VPN_SHIFT);
|
||||
|
||||
/* Writes to PTEADDR don't change the read-back VPN value */
|
||||
env->regs[CR_PTEADDR] = (v & ~CR_PTEADDR_VPN_MASK) |
|
||||
(env->regs[CR_PTEADDR] & CR_PTEADDR_VPN_MASK);
|
||||
env->ctrl[CR_PTEADDR] = ((v & ~CR_PTEADDR_VPN_MASK) |
|
||||
(env->ctrl[CR_PTEADDR] & CR_PTEADDR_VPN_MASK));
|
||||
env->mmu.pteaddr_wr = v;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ void helper_raise_exception(CPUNios2State *env, uint32_t index)
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
void helper_eret(CPUNios2State *env, uint32_t new_status, uint32_t new_pc)
|
||||
{
|
||||
env->regs[CR_STATUS] = new_status;
|
||||
env->ctrl[CR_STATUS] = new_status;
|
||||
env->pc = new_pc;
|
||||
cpu_loop_exit(env_cpu(env));
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ static void eret(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
g_assert_not_reached();
|
||||
#else
|
||||
TCGv tmp = tcg_temp_new();
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, regs[CR_ESTATUS]));
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, ctrl[CR_ESTATUS]));
|
||||
gen_helper_eret(cpu_env, tmp, cpu_R[R_EA]);
|
||||
tcg_temp_free(tmp);
|
||||
|
||||
|
@ -425,7 +425,7 @@ static void bret(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
g_assert_not_reached();
|
||||
#else
|
||||
TCGv tmp = tcg_temp_new();
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, regs[CR_BSTATUS]));
|
||||
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, ctrl[CR_BSTATUS]));
|
||||
gen_helper_eret(cpu_env, tmp, cpu_R[R_BA]);
|
||||
tcg_temp_free(tmp);
|
||||
|
||||
|
@ -481,7 +481,7 @@ static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
return;
|
||||
}
|
||||
|
||||
switch (instr.imm5 + CR_BASE) {
|
||||
switch (instr.imm5) {
|
||||
case CR_IPENDING:
|
||||
/*
|
||||
* The value of the ipending register is synthetic.
|
||||
|
@ -493,17 +493,15 @@ static void rdctl(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
*/
|
||||
t1 = tcg_temp_new();
|
||||
t2 = tcg_temp_new();
|
||||
tcg_gen_ld_tl(t1, cpu_env,
|
||||
offsetof(CPUNios2State, regs[CR_IPENDING]));
|
||||
tcg_gen_ld_tl(t2, cpu_env,
|
||||
offsetof(CPUNios2State, regs[CR_IENABLE]));
|
||||
tcg_gen_ld_tl(t1, cpu_env, offsetof(CPUNios2State, ctrl[CR_IPENDING]));
|
||||
tcg_gen_ld_tl(t2, cpu_env, offsetof(CPUNios2State, ctrl[CR_IENABLE]));
|
||||
tcg_gen_and_tl(cpu_R[instr.c], t1, t2);
|
||||
tcg_temp_free(t1);
|
||||
tcg_temp_free(t2);
|
||||
break;
|
||||
default:
|
||||
tcg_gen_ld_tl(cpu_R[instr.c], cpu_env,
|
||||
offsetof(CPUNios2State, regs[instr.imm5 + CR_BASE]));
|
||||
offsetof(CPUNios2State, ctrl[instr.imm5]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +519,7 @@ static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
R_TYPE(instr, code);
|
||||
TCGv v = load_gpr(dc, instr.a);
|
||||
|
||||
switch (instr.imm5 + CR_BASE) {
|
||||
switch (instr.imm5) {
|
||||
case CR_PTEADDR:
|
||||
gen_helper_mmu_write_pteaddr(cpu_env, v);
|
||||
break;
|
||||
|
@ -541,7 +539,7 @@ static void wrctl(DisasContext *dc, uint32_t code, uint32_t flags)
|
|||
/* fall through */
|
||||
default:
|
||||
tcg_gen_st_tl(v, cpu_env,
|
||||
offsetof(CPUNios2State, regs[instr.imm5 + CR_BASE]));
|
||||
offsetof(CPUNios2State, ctrl[instr.imm5]));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -774,7 +772,7 @@ illegal_op:
|
|||
t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
|
||||
}
|
||||
|
||||
static const char * const regnames[NUM_CORE_REGS] = {
|
||||
static const char * const gr_regnames[NUM_GP_REGS] = {
|
||||
"zero", "at", "r2", "r3",
|
||||
"r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11",
|
||||
|
@ -783,6 +781,9 @@ static const char * const regnames[NUM_CORE_REGS] = {
|
|||
"r20", "r21", "r22", "r23",
|
||||
"et", "bt", "gp", "sp",
|
||||
"fp", "ea", "ba", "ra",
|
||||
};
|
||||
|
||||
static const char * const cr_regnames[NUM_CR_REGS] = {
|
||||
"status", "estatus", "bstatus", "ienable",
|
||||
"ipending", "cpuid", "reserved0", "exception",
|
||||
"pteaddr", "tlbacc", "tlbmisc", "reserved1",
|
||||
|
@ -910,8 +911,14 @@ void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
|||
|
||||
qemu_fprintf(f, "IN: PC=%x %s\n", env->pc, lookup_symbol(env->pc));
|
||||
|
||||
for (i = 0; i < NUM_CORE_REGS; i++) {
|
||||
qemu_fprintf(f, "%9s=%8.8x ", regnames[i], env->regs[i]);
|
||||
for (i = 0; i < NUM_GP_REGS; i++) {
|
||||
qemu_fprintf(f, "%9s=%8.8x ", gr_regnames[i], env->regs[i]);
|
||||
if ((i + 1) % 4 == 0) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
for (i = 0; i < NUM_CR_REGS; i++) {
|
||||
qemu_fprintf(f, "%9s=%8.8x ", cr_regnames[i], env->ctrl[i]);
|
||||
if ((i + 1) % 4 == 0) {
|
||||
qemu_fprintf(f, "\n");
|
||||
}
|
||||
|
@ -932,7 +939,7 @@ void nios2_tcg_init(void)
|
|||
for (i = 0; i < NUM_GP_REGS; i++) {
|
||||
cpu_R[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUNios2State, regs[i]),
|
||||
regnames[i]);
|
||||
gr_regnames[i]);
|
||||
}
|
||||
cpu_pc = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUNios2State, pc), "pc");
|
||||
|
|
Loading…
Reference in New Issue