mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180208' into staging
tcg generic vectors # gpg: Signature made Thu 08 Feb 2018 16:47:16 GMT # gpg: using RSA key 64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-tcg-20180208: tcg/aarch64: Add vector operations tcg/i386: Add vector operations target/arm: Use vector infrastructure for aa64 orr/bic immediate target/arm: Use vector infrastructure for aa64 multiplies target/arm: Use vector infrastructure for aa64 compares target/arm: Use vector infrastructure for aa64 constant shifts target/arm: Use vector infrastructure for aa64 dup/movi target/arm: Use vector infrastructure for aa64 mov/not/neg target/arm: Use vector infrastructure for aa64 add/sub/logic target/arm: Align vector registers tcg/optimize: Handle vector opcodes during optimize tcg: Add generic vector helpers with a scalar operand tcg: Add generic helpers for saturating arithmetic tcg: Add generic vector ops for multiplication tcg: Add generic vector ops for comparisons tcg: Add generic vector ops for constant shifts tcg: Add generic vector expanders tcg: Standardize integral arguments to expanders tcg: Add types and basic operations for host vectors tcg: Allow multiple word entries into the constant pool Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+2
-2
@@ -93,8 +93,8 @@ all: $(PROGS) stap
|
||||
# cpu emulator library
|
||||
obj-y += exec.o
|
||||
obj-y += accel/
|
||||
obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
|
||||
obj-$(CONFIG_TCG) += tcg/tcg-common.o
|
||||
obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o
|
||||
obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o
|
||||
obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
|
||||
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
|
||||
obj-y += fpu/softfloat.o
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
obj-$(CONFIG_SOFTMMU) += tcg-all.o
|
||||
obj-$(CONFIG_SOFTMMU) += cputlb.o
|
||||
obj-y += tcg-runtime.o
|
||||
obj-y += tcg-runtime.o tcg-runtime-gvec.o
|
||||
obj-y += cpu-exec.o cpu-exec-common.o translate-all.o
|
||||
obj-y += translator.o
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -134,3 +134,121 @@ GEN_ATOMIC_HELPERS(xor_fetch)
|
||||
GEN_ATOMIC_HELPERS(xchg)
|
||||
|
||||
#undef GEN_ATOMIC_HELPERS
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_mov, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_dup8, TCG_CALL_NO_RWG, void, ptr, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_dup16, TCG_CALL_NO_RWG, void, ptr, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_dup32, TCG_CALL_NO_RWG, void, ptr, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_dup64, TCG_CALL_NO_RWG, void, ptr, i32, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_add8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_add16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_add32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_add64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_adds8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_adds16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_adds32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_adds64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_sub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_subs8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_subs16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_subs32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_subs64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_mul8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_mul16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_mul32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_mul64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_muls8, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_muls16, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_muls32, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_muls64, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_ssadd8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ssadd16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ssadd32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ssadd64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_sssub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sssub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sssub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_sssub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_usadd8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_usadd16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_usadd32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_usadd64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_ussub8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ussub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ussub32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ussub64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_neg8, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_neg16, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_neg32, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_neg64, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_not, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_and, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_or, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_xor, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_andc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_orc, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_ands, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_xors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ors, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_shl8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shl16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shl32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shl64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_shr8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shr16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shr32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_shr64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(gvec_sar8i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar16i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar32i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_3(gvec_sar64i, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_eq8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_eq64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_ne8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ne16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ne32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ne64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_lt8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_lt16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_lt32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_lt64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_le8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_le16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_le32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_le64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_ltu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ltu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ltu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_ltu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(gvec_leu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
@@ -5000,6 +5000,50 @@ if compile_prog "" "" ; then
|
||||
atomic64=yes
|
||||
fi
|
||||
|
||||
########################################
|
||||
# See if 16-byte vector operations are supported.
|
||||
# Even without a vector unit the compiler may expand these.
|
||||
# There is a bug in old GCC for PPC that crashes here.
|
||||
# Unfortunately it's the system compiler for Centos 7.
|
||||
|
||||
cat > $TMPC << EOF
|
||||
typedef unsigned char U1 __attribute__((vector_size(16)));
|
||||
typedef unsigned short U2 __attribute__((vector_size(16)));
|
||||
typedef unsigned int U4 __attribute__((vector_size(16)));
|
||||
typedef unsigned long long U8 __attribute__((vector_size(16)));
|
||||
typedef signed char S1 __attribute__((vector_size(16)));
|
||||
typedef signed short S2 __attribute__((vector_size(16)));
|
||||
typedef signed int S4 __attribute__((vector_size(16)));
|
||||
typedef signed long long S8 __attribute__((vector_size(16)));
|
||||
static U1 a1, b1;
|
||||
static U2 a2, b2;
|
||||
static U4 a4, b4;
|
||||
static U8 a8, b8;
|
||||
static S1 c1;
|
||||
static S2 c2;
|
||||
static S4 c4;
|
||||
static S8 c8;
|
||||
static int i;
|
||||
int main(void)
|
||||
{
|
||||
a1 += b1; a2 += b2; a4 += b4; a8 += b8;
|
||||
a1 -= b1; a2 -= b2; a4 -= b4; a8 -= b8;
|
||||
a1 *= b1; a2 *= b2; a4 *= b4; a8 *= b8;
|
||||
a1 &= b1; a2 &= b2; a4 &= b4; a8 &= b8;
|
||||
a1 |= b1; a2 |= b2; a4 |= b4; a8 |= b8;
|
||||
a1 ^= b1; a2 ^= b2; a4 ^= b4; a8 ^= b8;
|
||||
a1 <<= i; a2 <<= i; a4 <<= i; a8 <<= i;
|
||||
a1 >>= i; a2 >>= i; a4 >>= i; a8 >>= i;
|
||||
c1 >>= i; c2 >>= i; c4 >>= i; c8 >>= i;
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
vector16=no
|
||||
if compile_prog "" "" ; then
|
||||
vector16=yes
|
||||
fi
|
||||
|
||||
########################################
|
||||
# check if getauxval is available.
|
||||
|
||||
@@ -6329,6 +6373,10 @@ if test "$atomic64" = "yes" ; then
|
||||
echo "CONFIG_ATOMIC64=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$vector16" = "yes" ; then
|
||||
echo "CONFIG_VECTOR16=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$getauxval" = "yes" ; then
|
||||
echo "CONFIG_GETAUXVAL=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
+1
-1
@@ -492,7 +492,7 @@ typedef struct CPUARMState {
|
||||
* the two execution states, and means we do not need to explicitly
|
||||
* map these registers when changing states.
|
||||
*/
|
||||
uint64_t regs[64];
|
||||
uint64_t regs[64] QEMU_ALIGNED(16);
|
||||
|
||||
uint32_t xregs[16];
|
||||
/* We store these fpcsr fields separately for convenience. */
|
||||
|
||||
+715
-260
File diff suppressed because it is too large
Load Diff
+86
@@ -503,6 +503,92 @@ of the memory access.
|
||||
For a 32-bit host, qemu_ld/st_i64 is guaranteed to only be used with a
|
||||
64-bit memory access specified in flags.
|
||||
|
||||
********* Host vector operations
|
||||
|
||||
All of the vector ops have two parameters, TCGOP_VECL & TCGOP_VECE.
|
||||
The former specifies the length of the vector in log2 64-bit units; the
|
||||
later specifies the length of the element (if applicable) in log2 8-bit units.
|
||||
E.g. VECL=1 -> 64 << 1 -> v128, and VECE=2 -> 1 << 2 -> i32.
|
||||
|
||||
* mov_vec v0, v1
|
||||
* ld_vec v0, t1
|
||||
* st_vec v0, t1
|
||||
|
||||
Move, load and store.
|
||||
|
||||
* dup_vec v0, r1
|
||||
|
||||
Duplicate the low N bits of R1 into VECL/VECE copies across V0.
|
||||
|
||||
* dupi_vec v0, c
|
||||
|
||||
Similarly, for a constant.
|
||||
Smaller values will be replicated to host register size by the expanders.
|
||||
|
||||
* dup2_vec v0, r1, r2
|
||||
|
||||
Duplicate r2:r1 into VECL/64 copies across V0. This opcode is
|
||||
only present for 32-bit hosts.
|
||||
|
||||
* add_vec v0, v1, v2
|
||||
|
||||
v0 = v1 + v2, in elements across the vector.
|
||||
|
||||
* sub_vec v0, v1, v2
|
||||
|
||||
Similarly, v0 = v1 - v2.
|
||||
|
||||
* mul_vec v0, v1, v2
|
||||
|
||||
Similarly, v0 = v1 * v2.
|
||||
|
||||
* neg_vec v0, v1
|
||||
|
||||
Similarly, v0 = -v1.
|
||||
|
||||
* and_vec v0, v1, v2
|
||||
* or_vec v0, v1, v2
|
||||
* xor_vec v0, v1, v2
|
||||
* andc_vec v0, v1, v2
|
||||
* orc_vec v0, v1, v2
|
||||
* not_vec v0, v1
|
||||
|
||||
Similarly, logical operations with and without compliment.
|
||||
Note that VECE is unused.
|
||||
|
||||
* shli_vec v0, v1, i2
|
||||
* shls_vec v0, v1, s2
|
||||
|
||||
Shift all elements from v1 by a scalar i2/s2. I.e.
|
||||
|
||||
for (i = 0; i < VECL/VECE; ++i) {
|
||||
v0[i] = v1[i] << s2;
|
||||
}
|
||||
|
||||
* shri_vec v0, v1, i2
|
||||
* sari_vec v0, v1, i2
|
||||
* shrs_vec v0, v1, s2
|
||||
* sars_vec v0, v1, s2
|
||||
|
||||
Similarly for logical and arithmetic right shift.
|
||||
|
||||
* shlv_vec v0, v1, v2
|
||||
|
||||
Shift elements from v1 by elements from v2. I.e.
|
||||
|
||||
for (i = 0; i < VECL/VECE; ++i) {
|
||||
v0[i] = v1[i] << v2[i];
|
||||
}
|
||||
|
||||
* shrv_vec v0, v1, v2
|
||||
* sarv_vec v0, v1, v2
|
||||
|
||||
Similarly for logical and arithmetic right shift.
|
||||
|
||||
* cmp_vec v0, v1, v2, cond
|
||||
|
||||
Compare vectors by element, storing -1 for true and 0 for false.
|
||||
|
||||
*********
|
||||
|
||||
Note 1: Some shortcuts are defined when the last operand is known to be
|
||||
|
||||
@@ -31,13 +31,22 @@ typedef enum {
|
||||
TCG_REG_SP = 31,
|
||||
TCG_REG_XZR = 31,
|
||||
|
||||
TCG_REG_V0 = 32, TCG_REG_V1, TCG_REG_V2, TCG_REG_V3,
|
||||
TCG_REG_V4, TCG_REG_V5, TCG_REG_V6, TCG_REG_V7,
|
||||
TCG_REG_V8, TCG_REG_V9, TCG_REG_V10, TCG_REG_V11,
|
||||
TCG_REG_V12, TCG_REG_V13, TCG_REG_V14, TCG_REG_V15,
|
||||
TCG_REG_V16, TCG_REG_V17, TCG_REG_V18, TCG_REG_V19,
|
||||
TCG_REG_V20, TCG_REG_V21, TCG_REG_V22, TCG_REG_V23,
|
||||
TCG_REG_V24, TCG_REG_V25, TCG_REG_V26, TCG_REG_V27,
|
||||
TCG_REG_V28, TCG_REG_V29, TCG_REG_V30, TCG_REG_V31,
|
||||
|
||||
/* Aliases. */
|
||||
TCG_REG_FP = TCG_REG_X29,
|
||||
TCG_REG_LR = TCG_REG_X30,
|
||||
TCG_AREG0 = TCG_REG_X19,
|
||||
} TCGReg;
|
||||
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
#define TCG_TARGET_NB_REGS 64
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_SP
|
||||
@@ -113,6 +122,20 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#define TCG_TARGET_HAS_v64 1
|
||||
#define TCG_TARGET_HAS_v128 1
|
||||
#define TCG_TARGET_HAS_v256 0
|
||||
|
||||
#define TCG_TARGET_HAS_andc_vec 1
|
||||
#define TCG_TARGET_HAS_orc_vec 1
|
||||
#define TCG_TARGET_HAS_not_vec 1
|
||||
#define TCG_TARGET_HAS_neg_vec 1
|
||||
#define TCG_TARGET_HAS_shi_vec 1
|
||||
#define TCG_TARGET_HAS_shs_vec 0
|
||||
#define TCG_TARGET_HAS_shv_vec 0
|
||||
#define TCG_TARGET_HAS_cmp_vec 1
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
|
||||
+542
-46
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
/* Target-specific opcodes for host vector expansion. These will be
|
||||
emitted by tcg_expand_vec_op. For those familiar with GCC internals,
|
||||
consider these to be UNSPEC with names. */
|
||||
+39
-2
@@ -30,10 +30,10 @@
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define TCG_TARGET_REG_BITS 64
|
||||
# define TCG_TARGET_NB_REGS 16
|
||||
# define TCG_TARGET_NB_REGS 32
|
||||
#else
|
||||
# define TCG_TARGET_REG_BITS 32
|
||||
# define TCG_TARGET_NB_REGS 8
|
||||
# define TCG_TARGET_NB_REGS 24
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
@@ -56,6 +56,26 @@ typedef enum {
|
||||
TCG_REG_R13,
|
||||
TCG_REG_R14,
|
||||
TCG_REG_R15,
|
||||
|
||||
TCG_REG_XMM0,
|
||||
TCG_REG_XMM1,
|
||||
TCG_REG_XMM2,
|
||||
TCG_REG_XMM3,
|
||||
TCG_REG_XMM4,
|
||||
TCG_REG_XMM5,
|
||||
TCG_REG_XMM6,
|
||||
TCG_REG_XMM7,
|
||||
|
||||
/* 64-bit registers; likewise always define. */
|
||||
TCG_REG_XMM8,
|
||||
TCG_REG_XMM9,
|
||||
TCG_REG_XMM10,
|
||||
TCG_REG_XMM11,
|
||||
TCG_REG_XMM12,
|
||||
TCG_REG_XMM13,
|
||||
TCG_REG_XMM14,
|
||||
TCG_REG_XMM15,
|
||||
|
||||
TCG_REG_RAX = TCG_REG_EAX,
|
||||
TCG_REG_RCX = TCG_REG_ECX,
|
||||
TCG_REG_RDX = TCG_REG_EDX,
|
||||
@@ -77,6 +97,8 @@ typedef enum {
|
||||
|
||||
extern bool have_bmi1;
|
||||
extern bool have_popcnt;
|
||||
extern bool have_avx1;
|
||||
extern bool have_avx2;
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div2_i32 1
|
||||
@@ -146,6 +168,21 @@ extern bool have_popcnt;
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#endif
|
||||
|
||||
/* We do not support older SSE systems, only beginning with AVX1. */
|
||||
#define TCG_TARGET_HAS_v64 have_avx1
|
||||
#define TCG_TARGET_HAS_v128 have_avx1
|
||||
#define TCG_TARGET_HAS_v256 have_avx2
|
||||
|
||||
#define TCG_TARGET_HAS_andc_vec 1
|
||||
#define TCG_TARGET_HAS_orc_vec 0
|
||||
#define TCG_TARGET_HAS_not_vec 0
|
||||
#define TCG_TARGET_HAS_neg_vec 0
|
||||
#define TCG_TARGET_HAS_shi_vec 1
|
||||
#define TCG_TARGET_HAS_shs_vec 0
|
||||
#define TCG_TARGET_HAS_shv_vec 0
|
||||
#define TCG_TARGET_HAS_cmp_vec 1
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
|
||||
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
|
||||
(((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
|
||||
((ofs) == 0 && (len) == 16))
|
||||
|
||||
+935
-52
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
/* Target-specific opcodes for host vector expansion. These will be
|
||||
emitted by tcg_expand_vec_op. For those familiar with GCC internals,
|
||||
consider these to be UNSPEC with names. */
|
||||
|
||||
DEF(x86_shufps_vec, 1, 2, 1, IMPLVEC)
|
||||
DEF(x86_vpblendvb_vec, 1, 3, 0, IMPLVEC)
|
||||
DEF(x86_blend_vec, 1, 2, 1, IMPLVEC)
|
||||
DEF(x86_packss_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(x86_packus_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(x86_psrldq_vec, 1, 1, 1, IMPLVEC)
|
||||
DEF(x86_vperm2i128_vec, 1, 2, 1, IMPLVEC)
|
||||
DEF(x86_punpckl_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(x86_punpckh_vec, 1, 2, 0, IMPLVEC)
|
||||
+77
-73
@@ -32,6 +32,11 @@
|
||||
glue(glue(case INDEX_op_, x), _i32): \
|
||||
glue(glue(case INDEX_op_, x), _i64)
|
||||
|
||||
#define CASE_OP_32_64_VEC(x) \
|
||||
glue(glue(case INDEX_op_, x), _i32): \
|
||||
glue(glue(case INDEX_op_, x), _i64): \
|
||||
glue(glue(case INDEX_op_, x), _vec)
|
||||
|
||||
struct tcg_temp_info {
|
||||
bool is_const;
|
||||
TCGTemp *prev_copy;
|
||||
@@ -108,40 +113,6 @@ static void init_arg_info(struct tcg_temp_info *infos,
|
||||
init_ts_info(infos, temps_used, arg_temp(arg));
|
||||
}
|
||||
|
||||
static int op_bits(TCGOpcode op)
|
||||
{
|
||||
const TCGOpDef *def = &tcg_op_defs[op];
|
||||
return def->flags & TCG_OPF_64BIT ? 64 : 32;
|
||||
}
|
||||
|
||||
static TCGOpcode op_to_mov(TCGOpcode op)
|
||||
{
|
||||
switch (op_bits(op)) {
|
||||
case 32:
|
||||
return INDEX_op_mov_i32;
|
||||
case 64:
|
||||
return INDEX_op_mov_i64;
|
||||
default:
|
||||
fprintf(stderr, "op_to_mov: unexpected return value of "
|
||||
"function op_bits.\n");
|
||||
tcg_abort();
|
||||
}
|
||||
}
|
||||
|
||||
static TCGOpcode op_to_movi(TCGOpcode op)
|
||||
{
|
||||
switch (op_bits(op)) {
|
||||
case 32:
|
||||
return INDEX_op_movi_i32;
|
||||
case 64:
|
||||
return INDEX_op_movi_i64;
|
||||
default:
|
||||
fprintf(stderr, "op_to_movi: unexpected return value of "
|
||||
"function op_bits.\n");
|
||||
tcg_abort();
|
||||
}
|
||||
}
|
||||
|
||||
static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
|
||||
{
|
||||
TCGTemp *i;
|
||||
@@ -199,11 +170,23 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
|
||||
|
||||
static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
|
||||
{
|
||||
TCGOpcode new_op = op_to_movi(op->opc);
|
||||
const TCGOpDef *def;
|
||||
TCGOpcode new_op;
|
||||
tcg_target_ulong mask;
|
||||
struct tcg_temp_info *di = arg_info(dst);
|
||||
|
||||
def = &tcg_op_defs[op->opc];
|
||||
if (def->flags & TCG_OPF_VECTOR) {
|
||||
new_op = INDEX_op_dupi_vec;
|
||||
} else if (def->flags & TCG_OPF_64BIT) {
|
||||
new_op = INDEX_op_movi_i64;
|
||||
} else {
|
||||
new_op = INDEX_op_movi_i32;
|
||||
}
|
||||
op->opc = new_op;
|
||||
/* TCGOP_VECL and TCGOP_VECE remain unchanged. */
|
||||
op->args[0] = dst;
|
||||
op->args[1] = val;
|
||||
|
||||
reset_temp(dst);
|
||||
di->is_const = true;
|
||||
@@ -214,15 +197,13 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
|
||||
mask |= ~0xffffffffull;
|
||||
}
|
||||
di->mask = mask;
|
||||
|
||||
op->args[0] = dst;
|
||||
op->args[1] = val;
|
||||
}
|
||||
|
||||
static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
|
||||
{
|
||||
TCGTemp *dst_ts = arg_temp(dst);
|
||||
TCGTemp *src_ts = arg_temp(src);
|
||||
const TCGOpDef *def;
|
||||
struct tcg_temp_info *di;
|
||||
struct tcg_temp_info *si;
|
||||
tcg_target_ulong mask;
|
||||
@@ -236,9 +217,16 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
|
||||
reset_ts(dst_ts);
|
||||
di = ts_info(dst_ts);
|
||||
si = ts_info(src_ts);
|
||||
new_op = op_to_mov(op->opc);
|
||||
|
||||
def = &tcg_op_defs[op->opc];
|
||||
if (def->flags & TCG_OPF_VECTOR) {
|
||||
new_op = INDEX_op_mov_vec;
|
||||
} else if (def->flags & TCG_OPF_64BIT) {
|
||||
new_op = INDEX_op_mov_i64;
|
||||
} else {
|
||||
new_op = INDEX_op_mov_i32;
|
||||
}
|
||||
op->opc = new_op;
|
||||
/* TCGOP_VECL and TCGOP_VECE remain unchanged. */
|
||||
op->args[0] = dst;
|
||||
op->args[1] = src;
|
||||
|
||||
@@ -417,8 +405,9 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
|
||||
|
||||
static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
|
||||
{
|
||||
const TCGOpDef *def = &tcg_op_defs[op];
|
||||
TCGArg res = do_constant_folding_2(op, x, y);
|
||||
if (op_bits(op) == 32) {
|
||||
if (!(def->flags & TCG_OPF_64BIT)) {
|
||||
res = (int32_t)res;
|
||||
}
|
||||
return res;
|
||||
@@ -508,13 +497,12 @@ static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
|
||||
tcg_target_ulong xv = arg_info(x)->val;
|
||||
tcg_target_ulong yv = arg_info(y)->val;
|
||||
if (arg_is_const(x) && arg_is_const(y)) {
|
||||
switch (op_bits(op)) {
|
||||
case 32:
|
||||
return do_constant_folding_cond_32(xv, yv, c);
|
||||
case 64:
|
||||
const TCGOpDef *def = &tcg_op_defs[op];
|
||||
tcg_debug_assert(!(def->flags & TCG_OPF_VECTOR));
|
||||
if (def->flags & TCG_OPF_64BIT) {
|
||||
return do_constant_folding_cond_64(xv, yv, c);
|
||||
default:
|
||||
tcg_abort();
|
||||
} else {
|
||||
return do_constant_folding_cond_32(xv, yv, c);
|
||||
}
|
||||
} else if (args_are_copies(x, y)) {
|
||||
return do_constant_folding_cond_eq(c);
|
||||
@@ -653,11 +641,11 @@ void tcg_optimize(TCGContext *s)
|
||||
|
||||
/* For commutative operations make constant second argument */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(add):
|
||||
CASE_OP_32_64(mul):
|
||||
CASE_OP_32_64(and):
|
||||
CASE_OP_32_64(or):
|
||||
CASE_OP_32_64(xor):
|
||||
CASE_OP_32_64_VEC(add):
|
||||
CASE_OP_32_64_VEC(mul):
|
||||
CASE_OP_32_64_VEC(and):
|
||||
CASE_OP_32_64_VEC(or):
|
||||
CASE_OP_32_64_VEC(xor):
|
||||
CASE_OP_32_64(eqv):
|
||||
CASE_OP_32_64(nand):
|
||||
CASE_OP_32_64(nor):
|
||||
@@ -722,7 +710,7 @@ void tcg_optimize(TCGContext *s)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(sub):
|
||||
CASE_OP_32_64_VEC(sub):
|
||||
{
|
||||
TCGOpcode neg_op;
|
||||
bool have_neg;
|
||||
@@ -734,9 +722,12 @@ void tcg_optimize(TCGContext *s)
|
||||
if (opc == INDEX_op_sub_i32) {
|
||||
neg_op = INDEX_op_neg_i32;
|
||||
have_neg = TCG_TARGET_HAS_neg_i32;
|
||||
} else {
|
||||
} else if (opc == INDEX_op_sub_i64) {
|
||||
neg_op = INDEX_op_neg_i64;
|
||||
have_neg = TCG_TARGET_HAS_neg_i64;
|
||||
} else {
|
||||
neg_op = INDEX_op_neg_vec;
|
||||
have_neg = TCG_TARGET_HAS_neg_vec;
|
||||
}
|
||||
if (!have_neg) {
|
||||
break;
|
||||
@@ -750,7 +741,7 @@ void tcg_optimize(TCGContext *s)
|
||||
}
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(xor):
|
||||
CASE_OP_32_64_VEC(xor):
|
||||
CASE_OP_32_64(nand):
|
||||
if (!arg_is_const(op->args[1])
|
||||
&& arg_is_const(op->args[2])
|
||||
@@ -767,7 +758,7 @@ void tcg_optimize(TCGContext *s)
|
||||
goto try_not;
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(andc):
|
||||
CASE_OP_32_64_VEC(andc):
|
||||
if (!arg_is_const(op->args[2])
|
||||
&& arg_is_const(op->args[1])
|
||||
&& arg_info(op->args[1])->val == -1) {
|
||||
@@ -775,7 +766,7 @@ void tcg_optimize(TCGContext *s)
|
||||
goto try_not;
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(orc):
|
||||
CASE_OP_32_64_VEC(orc):
|
||||
CASE_OP_32_64(eqv):
|
||||
if (!arg_is_const(op->args[2])
|
||||
&& arg_is_const(op->args[1])
|
||||
@@ -789,7 +780,10 @@ void tcg_optimize(TCGContext *s)
|
||||
TCGOpcode not_op;
|
||||
bool have_not;
|
||||
|
||||
if (def->flags & TCG_OPF_64BIT) {
|
||||
if (def->flags & TCG_OPF_VECTOR) {
|
||||
not_op = INDEX_op_not_vec;
|
||||
have_not = TCG_TARGET_HAS_not_vec;
|
||||
} else if (def->flags & TCG_OPF_64BIT) {
|
||||
not_op = INDEX_op_not_i64;
|
||||
have_not = TCG_TARGET_HAS_not_i64;
|
||||
} else {
|
||||
@@ -810,16 +804,16 @@ void tcg_optimize(TCGContext *s)
|
||||
|
||||
/* Simplify expression for "op r, a, const => mov r, a" cases */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(add):
|
||||
CASE_OP_32_64(sub):
|
||||
CASE_OP_32_64_VEC(add):
|
||||
CASE_OP_32_64_VEC(sub):
|
||||
CASE_OP_32_64_VEC(or):
|
||||
CASE_OP_32_64_VEC(xor):
|
||||
CASE_OP_32_64_VEC(andc):
|
||||
CASE_OP_32_64(shl):
|
||||
CASE_OP_32_64(shr):
|
||||
CASE_OP_32_64(sar):
|
||||
CASE_OP_32_64(rotl):
|
||||
CASE_OP_32_64(rotr):
|
||||
CASE_OP_32_64(or):
|
||||
CASE_OP_32_64(xor):
|
||||
CASE_OP_32_64(andc):
|
||||
if (!arg_is_const(op->args[1])
|
||||
&& arg_is_const(op->args[2])
|
||||
&& arg_info(op->args[2])->val == 0) {
|
||||
@@ -827,8 +821,8 @@ void tcg_optimize(TCGContext *s)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_OP_32_64(and):
|
||||
CASE_OP_32_64(orc):
|
||||
CASE_OP_32_64_VEC(and):
|
||||
CASE_OP_32_64_VEC(orc):
|
||||
CASE_OP_32_64(eqv):
|
||||
if (!arg_is_const(op->args[1])
|
||||
&& arg_is_const(op->args[2])
|
||||
@@ -1042,8 +1036,8 @@ void tcg_optimize(TCGContext *s)
|
||||
|
||||
/* Simplify expression for "op r, a, 0 => movi r, 0" cases */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(and):
|
||||
CASE_OP_32_64(mul):
|
||||
CASE_OP_32_64_VEC(and):
|
||||
CASE_OP_32_64_VEC(mul):
|
||||
CASE_OP_32_64(muluh):
|
||||
CASE_OP_32_64(mulsh):
|
||||
if (arg_is_const(op->args[2])
|
||||
@@ -1058,8 +1052,8 @@ void tcg_optimize(TCGContext *s)
|
||||
|
||||
/* Simplify expression for "op r, a, a => mov r, a" cases */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(or):
|
||||
CASE_OP_32_64(and):
|
||||
CASE_OP_32_64_VEC(or):
|
||||
CASE_OP_32_64_VEC(and):
|
||||
if (args_are_copies(op->args[1], op->args[2])) {
|
||||
tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
|
||||
continue;
|
||||
@@ -1071,9 +1065,9 @@ void tcg_optimize(TCGContext *s)
|
||||
|
||||
/* Simplify expression for "op r, a, a => movi r, 0" cases */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(andc):
|
||||
CASE_OP_32_64(sub):
|
||||
CASE_OP_32_64(xor):
|
||||
CASE_OP_32_64_VEC(andc):
|
||||
CASE_OP_32_64_VEC(sub):
|
||||
CASE_OP_32_64_VEC(xor):
|
||||
if (args_are_copies(op->args[1], op->args[2])) {
|
||||
tcg_opt_gen_movi(s, op, op->args[0], 0);
|
||||
continue;
|
||||
@@ -1087,13 +1081,23 @@ void tcg_optimize(TCGContext *s)
|
||||
folding. Constants will be substituted to arguments by register
|
||||
allocator where needed and possible. Also detect copies. */
|
||||
switch (opc) {
|
||||
CASE_OP_32_64(mov):
|
||||
CASE_OP_32_64_VEC(mov):
|
||||
tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
|
||||
break;
|
||||
CASE_OP_32_64(movi):
|
||||
case INDEX_op_dupi_vec:
|
||||
tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
|
||||
break;
|
||||
|
||||
case INDEX_op_dup_vec:
|
||||
if (arg_is_const(op->args[1])) {
|
||||
tmp = arg_info(op->args[1])->val;
|
||||
tmp = dup_const(TCGOP_VECE(op), tmp);
|
||||
tcg_opt_gen_movi(s, op, op->args[0], tmp);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
CASE_OP_32_64(not):
|
||||
CASE_OP_32_64(neg):
|
||||
CASE_OP_32_64(ext8s):
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Generic vector operation descriptor
|
||||
*
|
||||
* Copyright (c) 2018 Linaro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */
|
||||
#define SIMD_OPRSZ_SHIFT 0
|
||||
#define SIMD_OPRSZ_BITS 5
|
||||
|
||||
#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
|
||||
#define SIMD_MAXSZ_BITS 5
|
||||
|
||||
#define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
|
||||
#define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
|
||||
|
||||
/* Create a descriptor from components. */
|
||||
uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
|
||||
|
||||
/* Extract the operation size from a descriptor. */
|
||||
static inline intptr_t simd_oprsz(uint32_t desc)
|
||||
{
|
||||
return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
|
||||
}
|
||||
|
||||
/* Extract the max vector size from a descriptor. */
|
||||
static inline intptr_t simd_maxsz(uint32_t desc)
|
||||
{
|
||||
return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
|
||||
}
|
||||
|
||||
/* Extract the operation-specific data from a descriptor. */
|
||||
static inline int32_t simd_data(uint32_t desc)
|
||||
{
|
||||
return sextract32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS);
|
||||
}
|
||||
+2216
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Generic vector operation expansion
|
||||
*
|
||||
* Copyright (c) 2018 Linaro
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* "Generic" vectors. All operands are given as offsets from ENV,
|
||||
* and therefore cannot also be allocated via tcg_global_mem_new_*.
|
||||
* OPRSZ is the byte size of the vector upon which the operation is performed.
|
||||
* MAXSZ is the byte size of the full vector; bytes beyond OPSZ are cleared.
|
||||
*
|
||||
* All sizes must be 8 or any multiple of 16.
|
||||
* When OPRSZ is 8, the alignment may be 8, otherwise must be 16.
|
||||
* Operands may completely, but not partially, overlap.
|
||||
*/
|
||||
|
||||
/* Expand a call to a gvec-style helper, with pointers to two vector
|
||||
operands, and a descriptor (see tcg-gvec-desc.h). */
|
||||
typedef void gen_helper_gvec_2(TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
|
||||
uint32_t oprsz, uint32_t maxsz, int32_t data,
|
||||
gen_helper_gvec_2 *fn);
|
||||
|
||||
/* Similarly, passing an extra data value. */
|
||||
typedef void gen_helper_gvec_2i(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_i32);
|
||||
void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
|
||||
uint32_t oprsz, uint32_t maxsz, int32_t data,
|
||||
gen_helper_gvec_2i *fn);
|
||||
|
||||
/* Similarly, passing an extra pointer (e.g. env or float_status). */
|
||||
typedef void gen_helper_gvec_2_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
|
||||
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
|
||||
int32_t data, gen_helper_gvec_2_ptr *fn);
|
||||
|
||||
/* Similarly, with three vector operands. */
|
||||
typedef void gen_helper_gvec_3(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
uint32_t oprsz, uint32_t maxsz, int32_t data,
|
||||
gen_helper_gvec_3 *fn);
|
||||
|
||||
/* Similarly, with four vector operands. */
|
||||
typedef void gen_helper_gvec_4(TCGv_ptr, TCGv_ptr, TCGv_ptr,
|
||||
TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
uint32_t cofs, uint32_t oprsz, uint32_t maxsz,
|
||||
int32_t data, gen_helper_gvec_4 *fn);
|
||||
|
||||
/* Similarly, with five vector operands. */
|
||||
typedef void gen_helper_gvec_5(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr,
|
||||
TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
uint32_t cofs, uint32_t xofs, uint32_t oprsz,
|
||||
uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn);
|
||||
|
||||
typedef void gen_helper_gvec_3_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
|
||||
TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
|
||||
int32_t data, gen_helper_gvec_3_ptr *fn);
|
||||
|
||||
typedef void gen_helper_gvec_4_ptr(TCGv_ptr, TCGv_ptr, TCGv_ptr,
|
||||
TCGv_ptr, TCGv_ptr, TCGv_i32);
|
||||
void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz,
|
||||
uint32_t maxsz, int32_t data,
|
||||
gen_helper_gvec_4_ptr *fn);
|
||||
|
||||
/* Expand a gvec operation. Either inline or out-of-line depending on
|
||||
the actual vector size and the operations supported by the host. */
|
||||
typedef struct {
|
||||
/* Expand inline as a 64-bit or 32-bit integer.
|
||||
Only one of these will be non-NULL. */
|
||||
void (*fni8)(TCGv_i64, TCGv_i64);
|
||||
void (*fni4)(TCGv_i32, TCGv_i32);
|
||||
/* Expand inline with a host vector type. */
|
||||
void (*fniv)(unsigned, TCGv_vec, TCGv_vec);
|
||||
/* Expand out-of-line helper w/descriptor. */
|
||||
gen_helper_gvec_2 *fno;
|
||||
/* The opcode, if any, to which this corresponds. */
|
||||
TCGOpcode opc;
|
||||
/* The data argument to the out-of-line helper. */
|
||||
int32_t data;
|
||||
/* The vector element size, if applicable. */
|
||||
uint8_t vece;
|
||||
/* Prefer i64 to v64. */
|
||||
bool prefer_i64;
|
||||
} GVecGen2;
|
||||
|
||||
typedef struct {
|
||||
/* Expand inline as a 64-bit or 32-bit integer.
|
||||
Only one of these will be non-NULL. */
|
||||
void (*fni8)(TCGv_i64, TCGv_i64, int64_t);
|
||||
void (*fni4)(TCGv_i32, TCGv_i32, int32_t);
|
||||
/* Expand inline with a host vector type. */
|
||||
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, int64_t);
|
||||
/* Expand out-of-line helper w/descriptor, data in descriptor. */
|
||||
gen_helper_gvec_2 *fno;
|
||||
/* Expand out-of-line helper w/descriptor, data as argument. */
|
||||
gen_helper_gvec_2i *fnoi;
|
||||
/* The opcode, if any, to which this corresponds. */
|
||||
TCGOpcode opc;
|
||||
/* The vector element size, if applicable. */
|
||||
uint8_t vece;
|
||||
/* Prefer i64 to v64. */
|
||||
bool prefer_i64;
|
||||
/* Load dest as a 3rd source operand. */
|
||||
bool load_dest;
|
||||
} GVecGen2i;
|
||||
|
||||
typedef struct {
|
||||
/* Expand inline as a 64-bit or 32-bit integer.
|
||||
Only one of these will be non-NULL. */
|
||||
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
|
||||
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
|
||||
/* Expand inline with a host vector type. */
|
||||
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
|
||||
/* Expand out-of-line helper w/descriptor. */
|
||||
gen_helper_gvec_2i *fno;
|
||||
/* The opcode, if any, to which this corresponds. */
|
||||
TCGOpcode opc;
|
||||
/* The data argument to the out-of-line helper. */
|
||||
uint32_t data;
|
||||
/* The vector element size, if applicable. */
|
||||
uint8_t vece;
|
||||
/* Prefer i64 to v64. */
|
||||
bool prefer_i64;
|
||||
/* Load scalar as 1st source operand. */
|
||||
bool scalar_first;
|
||||
} GVecGen2s;
|
||||
|
||||
typedef struct {
|
||||
/* Expand inline as a 64-bit or 32-bit integer.
|
||||
Only one of these will be non-NULL. */
|
||||
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
|
||||
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
|
||||
/* Expand inline with a host vector type. */
|
||||
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
|
||||
/* Expand out-of-line helper w/descriptor. */
|
||||
gen_helper_gvec_3 *fno;
|
||||
/* The opcode, if any, to which this corresponds. */
|
||||
TCGOpcode opc;
|
||||
/* The data argument to the out-of-line helper. */
|
||||
int32_t data;
|
||||
/* The vector element size, if applicable. */
|
||||
uint8_t vece;
|
||||
/* Prefer i64 to v64. */
|
||||
bool prefer_i64;
|
||||
/* Load dest as a 3rd source operand. */
|
||||
bool load_dest;
|
||||
} GVecGen3;
|
||||
|
||||
typedef struct {
|
||||
/* Expand inline as a 64-bit or 32-bit integer.
|
||||
Only one of these will be non-NULL. */
|
||||
void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64);
|
||||
void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
|
||||
/* Expand inline with a host vector type. */
|
||||
void (*fniv)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec, TCGv_vec);
|
||||
/* Expand out-of-line helper w/descriptor. */
|
||||
gen_helper_gvec_4 *fno;
|
||||
/* The opcode, if any, to which this corresponds. */
|
||||
TCGOpcode opc;
|
||||
/* The data argument to the out-of-line helper. */
|
||||
int32_t data;
|
||||
/* The vector element size, if applicable. */
|
||||
uint8_t vece;
|
||||
/* Prefer i64 to v64. */
|
||||
bool prefer_i64;
|
||||
} GVecGen4;
|
||||
|
||||
void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
|
||||
uint32_t oprsz, uint32_t maxsz, const GVecGen2 *);
|
||||
void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
|
||||
uint32_t maxsz, int64_t c, const GVecGen2i *);
|
||||
void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
|
||||
uint32_t maxsz, TCGv_i64 c, const GVecGen2s *);
|
||||
void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
|
||||
uint32_t oprsz, uint32_t maxsz, const GVecGen3 *);
|
||||
void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
|
||||
uint32_t oprsz, uint32_t maxsz, const GVecGen4 *);
|
||||
|
||||
/* Expand a specific vector operation. */
|
||||
|
||||
void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t c, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
/* Saturated arithmetic. */
|
||||
void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t c, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
uint32_t s, uint32_t m);
|
||||
void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t s,
|
||||
uint32_t m, TCGv_i32);
|
||||
void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t s,
|
||||
uint32_t m, TCGv_i64);
|
||||
|
||||
void tcg_gen_gvec_dup8i(uint32_t dofs, uint32_t s, uint32_t m, uint8_t x);
|
||||
void tcg_gen_gvec_dup16i(uint32_t dofs, uint32_t s, uint32_t m, uint16_t x);
|
||||
void tcg_gen_gvec_dup32i(uint32_t dofs, uint32_t s, uint32_t m, uint32_t x);
|
||||
void tcg_gen_gvec_dup64i(uint32_t dofs, uint32_t s, uint32_t m, uint64_t x);
|
||||
|
||||
void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t shift, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t shift, uint32_t oprsz, uint32_t maxsz);
|
||||
void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
|
||||
int64_t shift, uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
|
||||
uint32_t aofs, uint32_t bofs,
|
||||
uint32_t oprsz, uint32_t maxsz);
|
||||
|
||||
/*
|
||||
* 64-bit vector operations. Use these when the register has been allocated
|
||||
* with tcg_global_mem_new_i64, and so we cannot also address it via pointer.
|
||||
* OPRSZ = MAXSZ = 8.
|
||||
*/
|
||||
|
||||
void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 a);
|
||||
void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 a);
|
||||
void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 a);
|
||||
|
||||
void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
|
||||
void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
|
||||
|
||||
void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t);
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Tiny Code Generator for QEMU
|
||||
*
|
||||
* Copyright (c) 2018 Linaro, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "tcg.h"
|
||||
#include "tcg-op.h"
|
||||
#include "tcg-mo.h"
|
||||
|
||||
/* Reduce the number of ifdefs below. This assumes that all uses of
|
||||
TCGV_HIGH and TCGV_LOW are properly protected by a conditional that
|
||||
the compiler can eliminate. */
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
extern TCGv_i32 TCGV_LOW_link_error(TCGv_i64);
|
||||
extern TCGv_i32 TCGV_HIGH_link_error(TCGv_i64);
|
||||
#define TCGV_LOW TCGV_LOW_link_error
|
||||
#define TCGV_HIGH TCGV_HIGH_link_error
|
||||
#endif
|
||||
|
||||
void vec_gen_2(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(opc);
|
||||
TCGOP_VECL(op) = type - TCG_TYPE_V64;
|
||||
TCGOP_VECE(op) = vece;
|
||||
op->args[0] = r;
|
||||
op->args[1] = a;
|
||||
}
|
||||
|
||||
void vec_gen_3(TCGOpcode opc, TCGType type, unsigned vece,
|
||||
TCGArg r, TCGArg a, TCGArg b)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(opc);
|
||||
TCGOP_VECL(op) = type - TCG_TYPE_V64;
|
||||
TCGOP_VECE(op) = vece;
|
||||
op->args[0] = r;
|
||||
op->args[1] = a;
|
||||
op->args[2] = b;
|
||||
}
|
||||
|
||||
void vec_gen_4(TCGOpcode opc, TCGType type, unsigned vece,
|
||||
TCGArg r, TCGArg a, TCGArg b, TCGArg c)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(opc);
|
||||
TCGOP_VECL(op) = type - TCG_TYPE_V64;
|
||||
TCGOP_VECE(op) = vece;
|
||||
op->args[0] = r;
|
||||
op->args[1] = a;
|
||||
op->args[2] = b;
|
||||
op->args[3] = c;
|
||||
}
|
||||
|
||||
static void vec_gen_op2(TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
TCGTemp *at = tcgv_vec_temp(a);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
/* Must enough inputs for the output. */
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
vec_gen_2(opc, type, vece, temp_arg(rt), temp_arg(at));
|
||||
}
|
||||
|
||||
static void vec_gen_op3(TCGOpcode opc, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
TCGTemp *at = tcgv_vec_temp(a);
|
||||
TCGTemp *bt = tcgv_vec_temp(b);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
/* Must enough inputs for the output. */
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
tcg_debug_assert(bt->base_type >= type);
|
||||
vec_gen_3(opc, type, vece, temp_arg(rt), temp_arg(at), temp_arg(bt));
|
||||
}
|
||||
|
||||
void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
if (r != a) {
|
||||
vec_gen_op2(INDEX_op_mov_vec, 0, r, a);
|
||||
}
|
||||
}
|
||||
|
||||
#define MO_REG (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32)
|
||||
|
||||
static void do_dupi_vec(TCGv_vec r, unsigned vece, TCGArg a)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
vec_gen_2(INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a);
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_zeros_vec(TCGType type)
|
||||
{
|
||||
TCGv_vec ret = tcg_temp_new_vec(type);
|
||||
do_dupi_vec(ret, MO_REG, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_ones_vec(TCGType type)
|
||||
{
|
||||
TCGv_vec ret = tcg_temp_new_vec(type);
|
||||
do_dupi_vec(ret, MO_REG, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec m)
|
||||
{
|
||||
TCGTemp *t = tcgv_vec_temp(m);
|
||||
return tcg_const_zeros_vec(t->base_type);
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
|
||||
{
|
||||
TCGTemp *t = tcgv_vec_temp(m);
|
||||
return tcg_const_ones_vec(t->base_type);
|
||||
}
|
||||
|
||||
void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
|
||||
{
|
||||
if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
|
||||
do_dupi_vec(r, MO_32, a);
|
||||
} else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
|
||||
do_dupi_vec(r, MO_64, a);
|
||||
} else {
|
||||
TCGv_i64 c = tcg_const_i64(a);
|
||||
tcg_gen_dup_i64_vec(MO_64, r, c);
|
||||
tcg_temp_free_i64(c);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(r, MO_REG, dup_const(MO_32, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(r, MO_REG, dup_const(MO_16, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(r, MO_REG, dup_const(MO_8, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
|
||||
{
|
||||
do_dupi_vec(r, MO_REG, dup_const(vece, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(r);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
TCGArg ai = tcgv_i64_arg(a);
|
||||
vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
} else if (vece == MO_64) {
|
||||
TCGArg al = tcgv_i32_arg(TCGV_LOW(a));
|
||||
TCGArg ah = tcgv_i32_arg(TCGV_HIGH(a));
|
||||
vec_gen_3(INDEX_op_dup2_vec, type, MO_64, ri, al, ah);
|
||||
} else {
|
||||
TCGArg ai = tcgv_i32_arg(TCGV_LOW(a));
|
||||
vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec r, TCGv_i32 a)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(r);
|
||||
TCGArg ai = tcgv_i32_arg(a);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
vec_gen_2(INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
}
|
||||
|
||||
static void vec_gen_ldst(TCGOpcode opc, TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(r);
|
||||
TCGArg bi = tcgv_ptr_arg(b);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
vec_gen_3(opc, type, 0, ri, bi, o);
|
||||
}
|
||||
|
||||
void tcg_gen_ld_vec(TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
vec_gen_ldst(INDEX_op_ld_vec, r, b, o);
|
||||
}
|
||||
|
||||
void tcg_gen_st_vec(TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
vec_gen_ldst(INDEX_op_st_vec, r, b, o);
|
||||
}
|
||||
|
||||
void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr b, TCGArg o, TCGType low_type)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(r);
|
||||
TCGArg bi = tcgv_ptr_arg(b);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
tcg_debug_assert(low_type >= TCG_TYPE_V64);
|
||||
tcg_debug_assert(low_type <= type);
|
||||
vec_gen_3(INDEX_op_st_vec, low_type, 0, ri, bi, o);
|
||||
}
|
||||
|
||||
void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(INDEX_op_add_vec, vece, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(INDEX_op_sub_vec, vece, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_and_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(INDEX_op_and_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_or_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(INDEX_op_or_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_xor_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(INDEX_op_xor_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_andc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
if (TCG_TARGET_HAS_andc_vec) {
|
||||
vec_gen_op3(INDEX_op_andc_vec, 0, r, a, b);
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(r);
|
||||
tcg_gen_not_vec(0, t, b);
|
||||
tcg_gen_and_vec(0, r, a, t);
|
||||
tcg_temp_free_vec(t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_orc_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
if (TCG_TARGET_HAS_orc_vec) {
|
||||
vec_gen_op3(INDEX_op_orc_vec, 0, r, a, b);
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(r);
|
||||
tcg_gen_not_vec(0, t, b);
|
||||
tcg_gen_or_vec(0, r, a, t);
|
||||
tcg_temp_free_vec(t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_not_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
if (TCG_TARGET_HAS_not_vec) {
|
||||
vec_gen_op2(INDEX_op_not_vec, 0, r, a);
|
||||
} else {
|
||||
TCGv_vec t = tcg_const_ones_vec_matching(r);
|
||||
tcg_gen_xor_vec(0, r, a, t);
|
||||
tcg_temp_free_vec(t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_neg_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
if (TCG_TARGET_HAS_neg_vec) {
|
||||
vec_gen_op2(INDEX_op_neg_vec, vece, r, a);
|
||||
} else {
|
||||
TCGv_vec t = tcg_const_zeros_vec_matching(r);
|
||||
tcg_gen_sub_vec(vece, r, t, a);
|
||||
tcg_temp_free_vec(t);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_shifti(TCGOpcode opc, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
TCGTemp *at = tcgv_vec_temp(a);
|
||||
TCGArg ri = temp_arg(rt);
|
||||
TCGArg ai = temp_arg(at);
|
||||
TCGType type = rt->base_type;
|
||||
int can;
|
||||
|
||||
tcg_debug_assert(at->base_type == type);
|
||||
tcg_debug_assert(i >= 0 && i < (8 << vece));
|
||||
|
||||
if (i == 0) {
|
||||
tcg_gen_mov_vec(r, a);
|
||||
return;
|
||||
}
|
||||
|
||||
can = tcg_can_emit_vec_op(opc, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_3(opc, type, vece, ri, ai, i);
|
||||
} else {
|
||||
/* We leave the choice of expansion via scalar or vector shift
|
||||
to the target. Often, but not always, dupi can feed a vector
|
||||
shift easier than a scalar. */
|
||||
tcg_debug_assert(can < 0);
|
||||
tcg_expand_vec_op(opc, type, vece, ri, ai, i);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shli_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(INDEX_op_shli_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_shri_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(INDEX_op_shri_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_sari_vec(unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(INDEX_op_sari_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_cmp_vec(TCGCond cond, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
TCGTemp *at = tcgv_vec_temp(a);
|
||||
TCGTemp *bt = tcgv_vec_temp(b);
|
||||
TCGArg ri = temp_arg(rt);
|
||||
TCGArg ai = temp_arg(at);
|
||||
TCGArg bi = temp_arg(bt);
|
||||
TCGType type = rt->base_type;
|
||||
int can;
|
||||
|
||||
tcg_debug_assert(at->base_type == type);
|
||||
tcg_debug_assert(bt->base_type == type);
|
||||
can = tcg_can_emit_vec_op(INDEX_op_cmp_vec, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_4(INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond);
|
||||
} else {
|
||||
tcg_debug_assert(can < 0);
|
||||
tcg_expand_vec_op(INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_mul_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(r);
|
||||
TCGTemp *at = tcgv_vec_temp(a);
|
||||
TCGTemp *bt = tcgv_vec_temp(b);
|
||||
TCGArg ri = temp_arg(rt);
|
||||
TCGArg ai = temp_arg(at);
|
||||
TCGArg bi = temp_arg(bt);
|
||||
TCGType type = rt->base_type;
|
||||
int can;
|
||||
|
||||
tcg_debug_assert(at->base_type == type);
|
||||
tcg_debug_assert(bt->base_type == type);
|
||||
can = tcg_can_emit_vec_op(INDEX_op_mul_vec, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_3(INDEX_op_mul_vec, type, vece, ri, ai, bi);
|
||||
} else {
|
||||
tcg_debug_assert(can < 0);
|
||||
tcg_expand_vec_op(INDEX_op_mul_vec, type, vece, ri, ai, bi);
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -140,7 +140,7 @@ void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
|
||||
void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
{
|
||||
TCGv_i32 t0;
|
||||
/* Some cases can be optimized here. */
|
||||
@@ -148,17 +148,17 @@ void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, uint32_t arg2)
|
||||
case 0:
|
||||
tcg_gen_movi_i32(ret, 0);
|
||||
return;
|
||||
case 0xffffffffu:
|
||||
case -1:
|
||||
tcg_gen_mov_i32(ret, arg1);
|
||||
return;
|
||||
case 0xffu:
|
||||
case 0xff:
|
||||
/* Don't recurse with tcg_gen_ext8u_i32. */
|
||||
if (TCG_TARGET_HAS_ext8u_i32) {
|
||||
tcg_gen_op2_i32(INDEX_op_ext8u_i32, ret, arg1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xffffu:
|
||||
case 0xffff:
|
||||
if (TCG_TARGET_HAS_ext16u_i32) {
|
||||
tcg_gen_op2_i32(INDEX_op_ext16u_i32, ret, arg1);
|
||||
return;
|
||||
@@ -199,9 +199,9 @@ void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
|
||||
void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 32);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 32);
|
||||
if (arg2 == 0) {
|
||||
tcg_gen_mov_i32(ret, arg1);
|
||||
} else {
|
||||
@@ -211,9 +211,9 @@ void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
|
||||
void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 32);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 32);
|
||||
if (arg2 == 0) {
|
||||
tcg_gen_mov_i32(ret, arg1);
|
||||
} else {
|
||||
@@ -223,9 +223,9 @@ void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, unsigned arg2)
|
||||
void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 32);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 32);
|
||||
if (arg2 == 0) {
|
||||
tcg_gen_mov_i32(ret, arg1);
|
||||
} else {
|
||||
@@ -1201,7 +1201,7 @@ void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
|
||||
void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
|
||||
{
|
||||
TCGv_i64 t0;
|
||||
|
||||
@@ -1216,23 +1216,23 @@ void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, uint64_t arg2)
|
||||
case 0:
|
||||
tcg_gen_movi_i64(ret, 0);
|
||||
return;
|
||||
case 0xffffffffffffffffull:
|
||||
case -1:
|
||||
tcg_gen_mov_i64(ret, arg1);
|
||||
return;
|
||||
case 0xffull:
|
||||
case 0xff:
|
||||
/* Don't recurse with tcg_gen_ext8u_i64. */
|
||||
if (TCG_TARGET_HAS_ext8u_i64) {
|
||||
tcg_gen_op2_i64(INDEX_op_ext8u_i64, ret, arg1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xffffu:
|
||||
case 0xffff:
|
||||
if (TCG_TARGET_HAS_ext16u_i64) {
|
||||
tcg_gen_op2_i64(INDEX_op_ext16u_i64, ret, arg1);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0xffffffffull:
|
||||
case 0xffffffffu:
|
||||
if (TCG_TARGET_HAS_ext32u_i64) {
|
||||
tcg_gen_op2_i64(INDEX_op_ext32u_i64, ret, arg1);
|
||||
return;
|
||||
@@ -1332,9 +1332,9 @@ static inline void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
|
||||
void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 64);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 64);
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
|
||||
} else if (arg2 == 0) {
|
||||
@@ -1346,9 +1346,9 @@ void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
|
||||
void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 64);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 64);
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
|
||||
} else if (arg2 == 0) {
|
||||
@@ -1360,9 +1360,9 @@ void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, unsigned arg2)
|
||||
void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
|
||||
{
|
||||
tcg_debug_assert(arg2 < 64);
|
||||
tcg_debug_assert(arg2 >= 0 && arg2 < 64);
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
|
||||
} else if (arg2 == 0) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user