target/arm: Convert Bitfield to decodetree
Convert the BFM, SBFM, UBFM instructions. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20230512144106.3608981-12-peter.maydell@linaro.org [PMM: Rebased] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
ee0daeb946
commit
5e451ae63b
@ -84,3 +84,16 @@ MOVZ . 10 100101 .. ................ ..... @movw_64
|
|||||||
MOVZ . 10 100101 .. ................ ..... @movw_32
|
MOVZ . 10 100101 .. ................ ..... @movw_32
|
||||||
MOVK . 11 100101 .. ................ ..... @movw_64
|
MOVK . 11 100101 .. ................ ..... @movw_64
|
||||||
MOVK . 11 100101 .. ................ ..... @movw_32
|
MOVK . 11 100101 .. ................ ..... @movw_32
|
||||||
|
|
||||||
|
# Bitfield
|
||||||
|
|
||||||
|
&bitfield rd rn sf immr imms
|
||||||
|
@bitfield_64 1 .. ...... 1 immr:6 imms:6 rn:5 rd:5 &bitfield sf=1
|
||||||
|
@bitfield_32 0 .. ...... 0 0 immr:5 0 imms:5 rn:5 rd:5 &bitfield sf=0
|
||||||
|
|
||||||
|
SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
SBFM . 00 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
BFM . 01 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_64
|
||||||
|
UBFM . 10 100110 . ...... ...... ..... ..... @bitfield_32
|
||||||
|
@ -4431,82 +4431,103 @@ static bool trans_MOVK(DisasContext *s, arg_movw *a)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bitfield
|
/*
|
||||||
* 31 30 29 28 23 22 21 16 15 10 9 5 4 0
|
* Bitfield
|
||||||
* +----+-----+-------------+---+------+------+------+------+
|
|
||||||
* | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
|
|
||||||
* +----+-----+-------------+---+------+------+------+------+
|
|
||||||
*/
|
*/
|
||||||
static void disas_bitfield(DisasContext *s, uint32_t insn)
|
|
||||||
|
static bool trans_SBFM(DisasContext *s, arg_SBFM *a)
|
||||||
{
|
{
|
||||||
unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
|
TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
|
||||||
TCGv_i64 tcg_rd, tcg_tmp;
|
TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
|
||||||
|
unsigned int bitsize = a->sf ? 64 : 32;
|
||||||
|
unsigned int ri = a->immr;
|
||||||
|
unsigned int si = a->imms;
|
||||||
|
unsigned int pos, len;
|
||||||
|
|
||||||
sf = extract32(insn, 31, 1);
|
|
||||||
opc = extract32(insn, 29, 2);
|
|
||||||
n = extract32(insn, 22, 1);
|
|
||||||
ri = extract32(insn, 16, 6);
|
|
||||||
si = extract32(insn, 10, 6);
|
|
||||||
rn = extract32(insn, 5, 5);
|
|
||||||
rd = extract32(insn, 0, 5);
|
|
||||||
bitsize = sf ? 64 : 32;
|
|
||||||
|
|
||||||
if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
|
|
||||||
unallocated_encoding(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcg_rd = cpu_reg(s, rd);
|
|
||||||
|
|
||||||
/* Suppress the zero-extend for !sf. Since RI and SI are constrained
|
|
||||||
to be smaller than bitsize, we'll never reference data outside the
|
|
||||||
low 32-bits anyway. */
|
|
||||||
tcg_tmp = read_cpu_reg(s, rn, 1);
|
|
||||||
|
|
||||||
/* Recognize simple(r) extractions. */
|
|
||||||
if (si >= ri) {
|
if (si >= ri) {
|
||||||
/* Wd<s-r:0> = Wn<s:r> */
|
/* Wd<s-r:0> = Wn<s:r> */
|
||||||
len = (si - ri) + 1;
|
len = (si - ri) + 1;
|
||||||
if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
|
|
||||||
tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
|
tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||||
goto done;
|
if (!a->sf) {
|
||||||
} else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
|
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
|
||||||
tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
/* opc == 1, BFXIL fall through to deposit */
|
|
||||||
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
|
|
||||||
pos = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* Handle the ri > si case with a deposit
|
/* Wd<32+s-r,32-r> = Wn<s:0> */
|
||||||
* Wd<32+s-r,32-r> = Wn<s:0>
|
|
||||||
*/
|
|
||||||
len = si + 1;
|
len = si + 1;
|
||||||
pos = (bitsize - ri) & (bitsize - 1);
|
pos = (bitsize - ri) & (bitsize - 1);
|
||||||
}
|
|
||||||
|
|
||||||
if (opc == 0 && len < ri) {
|
if (len < ri) {
|
||||||
/* SBFM: sign extend the destination field from len to fill
|
/*
|
||||||
the balance of the word. Let the deposit below insert all
|
* Sign extend the destination field from len to fill the
|
||||||
of those sign bits. */
|
* balance of the word. Let the deposit below insert all
|
||||||
|
* of those sign bits.
|
||||||
|
*/
|
||||||
tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
|
tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
|
||||||
len = ri;
|
len = ri;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opc == 1) { /* BFM, BFXIL */
|
/*
|
||||||
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
* We start with zero, and we haven't modified any bits outside
|
||||||
} else {
|
* bitsize, therefore no final zero-extension is unneeded for !sf.
|
||||||
/* SBFM or UBFM: We start with zero, and we haven't modified
|
*/
|
||||||
any bits outside bitsize, therefore the zero-extension
|
|
||||||
below is unneeded. */
|
|
||||||
tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
||||||
return;
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool trans_UBFM(DisasContext *s, arg_UBFM *a)
|
||||||
|
{
|
||||||
|
TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
|
||||||
|
TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
|
||||||
|
unsigned int bitsize = a->sf ? 64 : 32;
|
||||||
|
unsigned int ri = a->immr;
|
||||||
|
unsigned int si = a->imms;
|
||||||
|
unsigned int pos, len;
|
||||||
|
|
||||||
|
tcg_rd = cpu_reg(s, a->rd);
|
||||||
|
tcg_tmp = read_cpu_reg(s, a->rn, 1);
|
||||||
|
|
||||||
|
if (si >= ri) {
|
||||||
|
/* Wd<s-r:0> = Wn<s:r> */
|
||||||
|
len = (si - ri) + 1;
|
||||||
|
tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||||
|
} else {
|
||||||
|
/* Wd<32+s-r,32-r> = Wn<s:0> */
|
||||||
|
len = si + 1;
|
||||||
|
pos = (bitsize - ri) & (bitsize - 1);
|
||||||
|
tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool trans_BFM(DisasContext *s, arg_BFM *a)
|
||||||
|
{
|
||||||
|
TCGv_i64 tcg_rd = cpu_reg(s, a->rd);
|
||||||
|
TCGv_i64 tcg_tmp = read_cpu_reg(s, a->rn, 1);
|
||||||
|
unsigned int bitsize = a->sf ? 64 : 32;
|
||||||
|
unsigned int ri = a->immr;
|
||||||
|
unsigned int si = a->imms;
|
||||||
|
unsigned int pos, len;
|
||||||
|
|
||||||
|
tcg_rd = cpu_reg(s, a->rd);
|
||||||
|
tcg_tmp = read_cpu_reg(s, a->rn, 1);
|
||||||
|
|
||||||
|
if (si >= ri) {
|
||||||
|
/* Wd<s-r:0> = Wn<s:r> */
|
||||||
|
tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
|
||||||
|
len = (si - ri) + 1;
|
||||||
|
pos = 0;
|
||||||
|
} else {
|
||||||
|
/* Wd<32+s-r,32-r> = Wn<s:0> */
|
||||||
|
len = si + 1;
|
||||||
|
pos = (bitsize - ri) & (bitsize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
||||||
if (!sf) { /* zero extend final result */
|
if (!a->sf) {
|
||||||
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
|
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract
|
/* Extract
|
||||||
@ -4573,9 +4594,6 @@ static void disas_extract(DisasContext *s, uint32_t insn)
|
|||||||
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
|
static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
|
||||||
{
|
{
|
||||||
switch (extract32(insn, 23, 6)) {
|
switch (extract32(insn, 23, 6)) {
|
||||||
case 0x26: /* Bitfield */
|
|
||||||
disas_bitfield(s, insn);
|
|
||||||
break;
|
|
||||||
case 0x27: /* Extract */
|
case 0x27: /* Extract */
|
||||||
disas_extract(s, insn);
|
disas_extract(s, insn);
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user