#include <stdio.h>
#include <string.h>
#include <inttypes.h>
-#include <signal.h>
#include "cpu.h"
void superh_cpu_do_interrupt(CPUState *cs)
{
- SuperHCPU *cpu = SUPERH_CPU(cs);
- CPUSH4State *env = &cpu->env;
-
- env->exception_index = -1;
+ cs->exception_index = -1;
}
-int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
- int mmu_idx)
+int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
+
env->tea = address;
- env->exception_index = -1;
+ cs->exception_index = -1;
switch (rw) {
case 0:
- env->exception_index = 0x0a0;
+ cs->exception_index = 0x0a0;
break;
case 1:
- env->exception_index = 0x0c0;
+ cs->exception_index = 0x0c0;
break;
case 2:
- env->exception_index = 0x0a0;
+ cs->exception_index = 0x0a0;
break;
}
return 1;
int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
{
- /* For user mode, only U0 area is cachable. */
+ /* For user mode, only U0 area is cacheable. */
return !(addr & 0x80000000);
}
SuperHCPU *cpu = SUPERH_CPU(cs);
CPUSH4State *env = &cpu->env;
int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
- int do_exp, irq_vector = env->exception_index;
+ int do_exp, irq_vector = cs->exception_index;
/* prioritize exceptions over interrupts */
- do_exp = env->exception_index != -1;
- do_irq = do_irq && (env->exception_index == -1);
+ do_exp = cs->exception_index != -1;
+ do_irq = do_irq && (cs->exception_index == -1);
- if (env->sr & SR_BL) {
- if (do_exp && env->exception_index != 0x1e0) {
- env->exception_index = 0x000; /* masked exception -> reset */
+ if (env->sr & (1u << SR_BL)) {
+ if (do_exp && cs->exception_index != 0x1e0) {
+ cs->exception_index = 0x000; /* masked exception -> reset */
}
if (do_irq && !env->in_sleep) {
return; /* masked */
if (qemu_loglevel_mask(CPU_LOG_INT)) {
const char *expname;
- switch (env->exception_index) {
+ switch (cs->exception_index) {
case 0x0e0:
expname = "addr_error";
break;
log_cpu_state(cs, 0);
}
- env->ssr = env->sr;
+ env->ssr = cpu_read_sr(env);
env->spc = env->pc;
env->sgr = env->gregs[15];
- env->sr |= SR_BL | SR_MD | SR_RB;
+ env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
if (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
/* Branch instruction should be executed again before delay slot. */
env->flags = 0;
if (do_exp) {
- env->expevt = env->exception_index;
- switch (env->exception_index) {
+ env->expevt = cs->exception_index;
+ switch (cs->exception_index) {
case 0x000:
case 0x020:
case 0x140:
- env->sr &= ~SR_FD;
+ env->sr &= ~(1u << SR_FD);
env->sr |= 0xf << 4; /* IMASK */
env->pc = 0xa0000000;
break;
static int itlb_replacement(CPUSH4State * env)
{
- if ((env->mmucr & 0xe0000000) == 0xe0000000)
+ SuperHCPU *cpu = sh_env_get_cpu(env);
+
+ if ((env->mmucr & 0xe0000000) == 0xe0000000) {
return 0;
- if ((env->mmucr & 0x98000000) == 0x18000000)
+ }
+ if ((env->mmucr & 0x98000000) == 0x18000000) {
return 1;
- if ((env->mmucr & 0x54000000) == 0x04000000)
+ }
+ if ((env->mmucr & 0x54000000) == 0x04000000) {
return 2;
- if ((env->mmucr & 0x2c000000) == 0x00000000)
+ }
+ if ((env->mmucr & 0x2c000000) == 0x00000000) {
return 3;
- cpu_abort(env, "Unhandled itlb_replacement");
+ }
+ cpu_abort(CPU(cpu), "Unhandled itlb_replacement");
}
/* Find the corresponding entry in the right TLB
itlb = itlb_replacement(env);
ientry = &env->itlb[itlb];
if (ientry->v) {
- tlb_flush_page(env, ientry->vpn << 10);
+ tlb_flush_page(CPU(sh_env_get_cpu(env)), ientry->vpn << 10);
}
*ientry = env->utlb[utlb];
update_itlb_use(env, itlb);
int use_asid, n;
tlb_t *matching = NULL;
- use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
+ use_asid = !(env->mmucr & MMUCR_SV) || !(env->sr & (1u << SR_MD));
if (rw == 2) {
n = find_itlb_entry(env, address, use_asid);
if (n >= 0) {
matching = &env->itlb[n];
- if (!(env->sr & SR_MD) && !(matching->pr & 2))
+ if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
n = MMU_ITLB_VIOLATION;
- else
+ } else {
*prot = PAGE_EXEC;
+ }
} else {
n = find_utlb_entry(env, address, use_asid);
if (n >= 0) {
n = copy_utlb_entry_itlb(env, n);
matching = &env->itlb[n];
- if (!(env->sr & SR_MD) && !(matching->pr & 2)) {
- n = MMU_ITLB_VIOLATION;
+ if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
+ n = MMU_ITLB_VIOLATION;
} else {
*prot = PAGE_READ | PAGE_EXEC;
if ((matching->pr & 1) && matching->d) {
n = find_utlb_entry(env, address, use_asid);
if (n >= 0) {
matching = &env->utlb[n];
- if (!(env->sr & SR_MD) && !(matching->pr & 2)) {
+ if (!(env->sr & (1u << SR_MD)) && !(matching->pr & 2)) {
n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
MMU_DTLB_VIOLATION_READ;
} else if ((rw == 1) && !(matching->pr & 1)) {
/* P1, P2 and P4 areas do not use translation */
if ((address >= 0x80000000 && address < 0xc0000000) ||
address >= 0xe0000000) {
- if (!(env->sr & SR_MD)
+ if (!(env->sr & (1u << SR_MD))
&& (address < 0xe0000000 || address >= 0xe4000000)) {
/* Unauthorized access in user mode (only store queues are available) */
fprintf(stderr, "Unauthorized access\n");
return get_mmu_address(env, physical, prot, address, rw, access_type);
}
-int cpu_sh4_handle_mmu_fault(CPUSH4State * env, target_ulong address, int rw,
- int mmu_idx)
+int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
target_ulong physical;
int prot, ret, access_type;
switch (ret) {
case MMU_ITLB_MISS:
case MMU_DTLB_MISS_READ:
- env->exception_index = 0x040;
+ cs->exception_index = 0x040;
break;
case MMU_DTLB_MULTIPLE:
case MMU_ITLB_MULTIPLE:
- env->exception_index = 0x140;
+ cs->exception_index = 0x140;
break;
case MMU_ITLB_VIOLATION:
- env->exception_index = 0x0a0;
+ cs->exception_index = 0x0a0;
break;
case MMU_DTLB_MISS_WRITE:
- env->exception_index = 0x060;
+ cs->exception_index = 0x060;
break;
case MMU_DTLB_INITIAL_WRITE:
- env->exception_index = 0x080;
+ cs->exception_index = 0x080;
break;
case MMU_DTLB_VIOLATION_READ:
- env->exception_index = 0x0a0;
+ cs->exception_index = 0x0a0;
break;
case MMU_DTLB_VIOLATION_WRITE:
- env->exception_index = 0x0c0;
+ cs->exception_index = 0x0c0;
break;
case MMU_IADDR_ERROR:
case MMU_DADDR_ERROR_READ:
- env->exception_index = 0x0e0;
+ cs->exception_index = 0x0e0;
break;
case MMU_DADDR_ERROR_WRITE:
- env->exception_index = 0x100;
+ cs->exception_index = 0x100;
break;
default:
- cpu_abort(env, "Unhandled MMU fault");
+ cpu_abort(cs, "Unhandled MMU fault");
}
return 1;
}
address &= TARGET_PAGE_MASK;
physical &= TARGET_PAGE_MASK;
- tlb_set_page(env, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
+ tlb_set_page(cs, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
}
void cpu_load_tlb(CPUSH4State * env)
{
+ SuperHCPU *cpu = sh_env_get_cpu(env);
int n = cpu_mmucr_urc(env->mmucr);
tlb_t * entry = &env->utlb[n];
if (entry->v) {
/* Overwriting valid entry in utlb. */
target_ulong address = entry->vpn << 10;
- tlb_flush_page(env, address);
+ tlb_flush_page(CPU(cpu), address);
}
/* Take values into cpu status from registers. */
entry->size = 1024 * 1024; /* 1M */
break;
default:
- cpu_abort(env, "Unhandled load_tlb");
+ cpu_abort(CPU(cpu), "Unhandled load_tlb");
break;
}
entry->sh = (uint8_t)cpu_ptel_sh(env->ptel);
entry->v = 0;
}
- tlb_flush(s, 1);
+ tlb_flush(CPU(sh_env_get_cpu(s)), 1);
}
uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s,
if (entry->v) {
/* Overwriting valid entry in itlb. */
target_ulong address = entry->vpn << 10;
- tlb_flush_page(s, address);
+ tlb_flush_page(CPU(sh_env_get_cpu(s)), address);
}
entry->asid = asid;
entry->vpn = vpn;
if (entry->v) {
/* Overwriting valid entry in utlb. */
target_ulong address = entry->vpn << 10;
- tlb_flush_page(s, address);
+ tlb_flush_page(CPU(sh_env_get_cpu(s)), address);
}
entry->ppn = (mem_value & 0x1ffffc00) >> 10;
entry->v = (mem_value & 0x00000100) >> 8;
uint8_t d = (uint8_t)((mem_value & 0x00000200) >> 9);
uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
- int use_asid = (s->mmucr & MMUCR_SV) == 0 || (s->sr & SR_MD) == 0;
+ int use_asid = !(s->mmucr & MMUCR_SV) || !(s->sr & (1u << SR_MD));
if (associate) {
int i;
if (entry->vpn == vpn
&& (!use_asid || entry->asid == asid || entry->sh)) {
if (utlb_match_entry) {
+ CPUState *cs = CPU(sh_env_get_cpu(s));
+
/* Multiple TLB Exception */
- s->exception_index = 0x140;
+ cs->exception_index = 0x140;
s->tea = addr;
break;
}
}
}
- if (needs_tlb_flush)
- tlb_flush_page(s, vpn << 10);
+ if (needs_tlb_flush) {
+ tlb_flush_page(CPU(sh_env_get_cpu(s)), vpn << 10);
+ }
} else {
int index = (addr & 0x00003f00) >> 8;
tlb_t * entry = &s->utlb[index];
if (entry->v) {
+ CPUState *cs = CPU(sh_env_get_cpu(s));
+
/* Overwriting valid entry in utlb. */
target_ulong address = entry->vpn << 10;
- tlb_flush_page(s, address);
+ tlb_flush_page(cs, address);
}
entry->asid = asid;
entry->vpn = vpn;
if (entry->v) {
/* Overwriting valid entry in utlb. */
target_ulong address = entry->vpn << 10;
- tlb_flush_page(s, address);
+ tlb_flush_page(CPU(sh_env_get_cpu(s)), address);
}
entry->ppn = (mem_value & 0x1ffffc00) >> 10;
entry->v = (mem_value & 0x00000100) >> 8;
int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
{
int n;
- int use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
+ int use_asid = !(env->mmucr & MMUCR_SV) || !(env->sr & (1u << SR_MD));
/* check area */
- if (env->sr & SR_MD) {
- /* For previledged mode, P2 and P4 area is not cachable. */
+ if (env->sr & (1u << SR_MD)) {
+ /* For privileged mode, P2 and P4 area is not cacheable. */
if ((0xA0000000 <= addr && addr < 0xC0000000) || 0xE0000000 <= addr)
return 0;
} else {
- /* For user mode, only U0 area is cachable. */
+ /* For user mode, only U0 area is cacheable. */
if (0x80000000 <= addr)
return 0;
}
}
#endif
+
+bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ superh_cpu_do_interrupt(cs);
+ return true;
+ }
+ return false;
+}