target/arm: Convert USAD8, USADA8, SBFX, UBFX, BFC, BFI, UDF

In op_bfx, note that tcg_gen_{,s}extract_i32 already checks
for width == 32, so we don't need to special case that here.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-24-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2019-09-04 12:30:13 -07:00 committed by Peter Maydell
parent af28822899
commit 86d21e4b50
3 changed files with 144 additions and 96 deletions

View file

@ -41,6 +41,8 @@
&ldst_ri p w u rn rt imm
&strex rn rd rt rt2 imm
&ldrex rn rt rt2 imm
&bfx rd rn lsb widthm1
&bfi rd rn lsb msb
# Data-processing (register)
@ -390,3 +392,21 @@ LDAEXH .... 0001 1111 .... .... 1110 1001 1111 @ldrex
LDA .... 0001 1001 .... .... 1100 1001 1111 @ldrex
LDAB .... 0001 1101 .... .... 1100 1001 1111 @ldrex
LDAH .... 0001 1111 .... .... 1100 1001 1111 @ldrex
# Media instructions
# usad8 is usada8 w/ ra=15
USADA8 ---- 0111 1000 rd:4 ra:4 rm:4 0001 rn:4
# ubfx and sbfx
@bfx ---- .... ... widthm1:5 rd:4 lsb:5 ... rn:4 &bfx
SBFX .... 0111 101 ..... .... ..... 101 .... @bfx
UBFX .... 0111 111 ..... .... ..... 101 .... @bfx
# bfc is bfi w/ rn=15
BFCI ---- 0111 110 msb:5 rd:4 lsb:5 001 rn:4 &bfi
# While we could get UDEF by not including this, add the pattern for
# documentation and to conflict with any other typos in this file.
UDF 1110 0111 1111 ---- ---- ---- 1111 ----

View file

@ -38,6 +38,8 @@
&ldst_ri !extern p w u rn rt imm
&strex !extern rn rd rt rt2 imm
&ldrex !extern rn rt rt2 imm
&bfx !extern rd rn lsb widthm1
&bfi !extern rd rn lsb msb
# Data-processing (register)
@ -144,6 +146,19 @@ RSB_rri 1111 0.0 1110 . .... 0 ... .... ........ @s_rri_rot
SUB_rri 1111 0.1 0101 0 .... 0 ... .... ........ @s0_rri_12
}
# Saturate, bitfield
@bfx .... .... ... . rn:4 . ... rd:4 .. . widthm1:5 \
&bfx lsb=%imm5_12_6
@bfi .... .... ... . rn:4 . ... rd:4 .. . msb:5 \
&bfi lsb=%imm5_12_6
SBFX 1111 0011 010 0 .... 0 ... .... ..0..... @bfx
UBFX 1111 0011 110 0 .... 0 ... .... ..0..... @bfx
# bfc is bfi w/ rn=15
BFCI 1111 0011 011 0 .... 0 ... .... ..0..... @bfi
# Multiply and multiply accumulate
@s0_rnadm .... .... .... rn:4 ra:4 rd:4 .... rm:4 &s_rrrr s=0
@ -192,6 +207,9 @@ SMLALBT 1111 1011 1100 .... .... .... 1001 .... @rnadm
SMLALTB 1111 1011 1100 .... .... .... 1010 .... @rnadm
SMLALTT 1111 1011 1100 .... .... .... 1011 .... @rnadm
# usad8 is usada8 w/ ra=15
USADA8 1111 1011 0111 .... .... .... 0000 .... @rnadm
# Data-processing (two source registers)
QADD 1111 1010 1000 .... 1111 .... 1000 .... @rndm
@ -254,6 +272,7 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
SMC 1111 0111 1111 imm:4 1000 0000 0000 0000 &i
HVC 1111 0111 1110 .... 1000 .... .... .... \
&i imm=%imm16_16_0
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
}
# Load/store (register, immediate, literal)

View file

@ -9220,6 +9220,104 @@ static bool trans_LDAH(DisasContext *s, arg_LDA *a)
return op_lda(s, a, MO_UW);
}
/*
* Media instructions
*/
static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
{
TCGv_i32 t1, t2;
if (!ENABLE_ARCH_6) {
return false;
}
t1 = load_reg(s, a->rn);
t2 = load_reg(s, a->rm);
gen_helper_usad8(t1, t1, t2);
tcg_temp_free_i32(t2);
if (a->ra != 15) {
t2 = load_reg(s, a->ra);
tcg_gen_add_i32(t1, t1, t2);
tcg_temp_free_i32(t2);
}
store_reg(s, a->rd, t1);
return true;
}
static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
{
TCGv_i32 tmp;
int width = a->widthm1 + 1;
int shift = a->lsb;
if (!ENABLE_ARCH_6T2) {
return false;
}
if (shift + width > 32) {
/* UNPREDICTABLE; we choose to UNDEF */
unallocated_encoding(s);
return true;
}
tmp = load_reg(s, a->rn);
if (u) {
tcg_gen_extract_i32(tmp, tmp, shift, width);
} else {
tcg_gen_sextract_i32(tmp, tmp, shift, width);
}
store_reg(s, a->rd, tmp);
return true;
}
static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
{
return op_bfx(s, a, false);
}
static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
{
return op_bfx(s, a, true);
}
static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
{
TCGv_i32 tmp;
int msb = a->msb, lsb = a->lsb;
int width;
if (!ENABLE_ARCH_6T2) {
return false;
}
if (msb < lsb) {
/* UNPREDICTABLE; we choose to UNDEF */
unallocated_encoding(s);
return true;
}
width = msb + 1 - lsb;
if (a->rn == 15) {
/* BFC */
tmp = tcg_const_i32(0);
} else {
/* BFI */
tmp = load_reg(s, a->rn);
}
if (width != 32) {
TCGv_i32 tmp2 = load_reg(s, a->rd);
tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
tcg_temp_free_i32(tmp2);
}
store_reg(s, a->rd, tmp);
return true;
}
static bool trans_UDF(DisasContext *s, arg_UDF *a)
{
unallocated_encoding(s);
return true;
}
/*
* Legacy decoder.
*/
@ -9769,65 +9867,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
}
break;
case 3:
op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
switch (op1) {
case 0: /* Unsigned sum of absolute differences. */
ARCH(6);
tmp = load_reg(s, rm);
tmp2 = load_reg(s, rs);
gen_helper_usad8(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
if (rd != 15) {
tmp2 = load_reg(s, rd);
tcg_gen_add_i32(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rn, tmp);
break;
case 0x20: case 0x24: case 0x28: case 0x2c:
/* Bitfield insert/clear. */
ARCH(6T2);
shift = (insn >> 7) & 0x1f;
i = (insn >> 16) & 0x1f;
if (i < shift) {
/* UNPREDICTABLE; we choose to UNDEF */
goto illegal_op;
}
i = i + 1 - shift;
if (rm == 15) {
tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, 0);
} else {
tmp = load_reg(s, rm);
}
if (i != 32) {
tmp2 = load_reg(s, rd);
tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
tcg_temp_free_i32(tmp2);
}
store_reg(s, rd, tmp);
break;
case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
ARCH(6T2);
tmp = load_reg(s, rm);
shift = (insn >> 7) & 0x1f;
i = ((insn >> 16) & 0x1f) + 1;
if (shift + i > 32)
goto illegal_op;
if (i < 32) {
if (op1 & 0x20) {
tcg_gen_extract_i32(tmp, tmp, shift, i);
} else {
tcg_gen_sextract_i32(tmp, tmp, shift, i);
}
}
store_reg(s, rd, tmp);
break;
default:
goto illegal_op;
}
break;
/* USAD, BFI, BFC, SBFX, UBFX */
/* Done by decodetree */
goto illegal_op;
}
break;
}
@ -10466,10 +10508,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
case 0: /* 32 x 32 -> 32 */
case 1: /* 16 x 16 -> 32 */
case 3: /* 32 * 16 -> 32msb */
case 7: /* Unsigned sum of absolute differences. */
/* in decodetree */
goto illegal_op;
case 7: /* Unsigned sum of absolute differences. */
break;
case 2: /* Dual multiply add. */
case 4: /* Dual multiply subtract. */
case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
@ -10534,15 +10575,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
}
tcg_temp_free_i32(tmp2);
break;
case 7: /* Unsigned sum of absolute differences. */
gen_helper_usad8(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
if (rs != 15) {
tmp2 = load_reg(s, rs);
tcg_gen_add_i32(tmp, tmp, tmp2);
tcg_temp_free_i32(tmp2);
}
break;
}
store_reg(s, rd, tmp);
break;
@ -10837,32 +10869,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
tmp = load_reg(s, rn);
}
switch (op) {
case 2: /* Signed bitfield extract. */
imm++;
if (shift + imm > 32)
goto illegal_op;
if (imm < 32) {
tcg_gen_sextract_i32(tmp, tmp, shift, imm);
}
break;
case 6: /* Unsigned bitfield extract. */
imm++;
if (shift + imm > 32)
goto illegal_op;
if (imm < 32) {
tcg_gen_extract_i32(tmp, tmp, shift, imm);
}
break;
case 3: /* Bitfield insert/clear. */
if (imm < shift)
goto illegal_op;
imm = imm + 1 - shift;
if (imm != 32) {
tmp2 = load_reg(s, rd);
tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
tcg_temp_free_i32(tmp2);
}
break;
case 2: /* Signed bitfield extract, in decodetree */
case 6: /* Unsigned bitfield extract, in decodetree */
case 3: /* Bitfield insert/clear, in decodetree */
case 7:
goto illegal_op;
default: /* Saturate. */