Skip to content

Commit

Permalink
target/arm: Convert RFE and SRS
Browse files Browse the repository at this point in the history
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-35-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
rth7680 authored and pm215 committed Sep 5, 2019
1 parent 542f518 commit 885782a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 89 deletions.
8 changes: 8 additions & 0 deletions target/arm/a32-uncond.decode
Expand Up @@ -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 100 pu:2 1 w:1 0 1101 0000 0101 000 mode:5 &srs
12 changes: 12 additions & 0 deletions target/arm/t32.decode
Expand Up @@ -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
Expand Down
144 changes: 55 additions & 89 deletions target/arm/translate.c
Expand Up @@ -10093,16 +10093,65 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
return true;
}

/*
* Unconditional system instructions
*/

static bool trans_RFE(DisasContext *s, arg_RFE *a)
{
static const int8_t pre_offset[4] = {
/* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
};
static const int8_t post_offset[4] = {
/* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
};
TCGv_i32 addr, t1, t2;

if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
return false;
}
if (IS_USER(s)) {
unallocated_encoding(s);
return true;
}

addr = load_reg(s, a->rn);
tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);

/* 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. */
tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
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 || arm_dc_feature(s, ARM_FEATURE_M)) {
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.
Expand Down Expand Up @@ -10221,52 +10270,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. */
Expand Down Expand Up @@ -10429,7 +10432,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;

Expand Down Expand Up @@ -10573,44 +10575,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:
Expand Down

0 comments on commit 885782a

Please sign in to comment.