#include "exec.h"
#include "host-utils.h"
#include "helper.h"
+#include "sysemu.h"
//#define DEBUG_MMU
//#define DEBUG_MXCC
//#define DEBUG_ASI
//#define DEBUG_PCALL
//#define DEBUG_PSTATE
+//#define DEBUG_CACHE_CONTROL
#ifdef DEBUG_MMU
#define DPRINTF_MMU(fmt, ...) \
#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
#endif
+#ifdef DEBUG_CACHE_CONTROL
+#define DPRINTF_CACHE_CONTROL(fmt, ...) \
+ do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0)
+#endif
+
#ifdef TARGET_SPARC64
#ifndef TARGET_ABI32
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
#define QT0 (env->qt0)
#define QT1 (env->qt1)
+/* Leon3 cache control */
+
+/* Cache control: emulate the behavior of cache control registers but without
+ any effect on the emulated */
+
+#define CACHE_STATE_MASK 0x3
+#define CACHE_DISABLED 0x0
+#define CACHE_FROZEN 0x1
+#define CACHE_ENABLED 0x3
+
+/* Cache Control register fields */
+
+#define CACHE_CTRL_IF (1 << 4) /* Instruction Cache Freeze on Interrupt */
+#define CACHE_CTRL_DF (1 << 5) /* Data Cache Freeze on Interrupt */
+#define CACHE_CTRL_DP (1 << 14) /* Data cache flush pending */
+#define CACHE_CTRL_IP (1 << 15) /* Instruction cache flush pending */
+#define CACHE_CTRL_IB (1 << 16) /* Instruction burst fetch */
+#define CACHE_CTRL_FI (1 << 21) /* Flush Instruction cache (Write only) */
+#define CACHE_CTRL_FD (1 << 22) /* Flush Data cache (Write only) */
+#define CACHE_CTRL_DS (1 << 23) /* Data cache snoop enable */
+
#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
int is_asi, int size);
replace_tlb_entry(&tlb[i], 0, 0, env1);
#ifdef DEBUG_MMU
DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
- dump_mmu(env1);
+ dump_mmu(stdout, fprintf, env1);
#endif
}
}
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
- dump_mmu(env1);
+ dump_mmu(stdout, fprintf, env1);
#endif
return;
}
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
strmmu, (replace_used?"used":"unused"), i);
- dump_mmu(env1);
+ dump_mmu(stdout, fprintf, env1);
#endif
return;
}
return addr;
}
+/* returns true if access using this ASI is to have address translated by MMU
+ otherwise access is to raw physical address */
+static inline int is_translating_asi(int asi)
+{
+#ifdef TARGET_SPARC64
+ /* Ultrasparc IIi translating asi
+ - note this list is defined by cpu implementation
+ */
+ switch (asi) {
+ case 0x04 ... 0x11:
+ case 0x18 ... 0x19:
+ case 0x24 ... 0x2C:
+ case 0x70 ... 0x73:
+ case 0x78 ... 0x79:
+ case 0x80 ... 0xFF:
+ return 1;
+
+ default:
+ return 0;
+ }
+#else
+ /* TODO: check sparc32 bits */
+ return 0;
+#endif
+}
+
+static inline target_ulong asi_address_mask(CPUState *env1,
+ int asi, target_ulong addr)
+{
+ if (is_translating_asi(asi)) {
+ return address_mask(env, addr);
+ } else {
+ return addr;
+ }
+}
+
static void raise_exception(int tt)
{
env->exception_index = tt;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
void HELPER(raise_exception)(int tt)
raise_exception(tt);
}
+void helper_shutdown(void)
+{
+#if !defined(CONFIG_USER_ONLY)
+ qemu_system_shutdown_request();
+#endif
+}
+
void helper_check_align(target_ulong addr, uint32_t align)
{
if (addr & align) {
QT0 = float128_sqrt(QT1, &env->fp_status);
}
-#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
+#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
void glue(helper_, name) (void) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(reg1) || \
+ glue(size, _is_any_nan)(reg2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
-#define GEN_FCMPS(name, size, FS, TRAP) \
+#define GEN_FCMPS(name, size, FS, E) \
void glue(helper_, name)(float32 src1, float32 src2) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(src1) || \
+ glue(size, _is_any_nan)(src2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
GEN_FCMPS(fcmps, float32, 0, 0);
#ifndef TARGET_SPARC64
#ifndef CONFIG_USER_ONLY
+
+
+/* Leon3 cache control */
+
+static void leon3_cache_control_int(void)
+{
+ uint32_t state = 0;
+
+ if (env->cache_control & CACHE_CTRL_IF) {
+ /* Instruction cache state */
+ state = env->cache_control & CACHE_STATE_MASK;
+ if (state == CACHE_ENABLED) {
+ state = CACHE_FROZEN;
+ DPRINTF_CACHE_CONTROL("Instruction cache: freeze\n");
+ }
+
+ env->cache_control &= ~CACHE_STATE_MASK;
+ env->cache_control |= state;
+ }
+
+ if (env->cache_control & CACHE_CTRL_DF) {
+ /* Data cache state */
+ state = (env->cache_control >> 2) & CACHE_STATE_MASK;
+ if (state == CACHE_ENABLED) {
+ state = CACHE_FROZEN;
+ DPRINTF_CACHE_CONTROL("Data cache: freeze\n");
+ }
+
+ env->cache_control &= ~(CACHE_STATE_MASK << 2);
+ env->cache_control |= (state << 2);
+ }
+}
+
+static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
+{
+ DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
+ addr, val, size);
+
+ if (size != 4) {
+ DPRINTF_CACHE_CONTROL("32bits only\n");
+ return;
+ }
+
+ switch (addr) {
+ case 0x00: /* Cache control */
+
+ /* These values must always be read as zeros */
+ val &= ~CACHE_CTRL_FD;
+ val &= ~CACHE_CTRL_FI;
+ val &= ~CACHE_CTRL_IB;
+ val &= ~CACHE_CTRL_IP;
+ val &= ~CACHE_CTRL_DP;
+
+ env->cache_control = val;
+ break;
+ case 0x04: /* Instruction cache configuration */
+ case 0x08: /* Data cache configuration */
+ /* Read Only */
+ break;
+ default:
+ DPRINTF_CACHE_CONTROL("write unknown register %08x\n", addr);
+ break;
+ };
+}
+
+static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
+{
+ uint64_t ret = 0;
+
+ if (size != 4) {
+ DPRINTF_CACHE_CONTROL("32bits only\n");
+ return 0;
+ }
+
+ switch (addr) {
+ case 0x00: /* Cache control */
+ ret = env->cache_control;
+ break;
+
+ /* Configuration registers are read and only always keep those
+ predefined values */
+
+ case 0x04: /* Instruction cache configuration */
+ ret = 0x10220000;
+ break;
+ case 0x08: /* Data cache configuration */
+ ret = 0x18220000;
+ break;
+ default:
+ DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr);
+ break;
+ };
+ DPRINTF_CACHE_CONTROL("ld addr:%08x, ret:0x%" PRIx64 ", size:%d\n",
+ addr, ret, size);
+ return ret;
+}
+
+void leon3_irq_manager(void *irq_manager, int intno)
+{
+ leon3_irq_ack(irq_manager, intno);
+ leon3_cache_control_int();
+}
+
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
{
uint64_t ret = 0;
helper_check_align(addr, size - 1);
switch (asi) {
- case 2: /* SuperSparc MXCC registers */
+ case 2: /* SuperSparc MXCC registers and Leon3 cache control */
switch (addr) {
+ case 0x00: /* Leon3 Cache Control */
+ case 0x08: /* Leon3 Instruction Cache config */
+ case 0x0C: /* Leon3 Date Cache config */
+ if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+ ret = leon3_cache_control_ld(addr, size);
+ }
+ break;
case 0x01c00a00: /* MXCC control register */
if (size == 8)
ret = env->mxccregs[3];
ret);
}
break;
+ case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
+ ret = env->mmubpctrv;
+ break;
+ case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
+ ret = env->mmubpctrc;
+ break;
+ case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
+ ret = env->mmubpctrs;
+ break;
+ case 0x4c: /* SuperSPARC MMU Breakpoint Action */
+ ret = env->mmubpaction;
+ break;
case 8: /* User code access, XXX */
default:
do_unassigned_access(addr, 0, 0, asi, size);
{
helper_check_align(addr, size - 1);
switch(asi) {
- case 2: /* SuperSparc MXCC registers */
+ case 2: /* SuperSparc MXCC registers and Leon3 cache control */
switch (addr) {
+ case 0x00: /* Leon3 Cache Control */
+ case 0x08: /* Leon3 Instruction Cache config */
+ case 0x0C: /* Leon3 Date Cache config */
+ if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+ leon3_cache_control_st(addr, val, size);
+ }
+ break;
+
case 0x01c00000: /* MXCC stream data register 0 */
if (size == 8)
env->mxccdata[0] = val;
break;
}
#ifdef DEBUG_MMU
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
}
break;
reg, oldreg, env->mmuregs[reg]);
}
#ifdef DEBUG_MMU
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
}
break;
// descriptor diagnostic
case 0x36: /* I-cache flash clear */
case 0x37: /* D-cache flash clear */
- case 0x4c: /* breakpoint action */
break;
case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
{
env->mmuregs[reg]);
}
break;
+ case 0x49: /* SuperSPARC MMU Counter Breakpoint Value */
+ env->mmubpctrv = val & 0xffffffff;
+ break;
+ case 0x4a: /* SuperSPARC MMU Counter Breakpoint Control */
+ env->mmubpctrc = val & 0x3;
+ break;
+ case 0x4b: /* SuperSPARC MMU Counter Breakpoint Status */
+ env->mmubpctrs = val & 0x3;
+ break;
+ case 0x4c: /* SuperSPARC MMU Breakpoint Action */
+ env->mmubpaction = val & 0x1fff;
+ break;
case 8: /* User code access, XXX */
case 9: /* Supervisor code access, XXX */
default:
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
- addr = address_mask(env, addr);
+ addr = asi_address_mask(env, asi, addr);
switch (asi) {
case 0x82: // Primary no-fault
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
- addr = address_mask(env, addr);
+ addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
switch (asi) {
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0x82: // Primary no-fault
case 0x8a: // Primary no-fault LE
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
+ addr = asi_address_mask(env, asi, addr);
+
/* Convert to little endian */
switch (asi) {
case 0x0c: // Nucleus Little Endian (LE)
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
oldreg, env->lsu);
#ifdef DEBUG_MMU
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env1);
#endif
tlb_flush(env, 1);
}
PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
}
#ifdef DEBUG_MMU
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
return;
}
#ifdef DEBUG_MMU
DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
return;
}
PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
}
#ifdef DEBUG_MMU
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
return;
}
#ifdef DEBUG_MMU
DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
- dump_mmu(env);
+ dump_mmu(stdout, fprintf, env);
#endif
return;
}
&& !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
+#if !defined(CONFIG_USER_ONLY)
case 0x24: // Nucleus quad LDD 128 bit atomic
case 0x2c: // Nucleus quad LDD 128 bit atomic LE
helper_check_align(addr, 0xf);
if (rd == 0) {
- env->gregs[1] = ldq_kernel(addr + 8);
+ env->gregs[1] = ldq_nucleus(addr + 8);
if (asi == 0x2c)
bswap64s(&env->gregs[1]);
} else if (rd < 8) {
- env->gregs[rd] = ldq_kernel(addr);
- env->gregs[rd + 1] = ldq_kernel(addr + 8);
+ env->gregs[rd] = ldq_nucleus(addr);
+ env->gregs[rd + 1] = ldq_nucleus(addr + 8);
if (asi == 0x2c) {
bswap64s(&env->gregs[rd]);
bswap64s(&env->gregs[rd + 1]);
}
} else {
- env->regwptr[rd] = ldq_kernel(addr);
- env->regwptr[rd + 1] = ldq_kernel(addr + 8);
+ env->regwptr[rd] = ldq_nucleus(addr);
+ env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
if (asi == 0x2c) {
bswap64s(&env->regwptr[rd]);
bswap64s(&env->regwptr[rd + 1]);
}
}
break;
+#endif
default:
helper_check_align(addr, 0x3);
if (rd == 0)
target_ulong val;
helper_check_align(addr, 3);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0xf0: // Block load primary
case 0xf1: // Block load secondary
addr += 4;
}
+ return;
+ case 0x70: // Block load primary, user privilege
+ case 0x71: // Block load secondary, user privilege
+ if (rd & 7) {
+ raise_exception(TT_ILL_INSN);
+ return;
+ }
+ helper_check_align(addr, 0x3f);
+ for (i = 0; i < 16; i++) {
+ *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x1f, 4,
+ 0);
+ addr += 4;
+ }
+
return;
default:
break;
target_ulong val = 0;
helper_check_align(addr, 3);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0xe0: // UA2007 Block commit store primary (cache flush)
case 0xe1: // UA2007 Block commit store secondary (cache flush)
addr += 4;
}
+ return;
+ case 0x70: // Block store primary, user privilege
+ case 0x71: // Block store secondary, user privilege
+ if (rd & 7) {
+ raise_exception(TT_ILL_INSN);
+ return;
+ }
+ helper_check_align(addr, 0x3f);
+ for (i = 0; i < 16; i++) {
+ val = *(uint32_t *)&env->fpr[rd++];
+ helper_st_asi(addr, val, asi & 0x1f, 4);
+ addr += 4;
+ }
+
return;
default:
break;
}
#endif
-target_ulong helper_udiv(target_ulong a, target_ulong b)
+static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
{
+ int overflow = 0;
uint64_t x0;
uint32_t x1;
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
- x1 = b;
+ x1 = (b & 0xffffffff);
if (x1 == 0) {
raise_exception(TT_DIV_ZERO);
x0 = x0 / x1;
if (x0 > 0xffffffff) {
- env->cc_src2 = 1;
- return 0xffffffff;
- } else {
- env->cc_src2 = 0;
- return x0;
+ x0 = 0xffffffff;
+ overflow = 1;
}
+
+ if (cc) {
+ env->cc_dst = x0;
+ env->cc_src2 = overflow;
+ env->cc_op = CC_OP_DIV;
+ }
+ return x0;
}
-target_ulong helper_sdiv(target_ulong a, target_ulong b)
+target_ulong helper_udiv(target_ulong a, target_ulong b)
+{
+ return helper_udiv_common(a, b, 0);
+}
+
+target_ulong helper_udiv_cc(target_ulong a, target_ulong b)
{
+ return helper_udiv_common(a, b, 1);
+}
+
+static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
+{
+ int overflow = 0;
int64_t x0;
int32_t x1;
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
- x1 = b;
+ x1 = (b & 0xffffffff);
if (x1 == 0) {
raise_exception(TT_DIV_ZERO);
x0 = x0 / x1;
if ((int32_t) x0 != x0) {
- env->cc_src2 = 1;
- return x0 < 0? 0x80000000: 0x7fffffff;
- } else {
- env->cc_src2 = 0;
- return x0;
+ x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
+ overflow = 1;
}
+
+ if (cc) {
+ env->cc_dst = x0;
+ env->cc_src2 = overflow;
+ env->cc_op = CC_OP_DIV;
+ }
+ return x0;
+}
+
+target_ulong helper_sdiv(target_ulong a, target_ulong b)
+{
+ return helper_sdiv_common(a, b, 0);
+}
+
+target_ulong helper_sdiv_cc(target_ulong a, target_ulong b)
+{
+ return helper_sdiv_common(a, b, 1);
}
void helper_stdf(target_ulong addr, int mem_idx)
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
stfq_user(addr, DT0);
break;
- case 1:
+ case MMU_KERNEL_IDX:
stfq_kernel(addr, DT0);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
stfq_hypv(addr, DT0);
break;
#endif
default:
+ DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
DT0 = ldfq_user(addr);
break;
- case 1:
+ case MMU_KERNEL_IDX:
DT0 = ldfq_kernel(addr);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
DT0 = ldfq_hypv(addr);
break;
#endif
default:
+ DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
u.ll.upper = ldq_user(addr);
u.ll.lower = ldq_user(addr + 8);
QT0 = u.q;
break;
- case 1:
+ case MMU_KERNEL_IDX:
u.ll.upper = ldq_kernel(addr);
u.ll.lower = ldq_kernel(addr + 8);
QT0 = u.q;
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
u.ll.upper = ldq_hypv(addr);
u.ll.lower = ldq_hypv(addr + 8);
QT0 = u.q;
break;
#endif
default:
+ DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
u.q = QT0;
stq_user(addr, u.ll.upper);
stq_user(addr + 8, u.ll.lower);
break;
- case 1:
+ case MMU_KERNEL_IDX:
u.q = QT0;
stq_kernel(addr, u.ll.upper);
stq_kernel(addr + 8, u.ll.lower);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
u.q = QT0;
stq_hypv(addr, u.ll.upper);
stq_hypv(addr + 8, u.ll.lower);
break;
#endif
default:
+ DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
void helper_debug(void)
{
env->exception_index = EXCP_DEBUG;
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
#ifndef TARGET_SPARC64
}
#endif
-void helper_flush(target_ulong addr)
-{
- addr &= ~7;
- tb_invalidate_page_range(addr, addr + 8);
-}
-
#ifdef TARGET_SPARC64
#ifdef DEBUG_PCALL
static const char * const excp_names[0x80] = {
void do_interrupt(CPUState *env)
{
int intno = env->exception_index;
- trap_state* tsptr;
+ trap_state *tsptr;
#ifdef DEBUG_PCALL
if (qemu_loglevel_mask(CPU_LOG_INT)) {
static int count;
const char *name;
- if (intno < 0 || intno >= 0x180)
+ if (intno < 0 || intno >= 0x180) {
name = "Unknown";
- else if (intno >= 0x100)
+ } else if (intno >= 0x100) {
name = "Trap Instruction";
- else if (intno >= 0xc0)
+ } else if (intno >= 0xc0) {
name = "Window Fill";
- else if (intno >= 0x80)
+ } else if (intno >= 0x80) {
name = "Window Spill";
- else {
+ } else {
name = excp_names[intno];
- if (!name)
+ if (!name) {
name = "Unknown";
+ }
}
qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
qemu_log(" code=");
ptr = (uint8_t *)env->pc;
- for(i = 0; i < 16; i++) {
+ for (i = 0; i < 16; i++) {
qemu_log(" %02x", ldub(ptr + i));
}
qemu_log("\n");
env->tl++;
} else {
env->pstate |= PS_RED;
- if (env->tl < env->maxtl)
+ if (env->tl < env->maxtl) {
env->tl++;
+ }
}
tsptr = cpu_tsptr(env);
static int count;
const char *name;
- if (intno < 0 || intno >= 0x100)
+ if (intno < 0 || intno >= 0x100) {
name = "Unknown";
- else if (intno >= 0x80)
+ } else if (intno >= 0x80) {
name = "Trap Instruction";
- else {
+ } else {
name = excp_names[intno];
- if (!name)
+ if (!name) {
name = "Unknown";
+ }
}
qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
qemu_log(" code=");
ptr = (uint8_t *)env->pc;
- for(i = 0; i < 16; i++) {
+ for (i = 0; i < 16; i++) {
qemu_log(" %02x", ldub(ptr + i));
}
qemu_log("\n");
env->pc = env->tbr;
env->npc = env->pc + 4;
env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+ /* IRQ acknowledgment */
+ if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
+ env->qemu_irq_ack(env->irq_manager, intno);
+ }
+#endif
}
#endif
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
+ cpu_restore_state(tb, env, pc);
}
}
}
ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
if (ret) {
cpu_restore_state2(retaddr);
- cpu_loop_exit();
+ cpu_loop_exit(env);
}
env = saved_env;
}