aboutsummaryrefslogtreecommitdiff
path: root/target-sparc/ldst_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc/ldst_helper.c')
-rw-r--r--target-sparc/ldst_helper.c696
1 files changed, 313 insertions, 383 deletions
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index e941cac..6ce5ccc 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -19,9 +19,11 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "tcg.h"
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
+#include "asi.h"
//#define DEBUG_MMU
//#define DEBUG_MXCC
@@ -427,9 +429,11 @@ static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr,
return ret;
}
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
- int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
+ int sign = memop & MO_SIGN;
CPUState *cs = CPU(sparc_env_get_cpu(env));
uint64_t ret = 0;
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
@@ -438,7 +442,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
helper_check_align(env, addr, size - 1);
switch (asi) {
- case 2: /* SuperSparc MXCC registers and Leon3 cache control */
+ case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
+ /* case ASI_LEON_CACHEREGS: Leon3 cache control */
switch (addr) {
case 0x00: /* Leon3 Cache Control */
case 0x08: /* Leon3 Instruction Cache config */
@@ -497,8 +502,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
dump_mxcc(env);
#endif
break;
- case 3: /* MMU probe */
- case 0x18: /* LEON3 MMU probe */
+ case ASI_M_FLUSH_PROBE: /* SuperSparc MMU probe */
+ case ASI_LEON_MMUFLUSH: /* LEON3 MMU probe */
{
int mmulev;
@@ -512,8 +517,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
addr, mmulev, ret);
}
break;
- case 4: /* read MMU regs */
- case 0x19: /* LEON3 read MMU regs */
+ case ASI_M_MMUREGS: /* SuperSparc MMU regs */
+ case ASI_LEON_MMUREGS: /* LEON3 MMU regs */
{
int reg = (addr >> 8) & 0x1f;
@@ -528,11 +533,11 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
}
break;
- case 5: /* Turbosparc ITLB Diagnostic */
- case 6: /* Turbosparc DTLB Diagnostic */
- case 7: /* Turbosparc IOTLB Diagnostic */
+ case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */
+ case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */
+ case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */
break;
- case 9: /* Supervisor code access */
+ case ASI_KERNELTXT: /* Supervisor code access */
switch (size) {
case 1:
ret = cpu_ldub_code(env, addr);
@@ -549,7 +554,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
break;
}
break;
- case 0xa: /* User data access */
+ case ASI_USERDATA: /* User data access */
switch (size) {
case 1:
ret = cpu_ldub_user(env, addr);
@@ -566,8 +571,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
break;
}
break;
- case 0xb: /* Supervisor data access */
- case 0x80:
+ case ASI_KERNELDATA: /* Supervisor data access */
+ case ASI_P: /* Implicit primary context data access (v9 only?) */
switch (size) {
case 1:
ret = cpu_ldub_kernel(env, addr);
@@ -584,13 +589,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
break;
}
break;
- case 0xc: /* I-cache tag */
- case 0xd: /* I-cache data */
- case 0xe: /* D-cache tag */
- case 0xf: /* D-cache data */
+ case ASI_M_TXTC_TAG: /* SparcStation 5 I-cache tag */
+ case ASI_M_TXTC_DATA: /* SparcStation 5 I-cache data */
+ case ASI_M_DATAC_TAG: /* SparcStation 5 D-cache tag */
+ case ASI_M_DATAC_DATA: /* SparcStation 5 D-cache data */
break;
- case 0x20: /* MMU passthrough */
- case 0x1c: /* LEON MMU passthrough */
+ case ASI_M_BYPASS: /* MMU passthrough */
+ case ASI_LEON_BYPASS: /* LEON MMU passthrough */
switch (size) {
case 1:
ret = ldub_phys(cs->as, addr);
@@ -669,7 +674,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
case 0x4c: /* SuperSPARC MMU Breakpoint Action */
ret = env->mmubpaction;
break;
- case 8: /* User code access, XXX */
+ case ASI_USERTXT: /* User code access, XXX */
default:
cpu_unassigned_access(cs, addr, false, false, asi, size);
ret = 0;
@@ -696,15 +701,17 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
return ret;
}
-void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
- int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val,
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
SPARCCPU *cpu = sparc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
helper_check_align(env, addr, size - 1);
switch (asi) {
- case 2: /* SuperSparc MXCC registers and Leon3 cache control */
+ case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
+ /* case ASI_LEON_CACHEREGS: Leon3 cache control */
switch (addr) {
case 0x00: /* Leon3 Cache Control */
case 0x08: /* Leon3 Instruction Cache config */
@@ -838,8 +845,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
dump_mxcc(env);
#endif
break;
- case 3: /* MMU flush */
- case 0x18: /* LEON3 MMU flush */
+ case ASI_M_FLUSH_PROBE: /* SuperSparc MMU flush */
+ case ASI_LEON_MMUFLUSH: /* LEON3 MMU flush */
{
int mmulev;
@@ -863,8 +870,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
#endif
}
break;
- case 4: /* write MMU regs */
- case 0x19: /* LEON3 write MMU regs */
+ case ASI_M_MMUREGS: /* write MMU regs */
+ case ASI_LEON_MMUREGS: /* LEON3 write MMU regs */
{
int reg = (addr >> 8) & 0x1f;
uint32_t oldreg;
@@ -918,11 +925,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
#endif
}
break;
- case 5: /* Turbosparc ITLB Diagnostic */
- case 6: /* Turbosparc DTLB Diagnostic */
- case 7: /* Turbosparc IOTLB Diagnostic */
+ case ASI_M_TLBDIAG: /* Turbosparc ITLB Diagnostic */
+ case ASI_M_DIAGS: /* Turbosparc DTLB Diagnostic */
+ case ASI_M_IODIAG: /* Turbosparc IOTLB Diagnostic */
break;
- case 0xa: /* User data access */
+ case ASI_USERDATA: /* User data access */
switch (size) {
case 1:
cpu_stb_user(env, addr, val);
@@ -939,8 +946,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
break;
}
break;
- case 0xb: /* Supervisor data access */
- case 0x80:
+ case ASI_KERNELDATA: /* Supervisor data access */
+ case ASI_P:
switch (size) {
case 1:
cpu_stb_kernel(env, addr, val);
@@ -957,17 +964,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
break;
}
break;
- case 0xc: /* I-cache tag */
- case 0xd: /* I-cache data */
- case 0xe: /* D-cache tag */
- case 0xf: /* D-cache data */
- case 0x10: /* I/D-cache flush page */
- case 0x11: /* I/D-cache flush segment */
- case 0x12: /* I/D-cache flush region */
- case 0x13: /* I/D-cache flush context */
- case 0x14: /* I/D-cache flush user */
+ case ASI_M_TXTC_TAG: /* I-cache tag */
+ case ASI_M_TXTC_DATA: /* I-cache data */
+ case ASI_M_DATAC_TAG: /* D-cache tag */
+ case ASI_M_DATAC_DATA: /* D-cache data */
+ case ASI_M_FLUSH_PAGE: /* I/D-cache flush page */
+ case ASI_M_FLUSH_SEG: /* I/D-cache flush segment */
+ case ASI_M_FLUSH_REGION: /* I/D-cache flush region */
+ case ASI_M_FLUSH_CTX: /* I/D-cache flush context */
+ case ASI_M_FLUSH_USER: /* I/D-cache flush user */
break;
- case 0x17: /* Block copy, sta access */
+ case ASI_M_BCOPY: /* Block copy, sta access */
{
/* val = src
addr = dst
@@ -981,20 +988,20 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
}
}
break;
- case 0x1f: /* Block fill, stda access */
+ case ASI_M_BFILL: /* Block fill, stda access */
{
/* addr = dst
fill 32 bytes with val */
unsigned int i;
- uint32_t dst = addr & 7;
+ uint32_t dst = addr & ~7;
for (i = 0; i < 32; i += 8, dst += 8) {
cpu_stq_kernel(env, dst, val);
}
}
break;
- case 0x20: /* MMU passthrough */
- case 0x1c: /* LEON MMU passthrough */
+ case ASI_M_BYPASS: /* MMU passthrough */
+ case ASI_LEON_BYPASS: /* LEON MMU passthrough */
{
switch (size) {
case 1:
@@ -1078,8 +1085,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
case 0x4c: /* SuperSPARC MMU Breakpoint Action */
env->mmubpaction = val & 0x1fff;
break;
- case 8: /* User code access, XXX */
- case 9: /* Supervisor code access, XXX */
+ case ASI_USERTXT: /* User code access, XXX */
+ case ASI_KERNELTXT: /* Supervisor code access, XXX */
default:
cpu_unassigned_access(CPU(sparc_env_get_cpu(env)),
addr, true, false, asi, size);
@@ -1094,9 +1101,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
#else /* TARGET_SPARC64 */
#ifdef CONFIG_USER_ONLY
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
- int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
+ int sign = memop & MO_SIGN;
uint64_t ret = 0;
#if defined(DEBUG_ASI)
target_ulong last_addr = addr;
@@ -1110,8 +1119,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
addr = asi_address_mask(env, asi, addr);
switch (asi) {
- case 0x82: /* Primary no-fault */
- case 0x8a: /* Primary no-fault LE */
+ case ASI_PNF: /* Primary no-fault */
+ case ASI_PNFL: /* Primary no-fault LE */
if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
dump_asi("read ", last_addr, asi, size, ret);
@@ -1119,8 +1128,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
return 0;
}
/* Fall through */
- case 0x80: /* Primary */
- case 0x88: /* Primary LE */
+ case ASI_P: /* Primary */
+ case ASI_PL: /* Primary LE */
{
switch (size) {
case 1:
@@ -1139,8 +1148,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
}
break;
- case 0x83: /* Secondary no-fault */
- case 0x8b: /* Secondary no-fault LE */
+ case ASI_SNF: /* Secondary no-fault */
+ case ASI_SNFL: /* Secondary no-fault LE */
if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
dump_asi("read ", last_addr, asi, size, ret);
@@ -1148,8 +1157,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
return 0;
}
/* Fall through */
- case 0x81: /* Secondary */
- case 0x89: /* Secondary LE */
+ case ASI_S: /* Secondary */
+ case ASI_SL: /* Secondary LE */
/* XXX */
break;
default:
@@ -1158,10 +1167,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
/* Convert from little endian */
switch (asi) {
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
- case 0x8a: /* Primary no-fault LE */
- case 0x8b: /* Secondary no-fault LE */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
+ case ASI_PNFL: /* Primary no-fault LE */
+ case ASI_SNFL: /* Secondary no-fault LE */
switch (size) {
case 2:
ret = bswap16(ret);
@@ -1202,8 +1211,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
- int asi, int size)
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
#ifdef DEBUG_ASI
dump_asi("write", addr, asi, size, val);
#endif
@@ -1216,8 +1226,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
/* Convert to little endian */
switch (asi) {
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
switch (size) {
case 2:
val = bswap16(val);
@@ -1236,8 +1246,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
switch (asi) {
- case 0x80: /* Primary */
- case 0x88: /* Primary LE */
+ case ASI_P: /* Primary */
+ case ASI_PL: /* Primary LE */
{
switch (size) {
case 1:
@@ -1256,15 +1266,15 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
}
break;
- case 0x81: /* Secondary */
- case 0x89: /* Secondary LE */
+ case ASI_S: /* Secondary */
+ case ASI_SL: /* Secondary LE */
/* XXX */
return;
- case 0x82: /* Primary no-fault, RO */
- case 0x83: /* Secondary no-fault, RO */
- case 0x8a: /* Primary no-fault LE, RO */
- case 0x8b: /* Secondary no-fault LE, RO */
+ case ASI_PNF: /* Primary no-fault, RO */
+ case ASI_SNF: /* Secondary no-fault, RO */
+ case ASI_PNFL: /* Primary no-fault LE, RO */
+ case ASI_SNFL: /* Secondary no-fault LE, RO */
default:
helper_raise_exception(env, TT_DATA_ACCESS);
return;
@@ -1273,9 +1283,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#else /* CONFIG_USER_ONLY */
-uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
- int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
+ int sign = memop & MO_SIGN;
CPUState *cs = CPU(sparc_env_get_cpu(env));
uint64_t ret = 0;
#if defined(DEBUG_ASI)
@@ -1318,16 +1330,14 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
switch (asi) {
- case 0x10: /* As if user primary */
- case 0x11: /* As if user secondary */
- case 0x18: /* As if user primary LE */
- case 0x19: /* As if user secondary LE */
- case 0x80: /* Primary */
- case 0x81: /* Secondary */
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
- case 0xe2: /* UA2007 Primary block init */
- case 0xe3: /* UA2007 Secondary block init */
+ case ASI_AIUP: /* As if user primary */
+ case ASI_AIUS: /* As if user secondary */
+ case ASI_AIUPL: /* As if user primary LE */
+ case ASI_AIUSL: /* As if user secondary LE */
+ case ASI_P: /* Primary */
+ case ASI_S: /* Secondary */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
if (cpu_hypervisor_mode(env)) {
switch (size) {
@@ -1418,10 +1428,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
}
break;
- case 0x14: /* Bypass */
- case 0x15: /* Bypass, non-cacheable */
- case 0x1c: /* Bypass LE */
- case 0x1d: /* Bypass, non-cacheable LE */
+ case ASI_REAL: /* Bypass */
+ case ASI_REAL_IO: /* Bypass, non-cacheable */
+ case ASI_REAL_L: /* Bypass LE */
+ case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
{
switch (size) {
case 1:
@@ -1440,13 +1450,8 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
break;
}
- case 0x24: /* Nucleus quad LDD 128 bit atomic */
- case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
- Only ldda allowed */
- helper_raise_exception(env, TT_ILL_INSN);
- return 0;
- case 0x04: /* Nucleus */
- case 0x0c: /* Nucleus Little Endian (LE) */
+ case ASI_N: /* Nucleus */
+ case ASI_NL: /* Nucleus Little Endian (LE) */
{
switch (size) {
case 1:
@@ -1465,13 +1470,13 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
break;
}
- case 0x4a: /* UPA config */
+ case ASI_UPA_CONFIG: /* UPA config */
/* XXX */
break;
- case 0x45: /* LSU */
+ case ASI_LSU_CONTROL: /* LSU */
ret = env->lsu;
break;
- case 0x50: /* I-MMU regs */
+ case ASI_IMMU: /* I-MMU regs */
{
int reg = (addr >> 3) & 0xf;
@@ -1484,7 +1489,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
break;
}
- case 0x51: /* I-MMU 8k TSB pointer */
+ case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer */
{
/* env->immuregs[5] holds I-MMU TSB register value
env->immuregs[6] holds I-MMU Tag Access register value */
@@ -1492,7 +1497,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
8*1024);
break;
}
- case 0x52: /* I-MMU 64k TSB pointer */
+ case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer */
{
/* env->immuregs[5] holds I-MMU TSB register value
env->immuregs[6] holds I-MMU Tag Access register value */
@@ -1500,21 +1505,21 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
64*1024);
break;
}
- case 0x55: /* I-MMU data access */
+ case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */
{
int reg = (addr >> 3) & 0x3f;
ret = env->itlb[reg].tte;
break;
}
- case 0x56: /* I-MMU tag read */
+ case ASI_ITLB_TAG_READ: /* I-MMU tag read */
{
int reg = (addr >> 3) & 0x3f;
ret = env->itlb[reg].tag;
break;
}
- case 0x58: /* D-MMU regs */
+ case ASI_DMMU: /* D-MMU regs */
{
int reg = (addr >> 3) & 0xf;
@@ -1526,7 +1531,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
break;
}
- case 0x59: /* D-MMU 8k TSB pointer */
+ case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer */
{
/* env->dmmuregs[5] holds D-MMU TSB register value
env->dmmuregs[6] holds D-MMU Tag Access register value */
@@ -1534,7 +1539,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
8*1024);
break;
}
- case 0x5a: /* D-MMU 64k TSB pointer */
+ case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer */
{
/* env->dmmuregs[5] holds D-MMU TSB register value
env->dmmuregs[6] holds D-MMU Tag Access register value */
@@ -1542,26 +1547,26 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
64*1024);
break;
}
- case 0x5d: /* D-MMU data access */
+ case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */
{
int reg = (addr >> 3) & 0x3f;
ret = env->dtlb[reg].tte;
break;
}
- case 0x5e: /* D-MMU tag read */
+ case ASI_DTLB_TAG_READ: /* D-MMU tag read */
{
int reg = (addr >> 3) & 0x3f;
ret = env->dtlb[reg].tag;
break;
}
- case 0x48: /* Interrupt dispatch, RO */
+ case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */
break;
- case 0x49: /* Interrupt data receive */
+ case ASI_INTR_RECEIVE: /* Interrupt data receive */
ret = env->ivec_status;
break;
- case 0x7f: /* Incoming interrupt vector, RO */
+ case ASI_INTR_R: /* Incoming interrupt vector, RO */
{
int reg = (addr >> 4) & 0x3;
if (reg < 3) {
@@ -1569,40 +1574,59 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
break;
}
- case 0x46: /* D-cache data */
- case 0x47: /* D-cache tag access */
- case 0x4b: /* E-cache error enable */
- case 0x4c: /* E-cache asynchronous fault status */
- case 0x4d: /* E-cache asynchronous fault address */
- case 0x4e: /* E-cache tag data */
- case 0x66: /* I-cache instruction access */
- case 0x67: /* I-cache tag access */
- case 0x6e: /* I-cache predecode */
- case 0x6f: /* I-cache LRU etc. */
- case 0x76: /* E-cache tag */
- case 0x7e: /* E-cache tag */
- break;
- case 0x5b: /* D-MMU data pointer */
- case 0x54: /* I-MMU data in, WO */
- case 0x57: /* I-MMU demap, WO */
- case 0x5c: /* D-MMU data in, WO */
- case 0x5f: /* D-MMU demap, WO */
- case 0x77: /* Interrupt vector, WO */
+ case ASI_DCACHE_DATA: /* D-cache data */
+ case ASI_DCACHE_TAG: /* D-cache tag access */
+ case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
+ case ASI_AFSR: /* E-cache asynchronous fault status */
+ case ASI_AFAR: /* E-cache asynchronous fault address */
+ case ASI_EC_TAG_DATA: /* E-cache tag data */
+ case ASI_IC_INSTR: /* I-cache instruction access */
+ case ASI_IC_TAG: /* I-cache tag access */
+ case ASI_IC_PRE_DECODE: /* I-cache predecode */
+ case ASI_IC_NEXT_FIELD: /* I-cache LRU etc. */
+ case ASI_EC_W: /* E-cache tag */
+ case ASI_EC_R: /* E-cache tag */
+ break;
+ case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer */
+ case ASI_ITLB_DATA_IN: /* I-MMU data in, WO */
+ case ASI_IMMU_DEMAP: /* I-MMU demap, WO */
+ case ASI_DTLB_DATA_IN: /* D-MMU data in, WO */
+ case ASI_DMMU_DEMAP: /* D-MMU demap, WO */
+ case ASI_INTR_W: /* Interrupt vector, WO */
default:
cpu_unassigned_access(cs, addr, false, false, 1, size);
ret = 0;
break;
+
+ case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */
+ case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+ case ASI_TWINX_AIUP: /* As if user primary, twinx */
+ case ASI_TWINX_AIUS: /* As if user secondary, twinx */
+ case ASI_TWINX_REAL: /* Real address, twinx */
+ case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+ case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+ case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+ case ASI_TWINX_N: /* Nucleus, twinx */
+ case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+ /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+ case ASI_TWINX_P: /* Primary, twinx */
+ case ASI_TWINX_PL: /* Primary, twinx, LE */
+ case ASI_TWINX_S: /* Secondary, twinx */
+ case ASI_TWINX_SL: /* Secondary, twinx, LE */
+ /* These are all 128-bit atomic; only ldda (now ldtxa) allowed */
+ helper_raise_exception(env, TT_ILL_INSN);
+ return 0;
}
/* Convert from little endian */
switch (asi) {
- case 0x0c: /* Nucleus Little Endian (LE) */
- case 0x18: /* As if user primary LE */
- case 0x19: /* As if user secondary LE */
- case 0x1c: /* Bypass LE */
- case 0x1d: /* Bypass, non-cacheable LE */
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
+ case ASI_NL: /* Nucleus Little Endian (LE) */
+ case ASI_AIUPL: /* As if user primary LE */
+ case ASI_AIUSL: /* As if user secondary LE */
+ case ASI_REAL_L: /* Bypass LE */
+ case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
switch(size) {
case 2:
ret = bswap16(ret);
@@ -1643,8 +1667,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
- int asi, int size)
+ int asi, uint32_t memop)
{
+ int size = 1 << (memop & MO_SIZE);
SPARCCPU *cpu = sparc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
@@ -1666,13 +1691,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
/* Convert to little endian */
switch (asi) {
- case 0x0c: /* Nucleus Little Endian (LE) */
- case 0x18: /* As if user primary LE */
- case 0x19: /* As if user secondary LE */
- case 0x1c: /* Bypass LE */
- case 0x1d: /* Bypass, non-cacheable LE */
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
+ case ASI_NL: /* Nucleus Little Endian (LE) */
+ case ASI_AIUPL: /* As if user primary LE */
+ case ASI_AIUSL: /* As if user secondary LE */
+ case ASI_REAL_L: /* Bypass LE */
+ case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
switch (size) {
case 2:
val = bswap16(val);
@@ -1691,16 +1716,14 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
switch (asi) {
- case 0x10: /* As if user primary */
- case 0x11: /* As if user secondary */
- case 0x18: /* As if user primary LE */
- case 0x19: /* As if user secondary LE */
- case 0x80: /* Primary */
- case 0x81: /* Secondary */
- case 0x88: /* Primary LE */
- case 0x89: /* Secondary LE */
- case 0xe2: /* UA2007 Primary block init */
- case 0xe3: /* UA2007 Secondary block init */
+ case ASI_AIUP: /* As if user primary */
+ case ASI_AIUS: /* As if user secondary */
+ case ASI_AIUPL: /* As if user primary LE */
+ case ASI_AIUSL: /* As if user secondary LE */
+ case ASI_P: /* Primary */
+ case ASI_S: /* Secondary */
+ case ASI_PL: /* Primary LE */
+ case ASI_SL: /* Secondary LE */
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
if (cpu_hypervisor_mode(env)) {
switch (size) {
@@ -1791,10 +1814,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
}
break;
- case 0x14: /* Bypass */
- case 0x15: /* Bypass, non-cacheable */
- case 0x1c: /* Bypass LE */
- case 0x1d: /* Bypass, non-cacheable LE */
+ case ASI_REAL: /* Bypass */
+ case ASI_REAL_IO: /* Bypass, non-cacheable */
+ case ASI_REAL_L: /* Bypass LE */
+ case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
{
switch (size) {
case 1:
@@ -1813,13 +1836,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
}
return;
- case 0x24: /* Nucleus quad LDD 128 bit atomic */
- case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
- Only ldda allowed */
- helper_raise_exception(env, TT_ILL_INSN);
- return;
- case 0x04: /* Nucleus */
- case 0x0c: /* Nucleus Little Endian (LE) */
+ case ASI_N: /* Nucleus */
+ case ASI_NL: /* Nucleus Little Endian (LE) */
{
switch (size) {
case 1:
@@ -1839,10 +1857,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
break;
}
- case 0x4a: /* UPA config */
+ case ASI_UPA_CONFIG: /* UPA config */
/* XXX */
return;
- case 0x45: /* LSU */
+ case ASI_LSU_CONTROL: /* LSU */
{
uint64_t oldreg;
@@ -1860,7 +1878,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
return;
}
- case 0x50: /* I-MMU regs */
+ case ASI_IMMU: /* I-MMU regs */
{
int reg = (addr >> 3) & 0xf;
uint64_t oldreg;
@@ -1904,10 +1922,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#endif
return;
}
- case 0x54: /* I-MMU data in */
+ case ASI_ITLB_DATA_IN: /* I-MMU data in */
replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
return;
- case 0x55: /* I-MMU data access */
+ case ASI_ITLB_DATA_ACCESS: /* I-MMU data access */
{
/* TODO: auto demap */
@@ -1921,10 +1939,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#endif
return;
}
- case 0x57: /* I-MMU demap */
+ case ASI_IMMU_DEMAP: /* I-MMU demap */
demap_tlb(env->itlb, addr, "immu", env);
return;
- case 0x58: /* D-MMU regs */
+ case ASI_DMMU: /* D-MMU regs */
{
int reg = (addr >> 3) & 0xf;
uint64_t oldreg;
@@ -1977,10 +1995,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#endif
return;
}
- case 0x5c: /* D-MMU data in */
+ case ASI_DTLB_DATA_IN: /* D-MMU data in */
replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
return;
- case 0x5d: /* D-MMU data access */
+ case ASI_DTLB_DATA_ACCESS: /* D-MMU data access */
{
unsigned int i = (addr >> 3) & 0x3f;
@@ -1992,38 +2010,56 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#endif
return;
}
- case 0x5f: /* D-MMU demap */
+ case ASI_DMMU_DEMAP: /* D-MMU demap */
demap_tlb(env->dtlb, addr, "dmmu", env);
return;
- case 0x49: /* Interrupt data receive */
+ case ASI_INTR_RECEIVE: /* Interrupt data receive */
env->ivec_status = val & 0x20;
return;
- case 0x46: /* D-cache data */
- case 0x47: /* D-cache tag access */
- case 0x4b: /* E-cache error enable */
- case 0x4c: /* E-cache asynchronous fault status */
- case 0x4d: /* E-cache asynchronous fault address */
- case 0x4e: /* E-cache tag data */
- case 0x66: /* I-cache instruction access */
- case 0x67: /* I-cache tag access */
- case 0x6e: /* I-cache predecode */
- case 0x6f: /* I-cache LRU etc. */
- case 0x76: /* E-cache tag */
- case 0x7e: /* E-cache tag */
+ case ASI_NUCLEUS_QUAD_LDD: /* Nucleus quad LDD 128 bit atomic */
+ case ASI_NUCLEUS_QUAD_LDD_L: /* Nucleus quad LDD 128 bit atomic LE */
+ case ASI_TWINX_AIUP: /* As if user primary, twinx */
+ case ASI_TWINX_AIUS: /* As if user secondary, twinx */
+ case ASI_TWINX_REAL: /* Real address, twinx */
+ case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
+ case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+ case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+ case ASI_TWINX_N: /* Nucleus, twinx */
+ case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+ /* ??? From the UA2011 document; overlaps BLK_INIT_QUAD_LDD_* */
+ case ASI_TWINX_P: /* Primary, twinx */
+ case ASI_TWINX_PL: /* Primary, twinx, LE */
+ case ASI_TWINX_S: /* Secondary, twinx */
+ case ASI_TWINX_SL: /* Secondary, twinx, LE */
+ /* Only stda allowed */
+ helper_raise_exception(env, TT_ILL_INSN);
+ return;
+ case ASI_DCACHE_DATA: /* D-cache data */
+ case ASI_DCACHE_TAG: /* D-cache tag access */
+ case ASI_ESTATE_ERROR_EN: /* E-cache error enable */
+ case ASI_AFSR: /* E-cache asynchronous fault status */
+ case ASI_AFAR: /* E-cache asynchronous fault address */
+ case ASI_EC_TAG_DATA: /* E-cache tag data */
+ case ASI_IC_INSTR: /* I-cache instruction access */
+ case ASI_IC_TAG: /* I-cache tag access */
+ case ASI_IC_PRE_DECODE: /* I-cache predecode */
+ case ASI_IC_NEXT_FIELD: /* I-cache LRU etc. */
+ case ASI_EC_W: /* E-cache tag */
+ case ASI_EC_R: /* E-cache tag */
return;
- case 0x51: /* I-MMU 8k TSB pointer, RO */
- case 0x52: /* I-MMU 64k TSB pointer, RO */
- case 0x56: /* I-MMU tag read, RO */
- case 0x59: /* D-MMU 8k TSB pointer, RO */
- case 0x5a: /* D-MMU 64k TSB pointer, RO */
- case 0x5b: /* D-MMU data pointer, RO */
- case 0x5e: /* D-MMU tag read, RO */
- case 0x48: /* Interrupt dispatch, RO */
- case 0x7f: /* Incoming interrupt vector, RO */
- case 0x82: /* Primary no-fault, RO */
- case 0x83: /* Secondary no-fault, RO */
- case 0x8a: /* Primary no-fault LE, RO */
- case 0x8b: /* Secondary no-fault LE, RO */
+ case ASI_IMMU_TSB_8KB_PTR: /* I-MMU 8k TSB pointer, RO */
+ case ASI_IMMU_TSB_64KB_PTR: /* I-MMU 64k TSB pointer, RO */
+ case ASI_ITLB_TAG_READ: /* I-MMU tag read, RO */
+ case ASI_DMMU_TSB_8KB_PTR: /* D-MMU 8k TSB pointer, RO */
+ case ASI_DMMU_TSB_64KB_PTR: /* D-MMU 64k TSB pointer, RO */
+ case ASI_DMMU_TSB_DIRECT_PTR: /* D-MMU data pointer, RO */
+ case ASI_DTLB_TAG_READ: /* D-MMU tag read, RO */
+ case ASI_INTR_DISPATCH_STAT: /* Interrupt dispatch, RO */
+ case ASI_INTR_R: /* Incoming interrupt vector, RO */
+ case ASI_PNF: /* Primary no-fault, RO */
+ case ASI_SNF: /* Secondary no-fault, RO */
+ case ASI_PNFL: /* Primary no-fault LE, RO */
+ case ASI_SNFL: /* Secondary no-fault LE, RO */
default:
cpu_unassigned_access(cs, addr, true, false, 1, size);
return;
@@ -2031,8 +2067,11 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
}
#endif /* CONFIG_USER_ONLY */
-void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
+/* 128-bit LDDA; result returned in QT0. */
+void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
{
+ uint64_t h, l;
+
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
@@ -2044,191 +2083,82 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
switch (asi) {
#if !defined(CONFIG_USER_ONLY)
- case 0x24: /* Nucleus quad LDD 128 bit atomic */
- case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
+ case ASI_TWINX_AIUP: /* As if user primary, twinx */
+ case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
helper_check_align(env, addr, 0xf);
- if (rd == 0) {
- env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
- if (asi == 0x2c) {
- bswap64s(&env->gregs[1]);
- }
- } else if (rd < 8) {
- env->gregs[rd] = cpu_ldq_nucleus(env, addr);
- env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
- if (asi == 0x2c) {
- bswap64s(&env->gregs[rd]);
- bswap64s(&env->gregs[rd + 1]);
- }
- } else {
- env->regwptr[rd - 8] = cpu_ldq_nucleus(env, addr);
- env->regwptr[rd + 1 - 8] = cpu_ldq_nucleus(env, addr + 8);
- if (asi == 0x2c) {
- bswap64s(&env->regwptr[rd - 8]);
- bswap64s(&env->regwptr[rd + 1 - 8]);
- }
- }
+ h = cpu_ldq_user(env, addr);
+ l = cpu_ldq_user(env, addr + 8);
break;
-#endif
- default:
- helper_check_align(env, addr, 0x3);
- if (rd == 0) {
- env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
- } else if (rd < 8) {
- env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
- env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
- } else {
- env->regwptr[rd - 8] = helper_ld_asi(env, addr, asi, 4, 0);
- env->regwptr[rd + 1 - 8] = helper_ld_asi(env, addr + 4, asi, 4, 0);
- }
+ case ASI_TWINX_AIUS: /* As if user secondary, twinx */
+ case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
+ helper_check_align(env, addr, 0xf);
+ h = cpu_ldq_user_secondary(env, addr);
+ l = cpu_ldq_user_secondary(env, addr + 8);
break;
- }
-}
-
-void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
- int rd)
-{
- unsigned int i;
- target_ulong val;
-
- helper_check_align(env, addr, 3);
- addr = asi_address_mask(env, asi, addr);
-
- switch (asi) {
- case 0xf0: /* UA2007/JPS1 Block load primary */
- case 0xf1: /* UA2007/JPS1 Block load secondary */
- case 0xf8: /* UA2007/JPS1 Block load primary LE */
- case 0xf9: /* UA2007/JPS1 Block load secondary LE */
- if (rd & 7) {
- helper_raise_exception(env, TT_ILL_INSN);
- return;
- }
- helper_check_align(env, addr, 0x3f);
- for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, 8, 0);
- }
- return;
-
- case 0x16: /* UA2007 Block load primary, user privilege */
- case 0x17: /* UA2007 Block load secondary, user privilege */
- case 0x1e: /* UA2007 Block load primary LE, user privilege */
- case 0x1f: /* UA2007 Block load secondary LE, user privilege */
- case 0x70: /* JPS1 Block load primary, user privilege */
- case 0x71: /* JPS1 Block load secondary, user privilege */
- case 0x78: /* JPS1 Block load primary LE, user privilege */
- case 0x79: /* JPS1 Block load secondary LE, user privilege */
- if (rd & 7) {
- helper_raise_exception(env, TT_ILL_INSN);
- return;
- }
- helper_check_align(env, addr, 0x3f);
- for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, 8, 0);
+ case ASI_TWINX_REAL: /* Real address, twinx */
+ case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
+ helper_check_align(env, addr, 0xf);
+ {
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
+ h = ldq_phys(cs->as, addr);
+ l = ldq_phys(cs->as, addr + 8);
}
- return;
-
- default:
break;
- }
-
- switch (size) {
- default:
- case 4:
- val = helper_ld_asi(env, addr, asi, size, 0);
- if (rd & 1) {
- env->fpr[rd / 2].l.lower = val;
- } else {
- env->fpr[rd / 2].l.upper = val;
+ case ASI_NUCLEUS_QUAD_LDD:
+ case ASI_NUCLEUS_QUAD_LDD_L:
+ case ASI_TWINX_N: /* Nucleus, twinx */
+ case ASI_TWINX_NL: /* Nucleus, twinx, LE */
+ helper_check_align(env, addr, 0xf);
+ h = cpu_ldq_nucleus(env, addr);
+ l = cpu_ldq_nucleus(env, addr + 8);
+ break;
+ case ASI_TWINX_S: /* Secondary, twinx */
+ case ASI_TWINX_SL: /* Secondary, twinx, LE */
+ if (!cpu_hypervisor_mode(env)) {
+ helper_check_align(env, addr, 0xf);
+ if (env->pstate & PS_PRIV) {
+ h = cpu_ldq_kernel_secondary(env, addr);
+ l = cpu_ldq_kernel_secondary(env, addr + 8);
+ } else {
+ h = cpu_ldq_user_secondary(env, addr);
+ l = cpu_ldq_user_secondary(env, addr + 8);
+ }
+ break;
}
+ /* fallthru */
+ case ASI_TWINX_P: /* Primary, twinx */
+ case ASI_TWINX_PL: /* Primary, twinx, LE */
+ helper_check_align(env, addr, 0xf);
+ h = cpu_ldq_data(env, addr);
+ l = cpu_ldq_data(env, addr + 8);
break;
- case 8:
- env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, size, 0);
- break;
- case 16:
- env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, 8, 0);
- env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
- break;
- }
-}
-
-void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
- int rd)
-{
- unsigned int i;
- target_ulong val;
-
- addr = asi_address_mask(env, asi, addr);
-
- switch (asi) {
- case 0xe0: /* UA2007/JPS1 Block commit store primary (cache flush) */
- case 0xe1: /* UA2007/JPS1 Block commit store secondary (cache flush) */
- case 0xf0: /* UA2007/JPS1 Block store primary */
- case 0xf1: /* UA2007/JPS1 Block store secondary */
- case 0xf8: /* UA2007/JPS1 Block store primary LE */
- case 0xf9: /* UA2007/JPS1 Block store secondary LE */
- if (rd & 7) {
- helper_raise_exception(env, TT_ILL_INSN);
- return;
- }
- helper_check_align(env, addr, 0x3f);
- for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, 8);
- }
-
- return;
- case 0x16: /* UA2007 Block load primary, user privilege */
- case 0x17: /* UA2007 Block load secondary, user privilege */
- case 0x1e: /* UA2007 Block load primary LE, user privilege */
- case 0x1f: /* UA2007 Block load secondary LE, user privilege */
- case 0x70: /* JPS1 Block store primary, user privilege */
- case 0x71: /* JPS1 Block store secondary, user privilege */
- case 0x78: /* JPS1 Block load primary LE, user privilege */
- case 0x79: /* JPS1 Block load secondary LE, user privilege */
- if (rd & 7) {
- helper_raise_exception(env, TT_ILL_INSN);
- return;
- }
- helper_check_align(env, addr, 0x3f);
- for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, 8);
- }
-
- return;
- case 0xd2: /* 16-bit floating point load primary */
- case 0xd3: /* 16-bit floating point load secondary */
- case 0xda: /* 16-bit floating point load primary, LE */
- case 0xdb: /* 16-bit floating point load secondary, LE */
- helper_check_align(env, addr, 1);
- /* Fall through */
- case 0xd0: /* 8-bit floating point load primary */
- case 0xd1: /* 8-bit floating point load secondary */
- case 0xd8: /* 8-bit floating point load primary, LE */
- case 0xd9: /* 8-bit floating point load secondary, LE */
- val = env->fpr[rd / 2].l.lower;
- helper_st_asi(env, addr, val, asi & 0x8d, ((asi & 2) >> 1) + 1);
- return;
+#else
+ case ASI_TWINX_P: /* Primary, twinx */
+ case ASI_TWINX_PL: /* Primary, twinx, LE */
+ case ASI_TWINX_S: /* Primary, twinx */
+ case ASI_TWINX_SL: /* Primary, twinx, LE */
+ /* ??? Should be available, but we need to implement
+ an atomic 128-bit load. */
+ helper_raise_exception(env, TT_PRIV_ACT);
+#endif
default:
- helper_check_align(env, addr, 3);
- break;
+ /* Non-twinx asi, so this is the legacy ldda insn, which
+ performs two word sized operations. */
+ /* ??? The UA2011 manual recommends emulating this with
+ a single 64-bit load. However, LE asis *are* treated
+ as two 32-bit loads individually byte swapped. */
+ helper_check_align(env, addr, 0x7);
+ QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, MO_UL);
+ QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, MO_UL);
+ return;
}
- switch (size) {
- default:
- case 4:
- if (rd & 1) {
- val = env->fpr[rd / 2].l.lower;
- } else {
- val = env->fpr[rd / 2].l.upper;
- }
- helper_st_asi(env, addr, val, asi, size);
- break;
- case 8:
- helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, size);
- break;
- case 16:
- helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, 8);
- helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, 8);
- break;
+ if (asi & 8) {
+ h = bswap64(h);
+ l = bswap64(l);
}
+ QT0.high = h;
+ QT0.low = l;
}
target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
@@ -2237,9 +2167,9 @@ target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
{
target_ulong ret;
- ret = helper_ld_asi(env, addr, asi, 8, 0);
+ ret = helper_ld_asi(env, addr, asi, MO_Q);
if (val2 == ret) {
- helper_st_asi(env, addr, val1, asi, 8);
+ helper_st_asi(env, addr, val1, asi, MO_Q);
}
return ret;
}
@@ -2252,10 +2182,10 @@ target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
target_ulong ret;
val2 &= 0xffffffffUL;
- ret = helper_ld_asi(env, addr, asi, 4, 0);
+ ret = helper_ld_asi(env, addr, asi, MO_UL);
ret &= 0xffffffffUL;
if (val2 == ret) {
- helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
+ helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, MO_UL);
}
return ret;
}