target-arm queue
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABCAAGBQJR5CARAAoJEDwlJe0UNgze2MYP/RzOLWiGX7Y4byy0XUYKupXW H4H43HVjt98V/PrJl/u3MA4mjI7EjgnO/WmWtqdj+GpCWJ47lCrYjdIH50IeG4Ug /ZR8GuVBvPmQeUDNL0as8c/aHJ4WCnAM8z08FKkjN1YWfamBgOL3CNdSZAxqORw6 xnHnmGbTqX5JfW78k9R6mSP5z1VRoOzXyMLSRso5ySzH+sLlAGCXYITaTGqDxoNu MnJZsa+E6bfOURVI0rodqwS8N2Pe6VBHWXQt7Jrll5fMGxvhbqteRU+pzXpzU9H/ 3oeROVLL3kK6n22AXmGgjszPQ2Dus0NhPqRiMml98SnsF5+4d9e/dVtVYJZkuusT 6uxrOIBu6OEdpl6siBuuZMNSVf4hXMPCVgIxi0pQpRt145VjRGcbzzEBII8ZRK8z tfzzwDW4m0K/UqV2D9RxG/86DEh0pBb0YvXoNFCMlbg1hKpbH/E7kGedRScffApE Pygo6lKcf3b4rpJCvNmGQOz8PS0mfqqUdasgyCeTw0QOgvHnbS6WsnEng/12PpTt 7AFILRngiwds7VUbnN0jtoEYerJmEoU8DTZWsehArcO/duVZE58FoSxMweNnLhDr gZJRMqEEq0ZWbqmDFcJXcvArtgfBiTHySWcLx4KuWL6GL0Oe4efR5ABMmUdCv7+5 ELiTRIKbagL03/sgUPQ1 =PySE -----END PGP SIGNATURE----- Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20130715-1' into staging target-arm queue # gpg: Signature made Mon 15 Jul 2013 11:15:13 AM CDT using RSA key ID 14360CDE # gpg: Can't check signature: public key not found # By Mans Rullgard (3) and others # Via Peter Maydell * pmaydell/tags/pull-target-arm-20130715-1: target-arm: Avoid g_hash_table_get_keys() target-arm: avoid undefined behaviour when writing TTBCR target-arm/helper.c: Allow const opaques in arm CP target-arm/helper.c: Implement MIDR aliases target-arm/helper.c: OMAP/StrongARM cp15 crn=0 cleanup target-arm: explicitly decode SEVL instruction target-arm: implement LDA/STL instructions target-arm: add feature flag for ARMv8 Message-id: 1373905022-27735-1-git-send-email-peter.maydell@linaro.org Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
ab4e1589f0
|
@ -157,6 +157,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
|
|
||||||
/* Some features automatically imply others: */
|
/* Some features automatically imply others: */
|
||||||
|
if (arm_feature(env, ARM_FEATURE_V8)) {
|
||||||
|
set_feature(env, ARM_FEATURE_V7);
|
||||||
|
set_feature(env, ARM_FEATURE_ARM_DIV);
|
||||||
|
set_feature(env, ARM_FEATURE_LPAE);
|
||||||
|
}
|
||||||
if (arm_feature(env, ARM_FEATURE_V7)) {
|
if (arm_feature(env, ARM_FEATURE_V7)) {
|
||||||
set_feature(env, ARM_FEATURE_VAPA);
|
set_feature(env, ARM_FEATURE_VAPA);
|
||||||
set_feature(env, ARM_FEATURE_THUMB2);
|
set_feature(env, ARM_FEATURE_THUMB2);
|
||||||
|
@ -744,7 +749,7 @@ static void pxa270c5_initfn(Object *obj)
|
||||||
static void arm_any_initfn(Object *obj)
|
static void arm_any_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(obj);
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_V7);
|
set_feature(&cpu->env, ARM_FEATURE_V8);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_VFP4);
|
set_feature(&cpu->env, ARM_FEATURE_VFP4);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
set_feature(&cpu->env, ARM_FEATURE_VFP_FP16);
|
||||||
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
set_feature(&cpu->env, ARM_FEATURE_NEON);
|
||||||
|
|
|
@ -387,6 +387,7 @@ enum arm_features {
|
||||||
ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
|
ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
|
||||||
ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
|
ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
|
||||||
ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
|
ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
|
||||||
|
ARM_FEATURE_V8,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int arm_feature(CPUARMState *env, int feature)
|
static inline int arm_feature(CPUARMState *env, int feature)
|
||||||
|
|
|
@ -222,15 +222,23 @@ static gint cpreg_key_compare(gconstpointer a, gconstpointer b)
|
||||||
return aidx - bidx;
|
return aidx - bidx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cpreg_make_keylist(gpointer key, gpointer value, gpointer udata)
|
||||||
|
{
|
||||||
|
GList **plist = udata;
|
||||||
|
|
||||||
|
*plist = g_list_prepend(*plist, key);
|
||||||
|
}
|
||||||
|
|
||||||
void init_cpreg_list(ARMCPU *cpu)
|
void init_cpreg_list(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
/* Initialise the cpreg_tuples[] array based on the cp_regs hash.
|
/* Initialise the cpreg_tuples[] array based on the cp_regs hash.
|
||||||
* Note that we require cpreg_tuples[] to be sorted by key ID.
|
* Note that we require cpreg_tuples[] to be sorted by key ID.
|
||||||
*/
|
*/
|
||||||
GList *keys;
|
GList *keys = NULL;
|
||||||
int arraylen;
|
int arraylen;
|
||||||
|
|
||||||
keys = g_hash_table_get_keys(cpu->cp_regs);
|
g_hash_table_foreach(cpu->cp_regs, cpreg_make_keylist, &keys);
|
||||||
|
|
||||||
keys = g_list_sort(keys, cpreg_key_compare);
|
keys = g_list_sort(keys, cpreg_key_compare);
|
||||||
|
|
||||||
cpu->cpreg_array_len = 0;
|
cpu->cpreg_array_len = 0;
|
||||||
|
@ -891,6 +899,8 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = {
|
||||||
static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
uint64_t value)
|
uint64_t value)
|
||||||
{
|
{
|
||||||
|
int maskshift = extract32(value, 0, 3);
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_LPAE)) {
|
if (arm_feature(env, ARM_FEATURE_LPAE)) {
|
||||||
value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
|
value &= ~((7 << 19) | (3 << 14) | (0xf << 3));
|
||||||
} else {
|
} else {
|
||||||
|
@ -902,8 +912,8 @@ static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
* and the c2_mask and c2_base_mask values are meaningless.
|
* and the c2_mask and c2_base_mask values are meaningless.
|
||||||
*/
|
*/
|
||||||
env->cp15.c2_control = value;
|
env->cp15.c2_control = value;
|
||||||
env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> value);
|
env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift);
|
||||||
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> value);
|
env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1378,9 +1388,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) {
|
if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) {
|
||||||
define_arm_cp_regs(cpu, dummy_c15_cp_reginfo);
|
define_arm_cp_regs(cpu, dummy_c15_cp_reginfo);
|
||||||
}
|
}
|
||||||
if (arm_feature(env, ARM_FEATURE_MPIDR)) {
|
|
||||||
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
|
|
||||||
}
|
|
||||||
if (arm_feature(env, ARM_FEATURE_LPAE)) {
|
if (arm_feature(env, ARM_FEATURE_LPAE)) {
|
||||||
define_arm_cp_regs(cpu, lpae_cp_reginfo);
|
define_arm_cp_regs(cpu, lpae_cp_reginfo);
|
||||||
}
|
}
|
||||||
|
@ -1393,12 +1400,17 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
/* Note that the MIDR isn't a simple constant register because
|
/* Note that the MIDR isn't a simple constant register because
|
||||||
* of the TI925 behaviour where writes to another register can
|
* of the TI925 behaviour where writes to another register can
|
||||||
* cause the MIDR value to change.
|
* cause the MIDR value to change.
|
||||||
|
*
|
||||||
|
* Unimplemented registers in the c15 0 0 0 space default to
|
||||||
|
* MIDR. Define MIDR first as this entire space, then CTR, TCMTR
|
||||||
|
* and friends override accordingly.
|
||||||
*/
|
*/
|
||||||
{ .name = "MIDR",
|
{ .name = "MIDR",
|
||||||
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0,
|
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = CP_ANY,
|
||||||
.access = PL1_R, .resetvalue = cpu->midr,
|
.access = PL1_R, .resetvalue = cpu->midr,
|
||||||
.writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
|
.writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid) },
|
.fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
|
||||||
|
.type = ARM_CP_OVERRIDE },
|
||||||
{ .name = "CTR",
|
{ .name = "CTR",
|
||||||
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
|
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
|
||||||
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
|
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
|
||||||
|
@ -1435,21 +1447,20 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
arm_feature(env, ARM_FEATURE_STRONGARM)) {
|
arm_feature(env, ARM_FEATURE_STRONGARM)) {
|
||||||
ARMCPRegInfo *r;
|
ARMCPRegInfo *r;
|
||||||
/* Register the blanket "writes ignored" value first to cover the
|
/* Register the blanket "writes ignored" value first to cover the
|
||||||
* whole space. Then define the specific ID registers, but update
|
* whole space. Then update the specific ID registers to allow write
|
||||||
* their access field to allow write access, so that they ignore
|
* access, so that they ignore writes rather than causing them to
|
||||||
* writes rather than causing them to UNDEF.
|
* UNDEF.
|
||||||
*/
|
*/
|
||||||
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
|
define_one_arm_cp_reg(cpu, &crn0_wi_reginfo);
|
||||||
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
|
for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) {
|
||||||
r->access = PL1_RW;
|
r->access = PL1_RW;
|
||||||
define_one_arm_cp_reg(cpu, r);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* Just register the standard ID registers (read-only, meaning
|
|
||||||
* that writes will UNDEF).
|
|
||||||
*/
|
|
||||||
define_arm_cp_regs(cpu, id_cp_reginfo);
|
|
||||||
}
|
}
|
||||||
|
define_arm_cp_regs(cpu, id_cp_reginfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arm_feature(env, ARM_FEATURE_MPIDR)) {
|
||||||
|
define_arm_cp_regs(cpu, mpidr_cp_reginfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_AUXCR)) {
|
if (arm_feature(env, ARM_FEATURE_AUXCR)) {
|
||||||
|
@ -1607,7 +1618,9 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
|
||||||
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
|
ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
|
||||||
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
|
int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
|
||||||
*key = ENCODE_CP_REG(r->cp, is64, r->crn, crm, opc1, opc2);
|
*key = ENCODE_CP_REG(r->cp, is64, r->crn, crm, opc1, opc2);
|
||||||
r2->opaque = opaque;
|
if (opaque) {
|
||||||
|
r2->opaque = opaque;
|
||||||
|
}
|
||||||
/* Make sure reginfo passed to helpers for wildcarded regs
|
/* Make sure reginfo passed to helpers for wildcarded regs
|
||||||
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
|
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
|
#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
|
||||||
#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
|
#define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
|
||||||
#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
|
#define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
|
||||||
|
#define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
|
||||||
|
|
||||||
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
|
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
|
||||||
|
|
||||||
|
@ -3500,7 +3501,8 @@ static void gen_nop_hint(DisasContext *s, int val)
|
||||||
break;
|
break;
|
||||||
case 2: /* wfe */
|
case 2: /* wfe */
|
||||||
case 4: /* sev */
|
case 4: /* sev */
|
||||||
/* TODO: Implement SEV and WFE. May help SMP performance. */
|
case 5: /* sevl */
|
||||||
|
/* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
|
||||||
default: /* nop */
|
default: /* nop */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7273,14 +7275,72 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
|
||||||
rd = (insn >> 12) & 0xf;
|
rd = (insn >> 12) & 0xf;
|
||||||
if (insn & (1 << 23)) {
|
if (insn & (1 << 23)) {
|
||||||
/* load/store exclusive */
|
/* load/store exclusive */
|
||||||
|
int op2 = (insn >> 8) & 3;
|
||||||
op1 = (insn >> 21) & 0x3;
|
op1 = (insn >> 21) & 0x3;
|
||||||
if (op1)
|
|
||||||
ARCH(6K);
|
switch (op2) {
|
||||||
else
|
case 0: /* lda/stl */
|
||||||
ARCH(6);
|
if (op1 == 1) {
|
||||||
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
ARCH(8);
|
||||||
|
break;
|
||||||
|
case 1: /* reserved */
|
||||||
|
goto illegal_op;
|
||||||
|
case 2: /* ldaex/stlex */
|
||||||
|
ARCH(8);
|
||||||
|
break;
|
||||||
|
case 3: /* ldrex/strex */
|
||||||
|
if (op1) {
|
||||||
|
ARCH(6K);
|
||||||
|
} else {
|
||||||
|
ARCH(6);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
addr = tcg_temp_local_new_i32();
|
addr = tcg_temp_local_new_i32();
|
||||||
load_reg_var(s, addr, rn);
|
load_reg_var(s, addr, rn);
|
||||||
if (insn & (1 << 20)) {
|
|
||||||
|
/* Since the emulation does not have barriers,
|
||||||
|
the acquire/release semantics need no special
|
||||||
|
handling */
|
||||||
|
if (op2 == 0) {
|
||||||
|
if (insn & (1 << 20)) {
|
||||||
|
tmp = tcg_temp_new_i32();
|
||||||
|
switch (op1) {
|
||||||
|
case 0: /* lda */
|
||||||
|
tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 2: /* ldab */
|
||||||
|
tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 3: /* ldah */
|
||||||
|
tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
store_reg(s, rd, tmp);
|
||||||
|
} else {
|
||||||
|
rm = insn & 0xf;
|
||||||
|
tmp = load_reg(s, rm);
|
||||||
|
switch (op1) {
|
||||||
|
case 0: /* stl */
|
||||||
|
tcg_gen_qemu_st32(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 2: /* stlb */
|
||||||
|
tcg_gen_qemu_st8(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 3: /* stlh */
|
||||||
|
tcg_gen_qemu_st16(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
tcg_temp_free_i32(tmp);
|
||||||
|
}
|
||||||
|
} else if (insn & (1 << 20)) {
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
case 0: /* ldrex */
|
case 0: /* ldrex */
|
||||||
gen_load_exclusive(s, rd, 15, addr, 2);
|
gen_load_exclusive(s, rd, 15, addr, 2);
|
||||||
|
@ -8125,7 +8185,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||||
gen_store_exclusive(s, rd, rs, 15, addr, 2);
|
gen_store_exclusive(s, rd, rs, 15, addr, 2);
|
||||||
}
|
}
|
||||||
tcg_temp_free_i32(addr);
|
tcg_temp_free_i32(addr);
|
||||||
} else if ((insn & (1 << 6)) == 0) {
|
} else if ((insn & (7 << 5)) == 0) {
|
||||||
/* Table Branch. */
|
/* Table Branch. */
|
||||||
if (rn == 15) {
|
if (rn == 15) {
|
||||||
addr = tcg_temp_new_i32();
|
addr = tcg_temp_new_i32();
|
||||||
|
@ -8151,15 +8211,66 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||||
tcg_gen_addi_i32(tmp, tmp, s->pc);
|
tcg_gen_addi_i32(tmp, tmp, s->pc);
|
||||||
store_reg(s, 15, tmp);
|
store_reg(s, 15, tmp);
|
||||||
} else {
|
} else {
|
||||||
/* Load/store exclusive byte/halfword/doubleword. */
|
int op2 = (insn >> 6) & 0x3;
|
||||||
ARCH(7);
|
|
||||||
op = (insn >> 4) & 0x3;
|
op = (insn >> 4) & 0x3;
|
||||||
if (op == 2) {
|
switch (op2) {
|
||||||
|
case 0:
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
|
case 1:
|
||||||
|
/* Load/store exclusive byte/halfword/doubleword */
|
||||||
|
if (op == 2) {
|
||||||
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
ARCH(7);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* Load-acquire/store-release */
|
||||||
|
if (op == 3) {
|
||||||
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
/* Fall through */
|
||||||
|
case 3:
|
||||||
|
/* Load-acquire/store-release exclusive */
|
||||||
|
ARCH(8);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
addr = tcg_temp_local_new_i32();
|
addr = tcg_temp_local_new_i32();
|
||||||
load_reg_var(s, addr, rn);
|
load_reg_var(s, addr, rn);
|
||||||
if (insn & (1 << 20)) {
|
if (!(op2 & 1)) {
|
||||||
|
if (insn & (1 << 20)) {
|
||||||
|
tmp = tcg_temp_new_i32();
|
||||||
|
switch (op) {
|
||||||
|
case 0: /* ldab */
|
||||||
|
tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 1: /* ldah */
|
||||||
|
tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 2: /* lda */
|
||||||
|
tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
store_reg(s, rs, tmp);
|
||||||
|
} else {
|
||||||
|
tmp = load_reg(s, rs);
|
||||||
|
switch (op) {
|
||||||
|
case 0: /* stlb */
|
||||||
|
tcg_gen_qemu_st8(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 1: /* stlh */
|
||||||
|
tcg_gen_qemu_st16(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
case 2: /* stl */
|
||||||
|
tcg_gen_qemu_st32(tmp, addr, IS_USER(s));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
tcg_temp_free_i32(tmp);
|
||||||
|
}
|
||||||
|
} else if (insn & (1 << 20)) {
|
||||||
gen_load_exclusive(s, rs, rd, addr, op);
|
gen_load_exclusive(s, rs, rd, addr, op);
|
||||||
} else {
|
} else {
|
||||||
gen_store_exclusive(s, rm, rs, rd, addr, op);
|
gen_store_exclusive(s, rm, rs, rd, addr, op);
|
||||||
|
|
Loading…
Reference in a new issue