mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-06-05 02:28:31 +00:00
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. Backports 0bf0dd4dcbd9fab324700ac6e0cd061cd043de0d
This commit is contained in:
parent
edae732810
commit
56532aa94c
|
@ -925,6 +925,99 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
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(tcg_ctx, addr, addr, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->v8m_stackcheck && a->rn == 13 && a->w) {
|
||||||
|
gen_helper_v8m_stackcheck(tcg_ctx, tcg_ctx->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(tcg_ctx, value);
|
||||||
|
|
||||||
|
if (a->w) {
|
||||||
|
/* writeback */
|
||||||
|
if (!a->p) {
|
||||||
|
tcg_gen_addi_i32(tcg_ctx, addr, addr, offset);
|
||||||
|
}
|
||||||
|
store_reg(s, a->rn, addr);
|
||||||
|
} else {
|
||||||
|
tcg_temp_free_i32(tcg_ctx, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
arg_vldr_sysreg *a = opaque;
|
||||||
|
uint32_t offset = a->imm;
|
||||||
|
TCGv_i32 addr;
|
||||||
|
TCGv_i32 value = tcg_temp_new_i32(tcg_ctx);
|
||||||
|
|
||||||
|
if (!a->a) {
|
||||||
|
offset = - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = load_reg(s, a->rn);
|
||||||
|
if (a->p) {
|
||||||
|
tcg_gen_addi_i32(tcg_ctx, addr, addr, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->v8m_stackcheck && a->rn == 13 && a->w) {
|
||||||
|
gen_helper_v8m_stackcheck(tcg_ctx, tcg_ctx->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(tcg_ctx, addr, addr, offset);
|
||||||
|
}
|
||||||
|
store_reg(s, a->rn, addr);
|
||||||
|
} else {
|
||||||
|
tcg_temp_free_i32(tcg_ctx, 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)
|
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
|
@ -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_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
|
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
|
# 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"
|
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
|
||||||
# grouping:
|
# grouping:
|
||||||
|
|
Loading…
Reference in a new issue