mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-07-08 21:50:36 +00:00
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. Backports commit 86d21e4b509a2835ed79f234f476a4c5191d435b from qemu
This commit is contained in:
parent
dbcc67ab20
commit
21df423e47
|
@ -41,6 +41,8 @@
|
||||||
&ldst_ri p w u rn rt imm
|
&ldst_ri p w u rn rt imm
|
||||||
&strex rn rd rt rt2 imm
|
&strex rn rd rt rt2 imm
|
||||||
&ldrex rn rt rt2 imm
|
&ldrex rn rt rt2 imm
|
||||||
|
&bfx rd rn lsb widthm1
|
||||||
|
&bfi rd rn lsb msb
|
||||||
|
|
||||||
# Data-processing (register)
|
# Data-processing (register)
|
||||||
|
|
||||||
|
@ -390,3 +392,21 @@ LDAEXH .... 0001 1111 .... .... 1110 1001 1111 @ldrex
|
||||||
LDA .... 0001 1001 .... .... 1100 1001 1111 @ldrex
|
LDA .... 0001 1001 .... .... 1100 1001 1111 @ldrex
|
||||||
LDAB .... 0001 1101 .... .... 1100 1001 1111 @ldrex
|
LDAB .... 0001 1101 .... .... 1100 1001 1111 @ldrex
|
||||||
LDAH .... 0001 1111 .... .... 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 ----
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
&ldst_ri !extern p w u rn rt imm
|
&ldst_ri !extern p w u rn rt imm
|
||||||
&strex !extern rn rd rt rt2 imm
|
&strex !extern rn rd rt rt2 imm
|
||||||
&ldrex !extern rn rt rt2 imm
|
&ldrex !extern rn rt rt2 imm
|
||||||
|
&bfx !extern rd rn lsb widthm1
|
||||||
|
&bfi !extern rd rn lsb msb
|
||||||
|
|
||||||
# Data-processing (register)
|
# 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
|
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
|
# Multiply and multiply accumulate
|
||||||
|
|
||||||
@s0_rnadm .... .... .... rn:4 ra:4 rd:4 .... rm:4 &s_rrrr s=0
|
@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
|
SMLALTB 1111 1011 1100 .... .... .... 1010 .... @rnadm
|
||||||
SMLALTT 1111 1011 1100 .... .... .... 1011 .... @rnadm
|
SMLALTT 1111 1011 1100 .... .... .... 1011 .... @rnadm
|
||||||
|
|
||||||
|
# usad8 is usada8 w/ ra=15
|
||||||
|
USADA8 1111 1011 0111 .... .... .... 0000 .... @rnadm
|
||||||
|
|
||||||
# Data-processing (two source registers)
|
# Data-processing (two source registers)
|
||||||
|
|
||||||
QADD 1111 1010 1000 .... 1111 .... 1000 .... @rndm
|
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
|
SMC 1111 0111 1111 imm:4 1000 0000 0000 0000 &i
|
||||||
HVC 1111 0111 1110 .... 1000 .... .... .... \
|
HVC 1111 0111 1110 .... 1000 .... .... .... \
|
||||||
&i imm=%imm16_16_0
|
&i imm=%imm16_16_0
|
||||||
|
UDF 1111 0111 1111 ---- 1010 ---- ---- ----
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load/store (register, immediate, literal)
|
# Load/store (register, immediate, literal)
|
||||||
|
|
|
@ -9463,6 +9463,107 @@ static bool trans_LDAH(DisasContext *s, arg_LDA *a)
|
||||||
return op_lda(s, a, MO_UW);
|
return op_lda(s, a, MO_UW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Media instructions
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
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(tcg_ctx, t1, t1, t2);
|
||||||
|
tcg_temp_free_i32(tcg_ctx, t2);
|
||||||
|
if (a->ra != 15) {
|
||||||
|
t2 = load_reg(s, a->ra);
|
||||||
|
tcg_gen_add_i32(tcg_ctx, t1, t1, t2);
|
||||||
|
tcg_temp_free_i32(tcg_ctx, t2);
|
||||||
|
}
|
||||||
|
store_reg(s, a->rd, t1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
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(tcg_ctx, tmp, tmp, shift, width);
|
||||||
|
} else {
|
||||||
|
tcg_gen_sextract_i32(tcg_ctx, 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)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
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(tcg_ctx, 0);
|
||||||
|
} else {
|
||||||
|
/* BFI */
|
||||||
|
tmp = load_reg(s, a->rn);
|
||||||
|
}
|
||||||
|
if (width != 32) {
|
||||||
|
TCGv_i32 tmp2 = load_reg(s, a->rd);
|
||||||
|
tcg_gen_deposit_i32(tcg_ctx, tmp, tmp2, tmp, lsb, width);
|
||||||
|
tcg_temp_free_i32(tcg_ctx, 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.
|
* Legacy decoder.
|
||||||
*/
|
*/
|
||||||
|
@ -10019,65 +10120,9 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
|
/* USAD, BFI, BFC, SBFX, UBFX */
|
||||||
switch (op1) {
|
/* Done by decodetree */
|
||||||
case 0: /* Unsigned sum of absolute differences. */
|
goto illegal_op;
|
||||||
ARCH(6);
|
|
||||||
tmp = load_reg(s, rm);
|
|
||||||
tmp2 = load_reg(s, rs);
|
|
||||||
gen_helper_usad8(tcg_ctx, tmp, tmp, tmp2);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
|
||||||
if (rd != 15) {
|
|
||||||
tmp2 = load_reg(s, rd);
|
|
||||||
tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp2);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, 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_ctx);
|
|
||||||
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
|
|
||||||
} else {
|
|
||||||
tmp = load_reg(s, rm);
|
|
||||||
}
|
|
||||||
if (i != 32) {
|
|
||||||
tmp2 = load_reg(s, rd);
|
|
||||||
tcg_gen_deposit_i32(tcg_ctx, tmp, tmp2, tmp, shift, i);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, 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(tcg_ctx, tmp, tmp, shift, i);
|
|
||||||
} else {
|
|
||||||
tcg_gen_sextract_i32(tcg_ctx, tmp, tmp, shift, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
store_reg(s, rd, tmp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto illegal_op;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -10714,10 +10759,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
||||||
case 0: /* 32 x 32 -> 32 */
|
case 0: /* 32 x 32 -> 32 */
|
||||||
case 1: /* 16 x 16 -> 32 */
|
case 1: /* 16 x 16 -> 32 */
|
||||||
case 3: /* 32 * 16 -> 32msb */
|
case 3: /* 32 * 16 -> 32msb */
|
||||||
|
case 7: /* Unsigned sum of absolute differences. */
|
||||||
/* in decodetree */
|
/* in decodetree */
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
case 7: /* Unsigned sum of absolute differences. */
|
|
||||||
break;
|
|
||||||
case 2: /* Dual multiply add. */
|
case 2: /* Dual multiply add. */
|
||||||
case 4: /* Dual multiply subtract. */
|
case 4: /* Dual multiply subtract. */
|
||||||
case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
|
case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
|
||||||
|
@ -10782,15 +10826,6 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
||||||
}
|
}
|
||||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
tcg_temp_free_i32(tcg_ctx, tmp2);
|
||||||
break;
|
break;
|
||||||
case 7: /* Unsigned sum of absolute differences. */
|
|
||||||
gen_helper_usad8(tcg_ctx, tmp, tmp, tmp2);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
|
||||||
if (rs != 15) {
|
|
||||||
tmp2 = load_reg(s, rs);
|
|
||||||
tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp2);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
store_reg(s, rd, tmp);
|
store_reg(s, rd, tmp);
|
||||||
break;
|
break;
|
||||||
|
@ -11085,32 +11120,9 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
|
||||||
tmp = load_reg(s, rn);
|
tmp = load_reg(s, rn);
|
||||||
}
|
}
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case 2: /* Signed bitfield extract. */
|
case 2: /* Signed bitfield extract, in decodetree */
|
||||||
imm++;
|
case 6: /* Unsigned bitfield extract, in decodetree */
|
||||||
if (shift + imm > 32)
|
case 3: /* Bitfield insert/clear, in decodetree */
|
||||||
goto illegal_op;
|
|
||||||
if (imm < 32) {
|
|
||||||
tcg_gen_sextract_i32(tcg_ctx, 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(tcg_ctx, 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(tcg_ctx, tmp, tmp2, tmp, shift, imm);
|
|
||||||
tcg_temp_free_i32(tcg_ctx, tmp2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 7:
|
case 7:
|
||||||
goto illegal_op;
|
goto illegal_op;
|
||||||
default: /* Saturate. */
|
default: /* Saturate. */
|
||||||
|
|
Loading…
Reference in a new issue