void OPPROTO op_st_asi_reg()
{
T0 += PARAM1;
- helper_st_asi(env->asi, PARAM2, PARAM3);
+ helper_st_asi(env->asi, PARAM2);
+}
+
+void OPPROTO op_ldstub_asi_reg() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ T0 += PARAM1;
+ helper_ld_asi(env->asi, 1, 0);
+ tmp = T1;
+ T1 = 0xff;
+ helper_st_asi(env->asi, 1);
+ T1 = tmp;
+}
+
+void OPPROTO op_swap_asi_reg() /* XXX: should be atomically */
+{
+ target_ulong tmp1, tmp2;
+
+ T0 += PARAM1;
+ tmp1 = T1;
+ helper_ld_asi(env->asi, 4, 0);
+ tmp2 = T1;
+ T1 = tmp1;
+ helper_st_asi(env->asi, 4);
+ T1 = tmp2;
+}
+
+void OPPROTO op_ldda_asi()
+{
+ helper_ld_asi(PARAM1, 8, 0);
+ T0 = T1 & 0xffffffffUL;
+ T1 >>= 32;
+}
+
+void OPPROTO op_ldda_asi_reg()
+{
+ T0 += PARAM1;
+ helper_ld_asi(env->asi, 8, 0);
+ T0 = T1 & 0xffffffffUL;
+ T1 >>= 32;
+}
+
+void OPPROTO op_stda_asi()
+{
+ T1 <<= 32;
+ T1 += T2 & 0xffffffffUL;
+ helper_st_asi(PARAM1, 8);
+}
+
+void OPPROTO op_stda_asi_reg()
+{
+ T0 += PARAM1;
+ T1 <<= 32;
+ T1 += T2 & 0xffffffffUL;
+ helper_st_asi(env->asi, 8);
+}
+
+void OPPROTO op_cas_asi() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ tmp = T1 & 0xffffffffUL;
+ helper_ld_asi(PARAM1, 4, 0);
+ if (tmp == T1) {
+ tmp = T1;
+ T1 = T2 & 0xffffffffUL;
+ helper_st_asi(PARAM1, 4);
+ T1 = tmp;
+ }
+ T1 &= 0xffffffffUL;
+}
+
+void OPPROTO op_cas_asi_reg() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ T0 += PARAM1;
+ tmp = T1 & 0xffffffffUL;
+ helper_ld_asi(env->asi, 4, 0);
+ if (tmp == T1) {
+ tmp = T1;
+ T1 = T2 & 0xffffffffUL;
+ helper_st_asi(env->asi, 4);
+ T1 = tmp;
+ }
+ T1 &= 0xffffffffUL;
+}
+
+void OPPROTO op_casx_asi() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ tmp = T1;
+ helper_ld_asi(PARAM1, 8, 0);
+ if (tmp == T1) {
+ tmp = T1;
+ T1 = T2;
+ helper_st_asi(PARAM1, 8);
+ T1 = tmp;
+ }
+}
+
+void OPPROTO op_casx_asi_reg() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ T0 += PARAM1;
+ tmp = T1;
+ helper_ld_asi(env->asi, 8, 0);
+ if (tmp == T1) {
+ tmp = T1;
+ T1 = T2;
+ helper_st_asi(env->asi, 8);
+ T1 = tmp;
+ }
}
#endif
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
void OPPROTO op_ld_asi()
{
helper_ld_asi(PARAM1, PARAM2, PARAM3);
void OPPROTO op_st_asi()
{
- helper_st_asi(PARAM1, PARAM2, PARAM3);
+ helper_st_asi(PARAM1, PARAM2);
}
+void OPPROTO op_ldstub_asi() /* XXX: should be atomically */
+{
+ target_ulong tmp;
+
+ helper_ld_asi(PARAM1, 1, 0);
+ tmp = T1;
+ T1 = 0xff;
+ helper_st_asi(PARAM1, 1);
+ T1 = tmp;
+}
+
+void OPPROTO op_swap_asi() /* XXX: should be atomically */
+{
+ target_ulong tmp1, tmp2;
+
+ tmp1 = T1;
+ helper_ld_asi(PARAM1, 4, 0);
+ tmp2 = T1;
+ T1 = tmp1;
+ helper_st_asi(PARAM1, 4);
+ T1 = tmp2;
+}
+#endif
+
#ifdef TARGET_SPARC64
// This function uses non-native bit order
#define GET_FIELD(X, FROM, TO) \
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
#endif
-#if defined(CONFIG_USER_ONLY)
-void helper_ld_asi(int asi, int size, int sign)
-{
-}
-
-void helper_st_asi(int asi, int size, int sign)
-{
-}
-#else
#ifndef TARGET_SPARC64
+#ifndef CONFIG_USER_ONLY
void helper_ld_asi(int asi, int size, int sign)
{
uint32_t ret = 0;
break;
}
break;
+ case 0xa: /* User data access */
+ switch(size) {
+ case 1:
+ ret = ldub_user(T0);
+ break;
+ case 2:
+ ret = lduw_user(T0 & ~1);
+ break;
+ default:
+ case 4:
+ ret = ldl_user(T0 & ~3);
+ break;
+ case 8:
+ ret = ldl_user(T0 & ~3);
+ T0 = ldl_user((T0 + 4) & ~3);
+ break;
+ }
+ break;
+ case 0xb: /* Supervisor data access */
+ switch(size) {
+ case 1:
+ ret = ldub_kernel(T0);
+ break;
+ case 2:
+ ret = lduw_kernel(T0 & ~1);
+ break;
+ default:
+ case 4:
+ ret = ldl_kernel(T0 & ~3);
+ break;
+ case 8:
+ ret = ldl_kernel(T0 & ~3);
+ T0 = ldl_kernel((T0 + 4) & ~3);
+ break;
+ }
+ break;
case 0xc: /* I-cache tag */
case 0xd: /* I-cache data */
case 0xe: /* D-cache tag */
ret = 0;
break;
}
- T1 = ret;
+ if (sign) {
+ switch(size) {
+ case 1:
+ T1 = (int8_t) ret;
+ case 2:
+ T1 = (int16_t) ret;
+ default:
+ T1 = ret;
+ break;
+ }
+ }
+ else
+ T1 = ret;
}
-void helper_st_asi(int asi, int size, int sign)
+void helper_st_asi(int asi, int size)
{
switch(asi) {
case 2: /* SuperSparc MXCC registers */
#endif
return;
}
+ case 0xa: /* User data access */
+ switch(size) {
+ case 1:
+ stb_user(T0, T1);
+ break;
+ case 2:
+ stw_user(T0 & ~1, T1);
+ break;
+ default:
+ case 4:
+ stl_user(T0 & ~3, T1);
+ break;
+ case 8:
+ stl_user(T0 & ~3, T1);
+ stl_user((T0 + 4) & ~3, T2);
+ break;
+ }
+ break;
+ case 0xb: /* Supervisor data access */
+ switch(size) {
+ case 1:
+ stb_kernel(T0, T1);
+ break;
+ case 2:
+ stw_kernel(T0 & ~1, T1);
+ break;
+ default:
+ case 4:
+ stl_kernel(T0 & ~3, T1);
+ break;
+ case 8:
+ stl_kernel(T0 & ~3, T1);
+ stl_kernel((T0 + 4) & ~3, T2);
+ break;
+ }
+ break;
case 0xc: /* I-cache tag */
case 0xd: /* I-cache data */
case 0xe: /* D-cache tag */
}
}
-#else
+#endif /* CONFIG_USER_ONLY */
+#else /* TARGET_SPARC64 */
+
+#ifdef CONFIG_USER_ONLY
+void helper_ld_asi(int asi, int size, int sign)
+{
+ uint64_t ret = 0;
+
+ if (asi < 0x80)
+ raise_exception(TT_PRIV_ACT);
+
+ switch (asi) {
+ case 0x80: // Primary
+ case 0x82: // Primary no-fault
+ case 0x88: // Primary LE
+ case 0x8a: // Primary no-fault LE
+ {
+ switch(size) {
+ case 1:
+ ret = ldub_raw(T0);
+ break;
+ case 2:
+ ret = lduw_raw(T0 & ~1);
+ break;
+ case 4:
+ ret = ldl_raw(T0 & ~3);
+ break;
+ default:
+ case 8:
+ ret = ldq_raw(T0 & ~7);
+ break;
+ }
+ }
+ break;
+ case 0x81: // Secondary
+ case 0x83: // Secondary no-fault
+ case 0x89: // Secondary LE
+ case 0x8b: // Secondary no-fault LE
+ // XXX
+ break;
+ default:
+ break;
+ }
+
+ /* 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
+ switch(size) {
+ case 2:
+ ret = bswap16(ret);
+ case 4:
+ ret = bswap32(ret);
+ case 8:
+ ret = bswap64(ret);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Convert to signed number */
+ if (sign) {
+ switch(size) {
+ case 1:
+ ret = (int8_t) ret;
+ case 2:
+ ret = (int16_t) ret;
+ case 4:
+ ret = (int32_t) ret;
+ default:
+ break;
+ }
+ }
+ T1 = ret;
+}
+
+void helper_st_asi(int asi, int size)
+{
+ if (asi < 0x80)
+ raise_exception(TT_PRIV_ACT);
+
+ /* Convert to little endian */
+ switch (asi) {
+ case 0x88: // Primary LE
+ case 0x89: // Secondary LE
+ switch(size) {
+ case 2:
+ T0 = bswap16(T0);
+ case 4:
+ T0 = bswap32(T0);
+ case 8:
+ T0 = bswap64(T0);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ switch(asi) {
+ case 0x80: // Primary
+ case 0x88: // Primary LE
+ {
+ switch(size) {
+ case 1:
+ stb_raw(T0, T1);
+ break;
+ case 2:
+ stw_raw(T0 & ~1, T1);
+ break;
+ case 4:
+ stl_raw(T0 & ~3, T1);
+ break;
+ case 8:
+ default:
+ stq_raw(T0 & ~7, T1);
+ break;
+ }
+ }
+ break;
+ case 0x81: // Secondary
+ case 0x89: // 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
+ default:
+ do_unassigned_access(T0, 1, 0, 1);
+ return;
+ }
+}
+
+#else /* CONFIG_USER_ONLY */
void helper_ld_asi(int asi, int size, int sign)
{
raise_exception(TT_PRIV_ACT);
switch (asi) {
+ case 0x10: // As if user primary
+ case 0x18: // As if user primary LE
+ case 0x80: // Primary
+ case 0x82: // Primary no-fault
+ case 0x88: // Primary LE
+ case 0x8a: // Primary no-fault LE
+ if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+ switch(size) {
+ case 1:
+ ret = ldub_kernel(T0);
+ break;
+ case 2:
+ ret = lduw_kernel(T0 & ~1);
+ break;
+ case 4:
+ ret = ldl_kernel(T0 & ~3);
+ break;
+ default:
+ case 8:
+ ret = ldq_kernel(T0 & ~7);
+ break;
+ }
+ } else {
+ switch(size) {
+ case 1:
+ ret = ldub_user(T0);
+ break;
+ case 2:
+ ret = lduw_user(T0 & ~1);
+ break;
+ case 4:
+ ret = ldl_user(T0 & ~3);
+ break;
+ default:
+ case 8:
+ ret = ldq_user(T0 & ~7);
+ break;
+ }
+ }
+ break;
case 0x14: // Bypass
case 0x15: // Bypass, non-cacheable
+ case 0x1c: // Bypass LE
+ case 0x1d: // Bypass, non-cacheable LE
{
switch(size) {
case 1:
}
case 0x04: // Nucleus
case 0x0c: // Nucleus Little Endian (LE)
- 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 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
case 0x24: // Nucleus quad LDD 128 bit atomic
case 0x2c: // Nucleus quad LDD 128 bit atomic
case 0x4a: // UPA config
- case 0x82: // Primary no-fault
+ case 0x81: // Secondary
case 0x83: // Secondary no-fault
- case 0x88: // Primary LE
case 0x89: // Secondary LE
- case 0x8a: // Primary no-fault LE
case 0x8b: // Secondary no-fault LE
// XXX
break;
ret = 0;
break;
}
+
+ /* 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 0x8a: // Primary no-fault LE
+ case 0x8b: // Secondary no-fault LE
+ switch(size) {
+ case 2:
+ ret = bswap16(ret);
+ case 4:
+ ret = bswap32(ret);
+ case 8:
+ ret = bswap64(ret);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Convert to signed number */
+ if (sign) {
+ switch(size) {
+ case 1:
+ ret = (int8_t) ret;
+ case 2:
+ ret = (int16_t) ret;
+ case 4:
+ ret = (int32_t) ret;
+ default:
+ break;
+ }
+ }
T1 = ret;
}
-void helper_st_asi(int asi, int size, int sign)
+void helper_st_asi(int asi, int size)
{
if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
raise_exception(TT_PRIV_ACT);
+ /* 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 0x81: // Secondary
+ case 0x88: // Primary LE
+ case 0x89: // Secondary LE
+ switch(size) {
+ case 2:
+ T0 = bswap16(T0);
+ case 4:
+ T0 = bswap32(T0);
+ case 8:
+ T0 = bswap64(T0);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
switch(asi) {
+ case 0x10: // As if user primary
+ case 0x18: // As if user primary LE
+ case 0x80: // Primary
+ case 0x88: // Primary LE
+ if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
+ switch(size) {
+ case 1:
+ stb_kernel(T0, T1);
+ break;
+ case 2:
+ stw_kernel(T0 & ~1, T1);
+ break;
+ case 4:
+ stl_kernel(T0 & ~3, T1);
+ break;
+ case 8:
+ default:
+ stq_kernel(T0 & ~7, T1);
+ break;
+ }
+ } else {
+ switch(size) {
+ case 1:
+ stb_user(T0, T1);
+ break;
+ case 2:
+ stw_user(T0 & ~1, T1);
+ break;
+ case 4:
+ stl_user(T0 & ~3, T1);
+ break;
+ case 8:
+ default:
+ stq_user(T0 & ~7, T1);
+ break;
+ }
+ }
+ break;
case 0x14: // Bypass
case 0x15: // Bypass, non-cacheable
+ case 0x1c: // Bypass LE
+ case 0x1d: // Bypass, non-cacheable LE
{
switch(size) {
case 1:
return;
case 0x04: // Nucleus
case 0x0c: // Nucleus Little Endian (LE)
- 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 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
case 0x24: // Nucleus quad LDD 128 bit atomic
case 0x2c: // Nucleus quad LDD 128 bit atomic
case 0x4a: // UPA config
- case 0x88: // Primary LE
case 0x89: // Secondary LE
// XXX
return;
return;
}
}
-#endif
-#endif /* !CONFIG_USER_ONLY */
+#endif /* CONFIG_USER_ONLY */
+#endif /* TARGET_SPARC64 */
#ifndef TARGET_SPARC64
void helper_rett()
#endif
#endif
-#ifdef TARGET_SPARC64
-// 'a' versions allowed to user depending on asi
-#if defined(CONFIG_USER_ONLY)
+/* moves */
+#ifdef CONFIG_USER_ONLY
#define supervisor(dc) 0
+#ifdef TARGET_SPARC64
#define hypervisor(dc) 0
+#endif
#define gen_op_ldst(name) gen_op_##name##_raw()
-#define OP_LD_TABLE(width) \
- static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
- { \
- int asi, offset; \
- \
- if (IS_IMM) { \
- offset = GET_FIELD(insn, 25, 31); \
- if (is_ld) \
- gen_op_ld_asi_reg(offset, size, sign); \
- else \
- gen_op_st_asi_reg(offset, size, sign); \
- return; \
- } \
- asi = GET_FIELD(insn, 19, 26); \
- switch (asi) { \
- case 0x80: /* Primary address space */ \
- gen_op_##width##_raw(); \
- break; \
- case 0x82: /* Primary address space, non-faulting load */ \
- gen_op_##width##_raw(); \
- break; \
- default: \
- break; \
- } \
- }
-
#else
+#define supervisor(dc) (dc->mem_idx == 1)
+#ifdef TARGET_SPARC64
+#define hypervisor(dc) (dc->mem_idx == 2)
+#endif
#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
#define OP_LD_TABLE(width) \
static GenOpFunc * const gen_op_##width[] = { \
&gen_op_##width##_user, \
&gen_op_##width##_kernel, \
- }; \
- \
- static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
- { \
- int asi, offset; \
- \
- if (IS_IMM) { \
- offset = GET_FIELD(insn, 25, 31); \
- if (is_ld) \
- gen_op_ld_asi_reg(offset, size, sign); \
- else \
- gen_op_st_asi_reg(offset, size, sign); \
- return; \
- } \
- asi = GET_FIELD(insn, 19, 26); \
- if (is_ld) \
- gen_op_ld_asi(asi, size, sign); \
- else \
- gen_op_st_asi(asi, size, sign); \
- }
-
-#define supervisor(dc) (dc->mem_idx == 1)
-#define hypervisor(dc) (dc->mem_idx == 2)
-#endif
-#else
-#if defined(CONFIG_USER_ONLY)
-#define gen_op_ldst(name) gen_op_##name##_raw()
-#define OP_LD_TABLE(width)
-#define supervisor(dc) 0
-#else
-#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
-#define OP_LD_TABLE(width) \
-static GenOpFunc * const gen_op_##width[] = { \
- &gen_op_##width##_user, \
- &gen_op_##width##_kernel, \
-}; \
- \
-static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
-{ \
- int asi; \
- \
- asi = GET_FIELD(insn, 19, 26); \
- switch (asi) { \
- case 10: /* User data access */ \
- gen_op_##width##_user(); \
- break; \
- case 11: /* Supervisor data access */ \
- gen_op_##width##_kernel(); \
- break; \
- case 0x20 ... 0x2f: /* MMU passthrough */ \
- if (is_ld) \
- gen_op_ld_asi(asi, size, sign); \
- else \
- gen_op_st_asi(asi, size, sign); \
- break; \
- default: \
- if (is_ld) \
- gen_op_ld_asi(asi, size, sign); \
- else \
- gen_op_st_asi(asi, size, sign); \
- break; \
- } \
-}
-
-#define supervisor(dc) (dc->mem_idx == 1)
-#endif
+ };
#endif
+#ifndef CONFIG_USER_ONLY
OP_LD_TABLE(ld);
OP_LD_TABLE(st);
OP_LD_TABLE(ldub);
OP_LD_TABLE(ldsw);
OP_LD_TABLE(ldx);
OP_LD_TABLE(stx);
-OP_LD_TABLE(cas);
-OP_LD_TABLE(casx);
+#endif
+#endif
+
+/* asi moves */
+#ifdef TARGET_SPARC64
+static inline void gen_ld_asi(int insn, int size, int sign)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_ld_asi_reg(offset, size, sign);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ld_asi(asi, size, sign);
+ }
+}
+
+static inline void gen_st_asi(int insn, int size)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_st_asi_reg(offset, size);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_st_asi(asi, size);
+ }
+}
+
+static inline void gen_swap_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_swap_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_swap_asi(asi);
+ }
+}
+
+static inline void gen_ldstub_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_ldstub_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ldstub_asi(asi);
+ }
+}
+
+static inline void gen_ldda_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_ldda_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ldda_asi(asi);
+ }
+}
+
+static inline void gen_stda_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_stda_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_stda_asi(asi);
+ }
+}
+
+static inline void gen_cas_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_cas_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_cas_asi(asi);
+ }
+}
+
+static inline void gen_casx_asi(int insn)
+{
+ int asi, offset;
+
+ if (IS_IMM) {
+ offset = GET_FIELD(insn, 25, 31);
+ gen_op_casx_asi_reg(offset);
+ } else {
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_casx_asi(asi);
+ }
+}
+
+#elif !defined(CONFIG_USER_ONLY)
+
+static inline void gen_ld_asi(int insn, int size, int sign)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ld_asi(asi, size, sign);
+}
+
+static inline void gen_st_asi(int insn, int size)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_st_asi(asi, size);
+}
+
+static inline void gen_ldstub_asi(int insn)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ldstub_asi(asi);
+}
+
+static inline void gen_swap_asi(int insn)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_swap_asi(asi);
+}
+
+static inline void gen_ldda_asi(int insn)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_ld_asi(asi, 8, 0);
+}
+
+static inline void gen_stda_asi(int insn)
+{
+ int asi;
+
+ asi = GET_FIELD(insn, 19, 26);
+ gen_op_st_asi(asi, 8);
+}
#endif
static inline void gen_movl_imm_TN(int reg, uint32_t imm)
rs1 = GET_FIELD(insn, 13, 17);
save_state(dc);
gen_movl_reg_T0(rs1);
- if (IS_IMM) { /* immediate */
+ if (xop == 0x3c || xop == 0x3e)
+ {
+ rs2 = GET_FIELD(insn, 27, 31);
+ gen_movl_reg_T1(rs2);
+ }
+ else if (IS_IMM) { /* immediate */
rs2 = GET_FIELDs(insn, 19, 31);
#if defined(OPTIM)
if (rs2 != 0) {
goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
-#ifdef CONFIG_USER_ONLY
+#elif CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_lda(insn, 1, 4, 0);
-#else
-#ifdef CONFIG_USER_ONLY
- gen_op_check_align_T0_3();
-#endif
- gen_op_lduwa(insn, 1, 4, 0);
-#endif
+ gen_ld_asi(insn, 4, 0);
break;
case 0x11: /* load unsigned byte alternate */
#ifndef TARGET_SPARC64
if (!supervisor(dc))
goto priv_insn;
#endif
- gen_op_lduba(insn, 1, 1, 0);
+ gen_ld_asi(insn, 1, 0);
break;
case 0x12: /* load unsigned halfword alternate */
#ifndef TARGET_SPARC64
goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
-#endif
-#ifdef CONFIG_USER_ONLY
+#elif CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
- gen_op_lduha(insn, 1, 2, 0);
+ gen_ld_asi(insn, 2, 0);
break;
case 0x13: /* load double word alternate */
#ifndef TARGET_SPARC64
if (rd & 1)
goto illegal_insn;
gen_op_check_align_T0_7();
- gen_op_ldda(insn, 1, 8, 0);
+ gen_ldda_asi(insn);
gen_movl_T0_reg(rd + 1);
break;
case 0x19: /* load signed byte alternate */
if (!supervisor(dc))
goto priv_insn;
#endif
- gen_op_ldsba(insn, 1, 1, 1);
+ gen_ld_asi(insn, 1, 1);
break;
case 0x1a: /* load signed halfword alternate */
#ifndef TARGET_SPARC64
goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
-#endif
-#ifdef CONFIG_USER_ONLY
+#elif CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
- gen_op_ldsha(insn, 1, 2 ,1);
+ gen_ld_asi(insn, 2, 1);
break;
case 0x1d: /* ldstuba -- XXX: should be atomically */
#ifndef TARGET_SPARC64
if (!supervisor(dc))
goto priv_insn;
#endif
- gen_op_ldstuba(insn, 1, 1, 0);
+ gen_ldstub_asi(insn);
break;
case 0x1f: /* swap reg with alt. memory. Also atomically */
#ifndef TARGET_SPARC64
goto illegal_insn;
if (!supervisor(dc))
goto priv_insn;
-#endif
- gen_movl_reg_T1(rd);
-#ifdef CONFIG_USER_ONLY
+#elif CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_swapa(insn, 1, 4, 0);
+ gen_movl_reg_T1(rd);
+ gen_swap_asi(insn);
break;
#ifndef TARGET_SPARC64
case 0x31: /* ldcsr */
case 0x33: /* lddc */
goto ncp_insn;
- /* avoid warnings */
- (void) &gen_op_stfa;
- (void) &gen_op_stdfa;
- (void) &gen_op_ldfa;
- (void) &gen_op_lddfa;
-#else
- (void) &gen_op_lda;
-#if !defined(CONFIG_USER_ONLY)
- (void) &gen_op_cas;
- (void) &gen_op_casx;
-#endif
#endif
#endif
#ifdef TARGET_SPARC64
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_ldswa(insn, 1, 4, 1);
+ gen_ld_asi(insn, 4, 1);
break;
case 0x1b: /* V9 ldxa */
gen_op_check_align_T0_7();
- gen_op_ldxa(insn, 1, 8, 0);
+ gen_ld_asi(insn, 8, 0);
break;
case 0x2d: /* V9 prefetch, no effect */
goto skip_move;
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_ldfa(insn, 1, 8, 0); // XXX
- break;
+ gen_ld_asi(insn, 8, 0); // XXX
+ goto skip_move;
case 0x33: /* V9 lddfa */
gen_op_check_align_T0_7();
- gen_op_lddfa(insn, 1, 8, 0); // XXX
-
- break;
+ gen_ld_asi(insn, 8, 0); // XXX
+ goto skip_move;
case 0x3d: /* V9 prefetcha, no effect */
goto skip_move;
case 0x32: /* V9 ldqfa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_sta(insn, 0, 4, 0);
+ gen_st_asi(insn, 4);
break;
case 0x15:
#ifndef TARGET_SPARC64
if (!supervisor(dc))
goto priv_insn;
#endif
- gen_op_stba(insn, 0, 1, 0);
+ gen_st_asi(insn, 1);
break;
case 0x16:
#ifndef TARGET_SPARC64
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_1();
#endif
- gen_op_stha(insn, 0, 2, 0);
+ gen_st_asi(insn, 2);
break;
case 0x17:
#ifndef TARGET_SPARC64
gen_op_check_align_T0_7();
flush_T2(dc);
gen_movl_reg_T2(rd + 1);
- gen_op_stda(insn, 0, 8, 0);
+ gen_stda_asi(insn);
break;
#endif
#ifdef TARGET_SPARC64
break;
case 0x1e: /* V9 stxa */
gen_op_check_align_T0_7();
- gen_op_stxa(insn, 0, 8, 0); // XXX
+ gen_st_asi(insn, 8);
break;
#endif
default:
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_stfa(insn, 0, 0, 0); // XXX
+ gen_st_asi(insn, 0); // XXX
break;
case 0x37: /* V9 stdfa */
gen_op_check_align_T0_7();
- gen_op_stdfa(insn, 0, 0, 0); // XXX
+ gen_st_asi(insn, 0); // XXX
break;
case 0x3c: /* V9 casa */
#ifdef CONFIG_USER_ONLY
gen_op_check_align_T0_3();
#endif
- gen_op_casa(insn, 0, 4, 0); // XXX
+ flush_T2(dc);
+ gen_movl_reg_T2(rd);
+ gen_cas_asi(insn);
+ gen_movl_T1_reg(rd);
break;
case 0x3e: /* V9 casxa */
gen_op_check_align_T0_7();
- gen_op_casxa(insn, 0, 8, 0); // XXX
+ flush_T2(dc);
+ gen_movl_reg_T2(rd);
+ gen_casx_asi(insn);
+ gen_movl_T1_reg(rd);
break;
case 0x36: /* V9 stqfa */
goto nfpu_insn;