mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-08 10:09:43 +00:00
target/arm: Convert RFE and SRS
Backports commit 885782a78c6d05932c5d8f463dc50fc8312e3eb9 from qemu
This commit is contained in:
parent
87ff6a8bdf
commit
eff475c9a9
qemu/target/arm
|
@ -29,3 +29,11 @@
|
||||||
%imm24h 0:s24 24:1 !function=times_2
|
%imm24h 0:s24 24:1 !function=times_2
|
||||||
|
|
||||||
BLX_i 1111 101 . ........................ &i imm=%imm24h
|
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
|
||||||
|
|
|
@ -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 1000 10.1 .... ................ @ldstm i=1 b=0
|
||||||
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
|
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
|
# Branches
|
||||||
|
|
||||||
%imm24 26:s1 13:1 11:1 16:10 0:11 !function=t32_branch24
|
%imm24 26:s1 13:1 11:1 16:10 0:11 !function=t32_branch24
|
||||||
|
|
|
@ -10429,6 +10429,59 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
|
||||||
return true;
|
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
|
||||||
|
};
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
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(tcg_ctx, addr, addr, pre_offset[a->pu]);
|
||||||
|
|
||||||
|
/* Load PC into tmp and CPSR into tmp2. */
|
||||||
|
t1 = tcg_temp_new_i32(tcg_ctx);
|
||||||
|
gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
|
||||||
|
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
|
||||||
|
t2 = tcg_temp_new_i32(tcg_ctx);
|
||||||
|
gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
|
||||||
|
|
||||||
|
if (a->w) {
|
||||||
|
/* Base writeback. */
|
||||||
|
tcg_gen_addi_i32(tcg_ctx, addr, addr, post_offset[a->pu]);
|
||||||
|
store_reg(s, a->rn, addr);
|
||||||
|
} else {
|
||||||
|
tcg_temp_free_i32(tcg_ctx, 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.
|
* Legacy decoder.
|
||||||
*/
|
*/
|
||||||
|
@ -10436,10 +10489,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
|
||||||
static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
unsigned int cond, op1, i, rn;
|
unsigned int cond, op1;
|
||||||
TCGv_i32 tmp;
|
|
||||||
TCGv_i32 tmp2;
|
|
||||||
TCGv_i32 addr;
|
|
||||||
|
|
||||||
/* M variants do not implement ARM mode; this must raise the INVSTATE
|
/* M variants do not implement ARM mode; this must raise the INVSTATE
|
||||||
* UsageFault exception.
|
* UsageFault exception.
|
||||||
|
@ -10566,52 +10616,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||||
default:
|
default:
|
||||||
goto illegal_op;
|
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(tcg_ctx, addr, addr, offset);
|
|
||||||
/* Load PC into tmp and CPSR into tmp2. */
|
|
||||||
tmp = tcg_temp_new_i32(tcg_ctx);
|
|
||||||
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
|
|
||||||
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
|
|
||||||
tmp2 = tcg_temp_new_i32(tcg_ctx);
|
|
||||||
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(tcg_ctx, addr, addr, offset);
|
|
||||||
store_reg(s, rn, addr);
|
|
||||||
} else {
|
|
||||||
tcg_temp_free_i32(tcg_ctx, addr);
|
|
||||||
}
|
|
||||||
gen_rfe(s, tmp, tmp2);
|
|
||||||
return;
|
|
||||||
} else if ((insn & 0x0e000f00) == 0x0c000100) {
|
} else if ((insn & 0x0e000f00) == 0x0c000100) {
|
||||||
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
|
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
|
||||||
/* iWMMXt register transfer. */
|
/* iWMMXt register transfer. */
|
||||||
|
@ -10777,7 +10781,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
||||||
uint32_t imm, offset;
|
uint32_t imm, offset;
|
||||||
uint32_t rd, rn, rm, rs;
|
uint32_t rd, rn, rm, rs;
|
||||||
TCGv_i32 tmp;
|
TCGv_i32 tmp;
|
||||||
TCGv_i32 tmp2;
|
|
||||||
TCGv_i32 addr;
|
TCGv_i32 addr;
|
||||||
int op;
|
int op;
|
||||||
|
|
||||||
|
@ -10921,45 +10924,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Load/store multiple, RFE, SRS. */
|
/* Load/store multiple, RFE, SRS, in decodetree */
|
||||||
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;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
if (insn & (1 << 20)) {
|
|
||||||
/* rfe */
|
|
||||||
addr = load_reg(s, rn);
|
|
||||||
if ((insn & (1 << 24)) == 0)
|
|
||||||
tcg_gen_addi_i32(tcg_ctx, addr, addr, -8);
|
|
||||||
/* Load PC into tmp and CPSR into tmp2. */
|
|
||||||
tmp = tcg_temp_new_i32(tcg_ctx);
|
|
||||||
gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
|
|
||||||
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
|
|
||||||
tmp2 = tcg_temp_new_i32(tcg_ctx);
|
|
||||||
gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
|
|
||||||
if (insn & (1 << 21)) {
|
|
||||||
/* Base writeback. */
|
|
||||||
if (insn & (1 << 24)) {
|
|
||||||
tcg_gen_addi_i32(tcg_ctx, addr, addr, 4);
|
|
||||||
} else {
|
|
||||||
tcg_gen_addi_i32(tcg_ctx, addr, addr, -4);
|
|
||||||
}
|
|
||||||
store_reg(s, rn, addr);
|
|
||||||
} else {
|
|
||||||
tcg_temp_free_i32(tcg_ctx, 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* All in decodetree */
|
/* All in decodetree */
|
||||||
|
|
Loading…
Reference in a new issue