target/arm: Implement VLDR/VSTR system register
Implement the new-in-v8.1M VLDR/VSTR variants which directly read or write FP system registers to memory. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
This commit is contained in:
parent
f7ed0c9433
commit
0bf0dd4dcb
@ -913,6 +913,97 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
|
||||
{
|
||||
arg_vldr_sysreg *a = opaque;
|
||||
uint32_t offset = a->imm;
|
||||
TCGv_i32 addr;
|
||||
|
||||
if (!a->a) {
|
||||
offset = - offset;
|
||||
}
|
||||
|
||||
addr = load_reg(s, a->rn);
|
||||
if (a->p) {
|
||||
tcg_gen_addi_i32(addr, addr, offset);
|
||||
}
|
||||
|
||||
if (s->v8m_stackcheck && a->rn == 13 && a->w) {
|
||||
gen_helper_v8m_stackcheck(cpu_env, addr);
|
||||
}
|
||||
|
||||
gen_aa32_st_i32(s, value, addr, get_mem_index(s),
|
||||
MO_UL | MO_ALIGN | s->be_data);
|
||||
tcg_temp_free_i32(value);
|
||||
|
||||
if (a->w) {
|
||||
/* writeback */
|
||||
if (!a->p) {
|
||||
tcg_gen_addi_i32(addr, addr, offset);
|
||||
}
|
||||
store_reg(s, a->rn, addr);
|
||||
} else {
|
||||
tcg_temp_free_i32(addr);
|
||||
}
|
||||
}
|
||||
|
||||
static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
|
||||
{
|
||||
arg_vldr_sysreg *a = opaque;
|
||||
uint32_t offset = a->imm;
|
||||
TCGv_i32 addr;
|
||||
TCGv_i32 value = tcg_temp_new_i32();
|
||||
|
||||
if (!a->a) {
|
||||
offset = - offset;
|
||||
}
|
||||
|
||||
addr = load_reg(s, a->rn);
|
||||
if (a->p) {
|
||||
tcg_gen_addi_i32(addr, addr, offset);
|
||||
}
|
||||
|
||||
if (s->v8m_stackcheck && a->rn == 13 && a->w) {
|
||||
gen_helper_v8m_stackcheck(cpu_env, addr);
|
||||
}
|
||||
|
||||
gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
|
||||
MO_UL | MO_ALIGN | s->be_data);
|
||||
|
||||
if (a->w) {
|
||||
/* writeback */
|
||||
if (!a->p) {
|
||||
tcg_gen_addi_i32(addr, addr, offset);
|
||||
}
|
||||
store_reg(s, a->rn, addr);
|
||||
} else {
|
||||
tcg_temp_free_i32(addr);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
|
||||
{
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
|
||||
return false;
|
||||
}
|
||||
if (a->rn == 15) {
|
||||
return false;
|
||||
}
|
||||
return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
|
||||
}
|
||||
|
||||
static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
|
||||
{
|
||||
if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
|
||||
return false;
|
||||
}
|
||||
if (a->rn == 15) {
|
||||
return false;
|
||||
}
|
||||
return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
|
||||
}
|
||||
|
||||
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
|
||||
{
|
||||
TCGv_i32 tmp;
|
||||
|
@ -84,6 +84,20 @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
|
||||
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
|
||||
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
|
||||
|
||||
# M-profile VLDR/VSTR to sysreg
|
||||
%vldr_sysreg 22:1 13:3
|
||||
%imm7_0x4 0:7 !function=times_4
|
||||
|
||||
&vldr_sysreg rn reg imm a w p
|
||||
@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
|
||||
reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
|
||||
|
||||
# P=0 W=0 is SEE "Related encodings", so split into two patterns
|
||||
VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
|
||||
VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
|
||||
VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
|
||||
VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
|
||||
|
||||
# We split the load/store multiple up into two patterns to avoid
|
||||
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
|
||||
# grouping:
|
||||
|
Loading…
Reference in New Issue
Block a user