mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
target/arm: Convert LDXP, STXP, CASP, CAS to decodetree
Convert the load/store exclusive pair (LDXP, STXP, LDAXP, STLXP), compare-and-swap pair (CASP, CASPA, CASPAL, CASPL), and compare-and swap (CAS, CASA, CASAL, CASL) instructions to decodetree. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20230602155223.2040685-10-peter.maydell@linaro.org
This commit is contained in:
parent
84693e67fa
commit
e8a149a359
2 changed files with 53 additions and 79 deletions
|
@ -237,7 +237,18 @@ HLT 1101 0100 010 ................ 000 00 @i16
|
|||
&stlr rn rt sz lasr
|
||||
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
|
||||
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
|
||||
%imm1_30_p2 30:1 !function=plus_2
|
||||
@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
|
||||
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
|
||||
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
|
||||
STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
|
||||
LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
|
||||
|
||||
STXP 1 . 001000 001 ..... . ..... ..... ..... @stxp # inc STLXP
|
||||
LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
|
||||
|
||||
# CASP, CASPA, CASPAL, CASPL (we don't decode the bits that determine
|
||||
# acquire/release semantics because QEMU's cmpxchg always has those)
|
||||
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
|
||||
# CAS, CASA, CASAL, CASL
|
||||
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
|
||||
|
|
|
@ -2741,84 +2741,50 @@ static bool trans_LDAR(DisasContext *s, arg_stlr *a)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Load/store exclusive
|
||||
*
|
||||
* 31 30 29 24 23 22 21 20 16 15 14 10 9 5 4 0
|
||||
* +-----+-------------+----+---+----+------+----+-------+------+------+
|
||||
* | sz | 0 0 1 0 0 0 | o2 | L | o1 | Rs | o0 | Rt2 | Rn | Rt |
|
||||
* +-----+-------------+----+---+----+------+----+-------+------+------+
|
||||
*
|
||||
* sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
|
||||
* L: 0 -> store, 1 -> load
|
||||
* o2: 0 -> exclusive, 1 -> not
|
||||
* o1: 0 -> single register, 1 -> register pair
|
||||
* o0: 1 -> load-acquire/store-release, 0 -> not
|
||||
*/
|
||||
static void disas_ldst_excl(DisasContext *s, uint32_t insn)
|
||||
static bool trans_STXP(DisasContext *s, arg_stxr *a)
|
||||
{
|
||||
int rt = extract32(insn, 0, 5);
|
||||
int rn = extract32(insn, 5, 5);
|
||||
int rt2 = extract32(insn, 10, 5);
|
||||
int rs = extract32(insn, 16, 5);
|
||||
int is_lasr = extract32(insn, 15, 1);
|
||||
int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
|
||||
int size = extract32(insn, 30, 2);
|
||||
|
||||
switch (o2_L_o1_o0) {
|
||||
case 0x2: case 0x3: /* CASP / STXP */
|
||||
if (size & 2) { /* STXP / STLXP */
|
||||
if (rn == 31) {
|
||||
gen_check_sp_alignment(s);
|
||||
}
|
||||
if (is_lasr) {
|
||||
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
|
||||
}
|
||||
gen_store_exclusive(s, rs, rt, rt2, rn, size, true);
|
||||
return;
|
||||
}
|
||||
if (rt2 == 31
|
||||
&& ((rt | rs) & 1) == 0
|
||||
&& dc_isar_feature(aa64_atomics, s)) {
|
||||
/* CASP / CASPL */
|
||||
gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6: case 0x7: /* CASPA / LDXP */
|
||||
if (size & 2) { /* LDXP / LDAXP */
|
||||
if (rn == 31) {
|
||||
gen_check_sp_alignment(s);
|
||||
}
|
||||
gen_load_exclusive(s, rt, rt2, rn, size, true);
|
||||
if (is_lasr) {
|
||||
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rt2 == 31
|
||||
&& ((rt | rs) & 1) == 0
|
||||
&& dc_isar_feature(aa64_atomics, s)) {
|
||||
/* CASPA / CASPAL */
|
||||
gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xa: /* CAS */
|
||||
case 0xb: /* CASL */
|
||||
case 0xe: /* CASA */
|
||||
case 0xf: /* CASAL */
|
||||
if (rt2 == 31 && dc_isar_feature(aa64_atomics, s)) {
|
||||
gen_compare_and_swap(s, rs, rt, rn, size);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Handled in decodetree */
|
||||
break;
|
||||
if (a->rn == 31) {
|
||||
gen_check_sp_alignment(s);
|
||||
}
|
||||
unallocated_encoding(s);
|
||||
if (a->lasr) {
|
||||
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
|
||||
}
|
||||
gen_store_exclusive(s, a->rs, a->rt, a->rt2, a->rn, a->sz, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_LDXP(DisasContext *s, arg_stxr *a)
|
||||
{
|
||||
if (a->rn == 31) {
|
||||
gen_check_sp_alignment(s);
|
||||
}
|
||||
gen_load_exclusive(s, a->rt, a->rt2, a->rn, a->sz, true);
|
||||
if (a->lasr) {
|
||||
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_CASP(DisasContext *s, arg_CASP *a)
|
||||
{
|
||||
if (!dc_isar_feature(aa64_atomics, s)) {
|
||||
return false;
|
||||
}
|
||||
if (((a->rt | a->rs) & 1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gen_compare_and_swap_pair(s, a->rs, a->rt, a->rn, a->sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_CAS(DisasContext *s, arg_CAS *a)
|
||||
{
|
||||
if (!dc_isar_feature(aa64_atomics, s)) {
|
||||
return false;
|
||||
}
|
||||
gen_compare_and_swap(s, a->rs, a->rt, a->rn, a->sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4247,9 +4213,6 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn)
|
|||
static void disas_ldst(DisasContext *s, uint32_t insn)
|
||||
{
|
||||
switch (extract32(insn, 24, 6)) {
|
||||
case 0x08: /* Load/store exclusive */
|
||||
disas_ldst_excl(s, insn);
|
||||
break;
|
||||
case 0x18: case 0x1c: /* Load register (literal) */
|
||||
disas_ld_lit(s, insn);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue