[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] target-arm: implement LDA/STL instructions
From: |
Mans Rullgard |
Subject: |
[Qemu-devel] [PATCH 2/3] target-arm: implement LDA/STL instructions |
Date: |
Fri, 7 Jun 2013 13:06:25 +0100 |
This adds support for the ARMv8 load acquire/store release instructions.
Since qemu does nothing special for memory barriers, these can be
emulated like their non-acquire/release counterparts.
Signed-off-by: Mans Rullgard <address@hidden>
---
target-arm/translate.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 85 insertions(+), 6 deletions(-)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 96ac5bc..f529257 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -7274,14 +7274,54 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
rd = (insn >> 12) & 0xf;
if (insn & (1 << 23)) {
/* load/store exclusive */
+ int excl = (insn >> 9) & 1;
op1 = (insn >> 21) & 0x3;
- if (op1)
+ if (!excl)
+ ARCH(8);
+ else if (op1)
ARCH(6K);
else
ARCH(6);
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
- if (insn & (1 << 20)) {
+ if (!excl) {
+ if (op1 == 1)
+ goto illegal_op;
+ tmp = tcg_temp_new_i32();
+ if (insn & (1 << 20)) {
+ 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) {
case 0: /* ldrex */
gen_load_exclusive(s, rd, 15, addr, 2);
@@ -8126,7 +8166,7 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
gen_store_exclusive(s, rd, rs, 15, addr, 2);
}
tcg_temp_free_i32(addr);
- } else if ((insn & (1 << 6)) == 0) {
+ } else if ((insn & (3 << 6)) == 0) {
/* Table Branch. */
if (rn == 15) {
addr = tcg_temp_new_i32();
@@ -8153,14 +8193,53 @@ static int disas_thumb2_insn(CPUARMState *env,
DisasContext *s, uint16_t insn_hw
store_reg(s, 15, tmp);
} else {
/* Load/store exclusive byte/halfword/doubleword. */
- ARCH(7);
+ if (((insn >> 6) & 3) != 1)
+ ARCH(8);
+ else
+ ARCH(7);
op = (insn >> 4) & 0x3;
- if (op == 2) {
+ if (((insn >> 7) & 1) == 0 && op == 2) {
goto illegal_op;
}
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
- if (insn & (1 << 20)) {
+ if ((insn & (1 << 6)) == 0) {
+ if (op == 3)
+ goto illegal_op;
+ tmp = tcg_temp_new_i32();
+ if (insn & (1 << 20)) {
+ 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);
} else {
gen_store_exclusive(s, rm, rs, rd, addr, op);
--
1.8.2.1