@@ -9980,16 +9980,71 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
return true;
}
+/*
+ * Unconditional system instructions
+ */
+
+static bool trans_RFE(DisasContext *s, arg_RFE *a)
+{
+ int32_t offset;
+ TCGv_i32 addr, t1, t2;
+
+ if (IS_USER(s) || !ENABLE_ARCH_6) {
+ return false;
+ }
+
+ addr = load_reg(s, a->rn);
+
+ switch (a->pu) {
+ case 0: offset = -4; break; /* DA */
+ case 1: offset = 0; break; /* IA */
+ case 2: offset = -8; break; /* DB */
+ case 3: offset = 4; break; /* IB */
+ default:
+ g_assert_not_reached();
+ }
+ tcg_gen_addi_i32(addr, addr, offset);
+
+ /* Load PC into tmp and CPSR into tmp2. */
+ t1 = tcg_temp_new_i32();
+ gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
+ tcg_gen_addi_i32(addr, addr, 4);
+ t2 = tcg_temp_new_i32();
+ gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
+
+ if (a->w) {
+ /* Base writeback. */
+ switch (a->pu) {
+ case 0: offset = -8; break;
+ case 1: offset = 4; break;
+ case 2: offset = -4; break;
+ case 3: offset = 0; break;
+ }
+ tcg_gen_addi_i32(addr, addr, offset);
+ store_reg(s, a->rn, addr);
+ } else {
+ tcg_temp_free_i32(addr);
+ }
+ gen_rfe(s, t1, t2);
+ return true;
+}
+
+static bool trans_SRS(DisasContext *s, arg_SRS *a)
+{
+ if (!ENABLE_ARCH_6) {
+ return false;
+ }
+ gen_srs(s, a->mode, a->pu, a->w);
+ return true;
+}
+
/*
* Legacy decoder.
*/
static void disas_arm_insn(DisasContext *s, unsigned int insn)
{
- unsigned int cond, op1, i, rn;
- TCGv_i32 tmp;
- TCGv_i32 tmp2;
- TCGv_i32 addr;
+ unsigned int cond, op1;
/* M variants do not implement ARM mode; this must raise the INVSTATE
* UsageFault exception.
@@ -10108,52 +10163,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
default:
goto illegal_op;
}
- } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
- /* srs */
- ARCH(6);
- gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
- return;
- } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
- /* rfe */
- int32_t offset;
- if (IS_USER(s))
- goto illegal_op;
- ARCH(6);
- rn = (insn >> 16) & 0xf;
- addr = load_reg(s, rn);
- i = (insn >> 23) & 3;
- switch (i) {
- case 0: offset = -4; break; /* DA */
- case 1: offset = 0; break; /* IA */
- case 2: offset = -8; break; /* DB */
- case 3: offset = 4; break; /* IB */
- default: abort();
- }
- if (offset)
- tcg_gen_addi_i32(addr, addr, offset);
- /* Load PC into tmp and CPSR into tmp2. */
- tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
- tcg_gen_addi_i32(addr, addr, 4);
- tmp2 = tcg_temp_new_i32();
- gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
- if (insn & (1 << 21)) {
- /* Base writeback. */
- switch (i) {
- case 0: offset = -8; break;
- case 1: offset = 4; break;
- case 2: offset = -4; break;
- case 3: offset = 0; break;
- default: abort();
- }
- if (offset)
- tcg_gen_addi_i32(addr, addr, offset);
- store_reg(s, rn, addr);
- } else {
- tcg_temp_free_i32(addr);
- }
- gen_rfe(s, tmp, tmp2);
- return;
} else if ((insn & 0x0e000f00) == 0x0c000100) {
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
/* iWMMXt register transfer. */
@@ -10316,7 +10325,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
uint32_t imm, offset;
uint32_t rd, rn, rm, rs;
TCGv_i32 tmp;
- TCGv_i32 tmp2;
TCGv_i32 addr;
int op;
@@ -10460,44 +10468,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
goto illegal_op;
}
} else {
- /* Load/store multiple, RFE, SRS. */
- if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
- /* RFE, SRS: not available in user mode or on M profile */
- if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
- goto illegal_op;
- }
- if (insn & (1 << 20)) {
- /* rfe */
- addr = load_reg(s, rn);
- if ((insn & (1 << 24)) == 0)
- tcg_gen_addi_i32(addr, addr, -8);
- /* Load PC into tmp and CPSR into tmp2. */
- tmp = tcg_temp_new_i32();
- gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
- tcg_gen_addi_i32(addr, addr, 4);
- tmp2 = tcg_temp_new_i32();
- gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
- if (insn & (1 << 21)) {
- /* Base writeback. */
- if (insn & (1 << 24)) {
- tcg_gen_addi_i32(addr, addr, 4);
- } else {
- tcg_gen_addi_i32(addr, addr, -4);
- }
- store_reg(s, rn, addr);
- } else {
- tcg_temp_free_i32(addr);
- }
- gen_rfe(s, tmp, tmp2);
- } else {
- /* srs */
- gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
- insn & (1 << 21));
- }
- } else {
- /* Load/store multiple, in decodetree */
- goto illegal_op;
- }
+ /* Load/store multiple, RFE, SRS, in decodetree */
+ goto illegal_op;
}
break;
case 5:
@@ -29,3 +29,11 @@
%imm24h 0:s24 24:1 !function=times_2
BLX_i 1111 101 . ........................ &i imm=%imm24h
+
+# System Instructions
+
+&rfe rn w pu
+&srs mode w pu
+
+RFE 1111 100 pu:2 0 w:1 1 rn:4 0000 1010 0000 0000 &rfe
+SRS 1111 110 pu:2 1 w:1 0 1101 0000 0101 000 mode:5 &srs
@@ -582,6 +582,18 @@ STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
+&rfe !extern rn w pu
+@rfe .... .... .. w:1 . rn:4 ................ &rfe
+
+RFE 1110 1000 00.1 .... 1100000000000000 @rfe pu=2
+RFE 1110 1001 10.1 .... 1100000000000000 @rfe pu=1
+
+&srs !extern mode w pu
+@srs .... .... .. w:1 . .... ........... mode:5 &srs
+
+SRS 1110 1000 00.0 1101 1100 0000 000. .... @srs pu=2
+SRS 1110 1001 10.0 1101 1100 0000 000. .... @srs pu=1
+
# Branches
%imm24 26:s1 13:1 11:1 16:10 0:11 !function=t32_branch24
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/arm/translate.c | 150 ++++++++++++++--------------------- target/arm/a32-uncond.decode | 8 ++ target/arm/t32.decode | 12 +++ 3 files changed, 81 insertions(+), 89 deletions(-) -- 2.17.1