target/arm: Convert Parallel addition and subtraction

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20190904193059.26202-25-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:14 -07:00 committed by Peter Maydell
parent 86d21e4b50
commit adf1a5662a
3 changed files with 200 additions and 117 deletions

View File

@ -410,3 +410,47 @@ 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 ----
# Parallel addition and subtraction
SADD16 .... 0110 0001 .... .... 1111 0001 .... @rndm
SASX .... 0110 0001 .... .... 1111 0011 .... @rndm
SSAX .... 0110 0001 .... .... 1111 0101 .... @rndm
SSUB16 .... 0110 0001 .... .... 1111 0111 .... @rndm
SADD8 .... 0110 0001 .... .... 1111 1001 .... @rndm
SSUB8 .... 0110 0001 .... .... 1111 1111 .... @rndm
QADD16 .... 0110 0010 .... .... 1111 0001 .... @rndm
QASX .... 0110 0010 .... .... 1111 0011 .... @rndm
QSAX .... 0110 0010 .... .... 1111 0101 .... @rndm
QSUB16 .... 0110 0010 .... .... 1111 0111 .... @rndm
QADD8 .... 0110 0010 .... .... 1111 1001 .... @rndm
QSUB8 .... 0110 0010 .... .... 1111 1111 .... @rndm
SHADD16 .... 0110 0011 .... .... 1111 0001 .... @rndm
SHASX .... 0110 0011 .... .... 1111 0011 .... @rndm
SHSAX .... 0110 0011 .... .... 1111 0101 .... @rndm
SHSUB16 .... 0110 0011 .... .... 1111 0111 .... @rndm
SHADD8 .... 0110 0011 .... .... 1111 1001 .... @rndm
SHSUB8 .... 0110 0011 .... .... 1111 1111 .... @rndm
UADD16 .... 0110 0101 .... .... 1111 0001 .... @rndm
UASX .... 0110 0101 .... .... 1111 0011 .... @rndm
USAX .... 0110 0101 .... .... 1111 0101 .... @rndm
USUB16 .... 0110 0101 .... .... 1111 0111 .... @rndm
UADD8 .... 0110 0101 .... .... 1111 1001 .... @rndm
USUB8 .... 0110 0101 .... .... 1111 1111 .... @rndm
UQADD16 .... 0110 0110 .... .... 1111 0001 .... @rndm
UQASX .... 0110 0110 .... .... 1111 0011 .... @rndm
UQSAX .... 0110 0110 .... .... 1111 0101 .... @rndm
UQSUB16 .... 0110 0110 .... .... 1111 0111 .... @rndm
UQADD8 .... 0110 0110 .... .... 1111 1001 .... @rndm
UQSUB8 .... 0110 0110 .... .... 1111 1111 .... @rndm
UHADD16 .... 0110 0111 .... .... 1111 0001 .... @rndm
UHASX .... 0110 0111 .... .... 1111 0011 .... @rndm
UHSAX .... 0110 0111 .... .... 1111 0101 .... @rndm
UHSUB16 .... 0110 0111 .... .... 1111 0111 .... @rndm
UHADD8 .... 0110 0111 .... .... 1111 1001 .... @rndm
UHSUB8 .... 0110 0111 .... .... 1111 1111 .... @rndm

View File

@ -457,3 +457,47 @@ LDAEXD_t32 1110 1000 1101 .... .... .... 1111 1111 @ldrex_d
LDA 1110 1000 1101 .... .... 1111 1010 1111 @ldrex_0
LDAB 1110 1000 1101 .... .... 1111 1000 1111 @ldrex_0
LDAH 1110 1000 1101 .... .... 1111 1001 1111 @ldrex_0
# Parallel addition and subtraction
SADD8 1111 1010 1000 .... 1111 .... 0000 .... @rndm
QADD8 1111 1010 1000 .... 1111 .... 0001 .... @rndm
SHADD8 1111 1010 1000 .... 1111 .... 0010 .... @rndm
UADD8 1111 1010 1000 .... 1111 .... 0100 .... @rndm
UQADD8 1111 1010 1000 .... 1111 .... 0101 .... @rndm
UHADD8 1111 1010 1000 .... 1111 .... 0110 .... @rndm
SADD16 1111 1010 1001 .... 1111 .... 0000 .... @rndm
QADD16 1111 1010 1001 .... 1111 .... 0001 .... @rndm
SHADD16 1111 1010 1001 .... 1111 .... 0010 .... @rndm
UADD16 1111 1010 1001 .... 1111 .... 0100 .... @rndm
UQADD16 1111 1010 1001 .... 1111 .... 0101 .... @rndm
UHADD16 1111 1010 1001 .... 1111 .... 0110 .... @rndm
SASX 1111 1010 1010 .... 1111 .... 0000 .... @rndm
QASX 1111 1010 1010 .... 1111 .... 0001 .... @rndm
SHASX 1111 1010 1010 .... 1111 .... 0010 .... @rndm
UASX 1111 1010 1010 .... 1111 .... 0100 .... @rndm
UQASX 1111 1010 1010 .... 1111 .... 0101 .... @rndm
UHASX 1111 1010 1010 .... 1111 .... 0110 .... @rndm
SSUB8 1111 1010 1100 .... 1111 .... 0000 .... @rndm
QSUB8 1111 1010 1100 .... 1111 .... 0001 .... @rndm
SHSUB8 1111 1010 1100 .... 1111 .... 0010 .... @rndm
USUB8 1111 1010 1100 .... 1111 .... 0100 .... @rndm
UQSUB8 1111 1010 1100 .... 1111 .... 0101 .... @rndm
UHSUB8 1111 1010 1100 .... 1111 .... 0110 .... @rndm
SSUB16 1111 1010 1101 .... 1111 .... 0000 .... @rndm
QSUB16 1111 1010 1101 .... 1111 .... 0001 .... @rndm
SHSUB16 1111 1010 1101 .... 1111 .... 0010 .... @rndm
USUB16 1111 1010 1101 .... 1111 .... 0100 .... @rndm
UQSUB16 1111 1010 1101 .... 1111 .... 0101 .... @rndm
UHSUB16 1111 1010 1101 .... 1111 .... 0110 .... @rndm
SSAX 1111 1010 1110 .... 1111 .... 0000 .... @rndm
QSAX 1111 1010 1110 .... 1111 .... 0001 .... @rndm
SHSAX 1111 1010 1110 .... 1111 .... 0010 .... @rndm
USAX 1111 1010 1110 .... 1111 .... 0100 .... @rndm
UQSAX 1111 1010 1110 .... 1111 .... 0101 .... @rndm
UHSAX 1111 1010 1110 .... 1111 .... 0110 .... @rndm

View File

@ -648,99 +648,6 @@ static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
tcg_temp_free_i32(shift);
}
#define PAS_OP(pfx) \
switch (op2) { \
case 0: gen_pas_helper(glue(pfx,add16)); break; \
case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
case 3: gen_pas_helper(glue(pfx,sub16)); break; \
case 4: gen_pas_helper(glue(pfx,add8)); break; \
case 7: gen_pas_helper(glue(pfx,sub8)); break; \
}
static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
{
TCGv_ptr tmp;
switch (op1) {
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
case 1:
tmp = tcg_temp_new_ptr();
tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
PAS_OP(s)
tcg_temp_free_ptr(tmp);
break;
case 5:
tmp = tcg_temp_new_ptr();
tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
PAS_OP(u)
tcg_temp_free_ptr(tmp);
break;
#undef gen_pas_helper
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
case 2:
PAS_OP(q);
break;
case 3:
PAS_OP(sh);
break;
case 6:
PAS_OP(uq);
break;
case 7:
PAS_OP(uh);
break;
#undef gen_pas_helper
}
}
#undef PAS_OP
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
#define PAS_OP(pfx) \
switch (op1) { \
case 0: gen_pas_helper(glue(pfx,add8)); break; \
case 1: gen_pas_helper(glue(pfx,add16)); break; \
case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
case 4: gen_pas_helper(glue(pfx,sub8)); break; \
case 5: gen_pas_helper(glue(pfx,sub16)); break; \
case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
}
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
{
TCGv_ptr tmp;
switch (op2) {
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
case 0:
tmp = tcg_temp_new_ptr();
tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
PAS_OP(s)
tcg_temp_free_ptr(tmp);
break;
case 4:
tmp = tcg_temp_new_ptr();
tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
PAS_OP(u)
tcg_temp_free_ptr(tmp);
break;
#undef gen_pas_helper
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
case 1:
PAS_OP(q);
break;
case 2:
PAS_OP(sh);
break;
case 5:
PAS_OP(uq);
break;
case 6:
PAS_OP(uh);
break;
#undef gen_pas_helper
}
}
#undef PAS_OP
/*
* Generate a conditional based on ARM condition code cc.
* This is common between ARM and Aarch64 targets.
@ -9318,6 +9225,114 @@ static bool trans_UDF(DisasContext *s, arg_UDF *a)
return true;
}
/*
* Parallel addition and subtraction
*/
static bool op_par_addsub(DisasContext *s, arg_rrr *a,
void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
{
TCGv_i32 t0, t1;
if (s->thumb
? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
: !ENABLE_ARCH_6) {
return false;
}
t0 = load_reg(s, a->rn);
t1 = load_reg(s, a->rm);
gen(t0, t0, t1);
tcg_temp_free_i32(t1);
store_reg(s, a->rd, t0);
return true;
}
static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
void (*gen)(TCGv_i32, TCGv_i32,
TCGv_i32, TCGv_ptr))
{
TCGv_i32 t0, t1;
TCGv_ptr ge;
if (s->thumb
? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
: !ENABLE_ARCH_6) {
return false;
}
t0 = load_reg(s, a->rn);
t1 = load_reg(s, a->rm);
ge = tcg_temp_new_ptr();
tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
gen(t0, t0, t1, ge);
tcg_temp_free_ptr(ge);
tcg_temp_free_i32(t1);
store_reg(s, a->rd, t0);
return true;
}
#define DO_PAR_ADDSUB(NAME, helper) \
static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
{ \
return op_par_addsub(s, a, helper); \
}
#define DO_PAR_ADDSUB_GE(NAME, helper) \
static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
{ \
return op_par_addsub_ge(s, a, helper); \
}
DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
#undef DO_PAR_ADDSUB
#undef DO_PAR_ADDSUB_GE
/*
* Legacy decoder.
*/
@ -9630,16 +9645,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
rs = (insn >> 8) & 0xf;
switch ((insn >> 23) & 3) {
case 0: /* Parallel add/subtract. */
op1 = (insn >> 20) & 7;
tmp = load_reg(s, rn);
tmp2 = load_reg(s, rm);
sh = (insn >> 5) & 7;
if ((op1 & 3) == 0 || sh == 5 || sh == 6)
goto illegal_op;
gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
/* Done by decodetree */
goto illegal_op;
case 1:
if ((insn & 0x00700020) == 0) {
/* Halfword pack. */
@ -10432,20 +10439,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
}
store_reg(s, rd, tmp);
break;
case 2: /* SIMD add/subtract. */
if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
goto illegal_op;
}
op = (insn >> 20) & 7;
shift = (insn >> 4) & 7;
if ((op & 3) == 3 || (shift & 3) == 3)
goto illegal_op;
tmp = load_reg(s, rn);
tmp2 = load_reg(s, rm);
gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
case 2: /* SIMD add/subtract, in decodetree */
goto illegal_op;
case 3: /* Other data processing. */
op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
if (op < 4) {