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:
Peter Maydell 2020-11-19 21:55:58 +00:00
parent f7ed0c9433
commit 0bf0dd4dcb
2 changed files with 105 additions and 0 deletions

View File

@ -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;

View File

@ -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: