diff options
| author | Richard Henderson <richard.henderson@linaro.org> | 2021-05-03 16:47:52 -0700 |
|---|---|---|
| committer | Richard Henderson <richard.henderson@linaro.org> | 2021-06-04 11:50:11 -0700 |
| commit | 000cf4777aadda69d14a6994ca0d195a36733cbd (patch) | |
| tree | a01d2bbc4dbf2ac318f9754d18b2ae05d8c14a2f /tcg/arm/tcg-target.c.inc | |
| parent | a4fbbd779a29b912299bc2830f0157513080ddb7 (diff) | |
| download | focaccia-qemu-000cf4777aadda69d14a6994ca0d195a36733cbd.tar.gz focaccia-qemu-000cf4777aadda69d14a6994ca0d195a36733cbd.zip | |
tcg/arm: Add host vector framework
Add registers and function stubs. The functionality is disabled via use_neon_instructions defined to 0. We must still include results for the mandatory opcodes in tcg_target_op_def, as all opcodes are checked during tcg init. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tcg/arm/tcg-target.c.inc')
| -rw-r--r-- | tcg/arm/tcg-target.c.inc | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index eb4f42e53d..4770d0c537 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -40,22 +40,10 @@ bool use_idiv_instructions; #ifdef CONFIG_DEBUG_TCG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { - "%r0", - "%r1", - "%r2", - "%r3", - "%r4", - "%r5", - "%r6", - "%r7", - "%r8", - "%r9", - "%r10", - "%r11", - "%r12", - "%r13", - "%r14", - "%pc", + "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", + "%r8", "%r9", "%r10", "%r11", "%r12", "%sp", "%r14", "%pc", + "%q0", "%q1", "%q2", "%q3", "%q4", "%q5", "%q6", "%q7", + "%q8", "%q9", "%q10", "%q11", "%q12", "%q13", "%q14", "%q15", }; #endif @@ -75,6 +63,20 @@ static const int tcg_target_reg_alloc_order[] = { TCG_REG_R3, TCG_REG_R12, TCG_REG_R14, + + TCG_REG_Q0, + TCG_REG_Q1, + TCG_REG_Q2, + TCG_REG_Q3, + /* Q4 - Q7 are call-saved, and skipped. */ + TCG_REG_Q8, + TCG_REG_Q9, + TCG_REG_Q10, + TCG_REG_Q11, + TCG_REG_Q12, + TCG_REG_Q13, + TCG_REG_Q14, + TCG_REG_Q15, }; static const int tcg_target_call_iarg_regs[4] = { @@ -85,6 +87,7 @@ static const int tcg_target_call_oarg_regs[2] = { }; #define TCG_REG_TMP TCG_REG_R12 +#define TCG_VEC_TMP TCG_REG_Q15 enum arm_cond_code_e { COND_EQ = 0x0, @@ -238,6 +241,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type, #define TCG_CT_CONST_ZERO 0x800 #define ALL_GENERAL_REGS 0xffffu +#define ALL_VECTOR_REGS 0xffff0000u /* * r0-r2 will be overwritten when reading the tlb entry (softmmu only) @@ -2117,6 +2121,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_qemu_st_i64: return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s); + case INDEX_op_st_vec: + return C_O0_I2(w, r); + case INDEX_op_ld_vec: + case INDEX_op_dupm_vec: + return C_O1_I1(w, r); + case INDEX_op_dup_vec: + return C_O1_I1(w, wr); + case INDEX_op_dup2_vec: + case INDEX_op_add_vec: + case INDEX_op_sub_vec: + case INDEX_op_xor_vec: + case INDEX_op_or_vec: + case INDEX_op_and_vec: + case INDEX_op_cmp_vec: + return C_O1_I2(w, w, w); + default: g_assert_not_reached(); } @@ -2126,12 +2146,18 @@ static void tcg_target_init(TCGContext *s) { /* Only probe for the platform and capabilities if we havn't already determined maximum values at compile time. */ -#ifndef use_idiv_instructions +#if !defined(use_idiv_instructions) || !defined(use_neon_instructions) { unsigned long hwcap = qemu_getauxval(AT_HWCAP); +#ifndef use_idiv_instructions use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0; +#endif +#ifndef use_neon_instructions + use_neon_instructions = (hwcap & HWCAP_ARM_NEON) != 0; +#endif } #endif + if (__ARM_ARCH < 7) { const char *pl = (const char *)qemu_getauxval(AT_PLATFORM); if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') { @@ -2139,7 +2165,7 @@ static void tcg_target_init(TCGContext *s) } } - tcg_target_available_regs[TCG_TYPE_I32] = 0xffff; + tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; tcg_target_call_clobber_regs = 0; tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0); @@ -2149,10 +2175,29 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R12); tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14); + if (use_neon_instructions) { + tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; + tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; + + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q0); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q1); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q2); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q3); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q8); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q9); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q10); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q11); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q12); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q13); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q14); + tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q15); + } + s->reserved_regs = 0; tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK); tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC); + tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP); } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, @@ -2186,6 +2231,42 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, tcg_out_movi32(s, COND_AL, ret, arg); } +static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece, + TCGReg rd, TCGReg rs) +{ + g_assert_not_reached(); +} + +static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece, + TCGReg rd, TCGReg base, intptr_t offset) +{ + g_assert_not_reached(); +} + +static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, + TCGReg rd, int64_t v64) +{ + g_assert_not_reached(); +} + +static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, + unsigned vecl, unsigned vece, + const TCGArg *args, const int *const_args) +{ + g_assert_not_reached(); +} + +int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) +{ + return 0; +} + +void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, + TCGArg a0, ...) +{ + g_assert_not_reached(); +} + static void tcg_out_nop_fill(tcg_insn_unit *p, int count) { int i; |