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
|
||||
MOVK . 11 100101 .. ................ ..... @movw_64
|
||||
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;
|
||||
}
|
||||
|
||||
/* Bitfield
|
||||
* 31 30 29 28 23 22 21 16 15 10 9 5 4 0
|
||||
* +----+-----+-------------+---+------+------+------+------+
|
||||
* | sf | opc | 1 0 0 1 1 0 | N | immr | imms | Rn | Rd |
|
||||
* +----+-----+-------------+---+------+------+------+------+
|
||||
/*
|
||||
* Bitfield
|
||||
*/
|
||||
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, tcg_tmp;
|
||||
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;
|
||||
|
||||
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) {
|
||||
/* Wd<s-r:0> = Wn<s:r> */
|
||||
len = (si - ri) + 1;
|
||||
if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
|
||||
tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||
goto done;
|
||||
} else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
|
||||
tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||
return;
|
||||
tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
|
||||
if (!a->sf) {
|
||||
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
|
||||
}
|
||||
/* opc == 1, BFXIL fall through to deposit */
|
||||
} else {
|
||||
/* Wd<32+s-r,32-r> = Wn<s:0> */
|
||||
len = si + 1;
|
||||
pos = (bitsize - ri) & (bitsize - 1);
|
||||
|
||||
if (len < ri) {
|
||||
/*
|
||||
* Sign extend the destination field from len to fill the
|
||||
* balance of the word. Let the deposit below insert all
|
||||
* of those sign bits.
|
||||
*/
|
||||
tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
|
||||
len = ri;
|
||||
}
|
||||
|
||||
/*
|
||||
* We start with zero, and we haven't modified any bits outside
|
||||
* bitsize, therefore no final zero-extension is unneeded for !sf.
|
||||
*/
|
||||
tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
|
||||
}
|
||||
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 {
|
||||
/* 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;
|
||||
pos = (bitsize - ri) & (bitsize - 1);
|
||||
}
|
||||
|
||||
if (opc == 0 && len < ri) {
|
||||
/* SBFM: sign extend the destination field from len to fill
|
||||
the balance of the word. Let the deposit below insert all
|
||||
of those sign bits. */
|
||||
tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
|
||||
len = ri;
|
||||
}
|
||||
|
||||
if (opc == 1) { /* BFM, BFXIL */
|
||||
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
||||
} else {
|
||||
/* 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);
|
||||
return;
|
||||
}
|
||||
|
||||
done:
|
||||
if (!sf) { /* zero extend final result */
|
||||
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
|
||||
if (!a->sf) {
|
||||
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
switch (extract32(insn, 23, 6)) {
|
||||
case 0x26: /* Bitfield */
|
||||
disas_bitfield(s, insn);
|
||||
break;
|
||||
case 0x27: /* Extract */
|
||||
disas_extract(s, insn);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user