import Unicorn2
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
All the files in this directory and subdirectories are released under
|
||||
a BSD like license (see header in each file). No other license is
|
||||
accepted.
|
||||
247
qemu/tcg/README
247
qemu/tcg/README
@@ -8,6 +8,11 @@ in the QOP code generator written by Paul Brook.
|
||||
|
||||
2) Definitions
|
||||
|
||||
TCG receives RISC-like "TCG ops" and performs some optimizations on them,
|
||||
including liveness analysis and trivial constant expression
|
||||
evaluation. TCG ops are then implemented in the host CPU back end,
|
||||
also known as the TCG "target".
|
||||
|
||||
The TCG "target" is the architecture for which we generate the
|
||||
code. It is of course not the same as the "target" of QEMU which is
|
||||
the emulated architecture. As TCG started as a generic C backend used
|
||||
@@ -96,7 +101,7 @@ This can be overridden using the following function modifiers:
|
||||
canonical locations before calling the helper.
|
||||
- TCG_CALL_NO_WRITE_GLOBALS means that the helper does not modify any globals.
|
||||
They will only be saved to their canonical location before calling helpers,
|
||||
but they won't be reloaded afterwise.
|
||||
but they won't be reloaded afterwards.
|
||||
- TCG_CALL_NO_SIDE_EFFECTS means that the call to the function is removed if
|
||||
the return value is not used.
|
||||
|
||||
@@ -241,6 +246,14 @@ t0=~(t1|t2)
|
||||
|
||||
t0=t1|~t2
|
||||
|
||||
* clz_i32/i64 t0, t1, t2
|
||||
|
||||
t0 = t1 ? clz(t1) : t2
|
||||
|
||||
* ctz_i32/i64 t0, t1, t2
|
||||
|
||||
t0 = t1 ? ctz(t1) : t2
|
||||
|
||||
********* Shifts/Rotates
|
||||
|
||||
* shl_i32/i64 t0, t1, t2
|
||||
@@ -309,16 +322,45 @@ The bitfield is described by POS/LEN, which are immediate values:
|
||||
LEN - the length of the bitfield
|
||||
POS - the position of the first bit, counting from the LSB
|
||||
|
||||
For example, pos=8, len=4 indicates a 4-bit field at bit 8.
|
||||
This operation would be equivalent to
|
||||
For example, "deposit_i32 dest, t1, t2, 8, 4" indicates a 4-bit field
|
||||
at bit 8. This operation would be equivalent to
|
||||
|
||||
dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
|
||||
|
||||
* trunc_shr_i32 t0, t1, pos
|
||||
* extract_i32/i64 dest, t1, pos, len
|
||||
* sextract_i32/i64 dest, t1, pos, len
|
||||
|
||||
For 64-bit hosts only, right shift the 64-bit input T1 by POS and
|
||||
truncate to 32-bit output T0. Depending on the host, this may be
|
||||
a simple mov/shift, or may require additional canonicalization.
|
||||
Extract a bitfield from T1, placing the result in DEST.
|
||||
The bitfield is described by POS/LEN, which are immediate values,
|
||||
as above for deposit. For extract_*, the result will be extended
|
||||
to the left with zeros; for sextract_*, the result will be extended
|
||||
to the left with copies of the bitfield sign bit at pos + len - 1.
|
||||
|
||||
For example, "sextract_i32 dest, t1, 8, 4" indicates a 4-bit field
|
||||
at bit 8. This operation would be equivalent to
|
||||
|
||||
dest = (t1 << 20) >> 28
|
||||
|
||||
(using an arithmetic right shift).
|
||||
|
||||
* extract2_i32/i64 dest, t1, t2, pos
|
||||
|
||||
For N = {32,64}, extract an N-bit quantity from the concatenation
|
||||
of t2:t1, beginning at pos. The tcg_gen_extract2_{i32,i64} expander
|
||||
accepts 0 <= pos <= N as inputs. The backend code generator will
|
||||
not see either 0 or N as inputs for these opcodes.
|
||||
|
||||
* extrl_i64_i32 t0, t1
|
||||
|
||||
For 64-bit hosts only, extract the low 32-bits of input T1 and place it
|
||||
into 32-bit output T0. Depending on the host, this may be a simple move,
|
||||
or may require additional canonicalization.
|
||||
|
||||
* extrh_i64_i32 t0, t1
|
||||
|
||||
For 64-bit hosts only, extract the high 32-bits of input T1 and place it
|
||||
into 32-bit output T0. Depending on the host, this may be a simple shift,
|
||||
or may require additional canonicalization.
|
||||
|
||||
********* Conditional moves
|
||||
|
||||
@@ -396,6 +438,31 @@ double-word product T0. The later is returned in two single-word outputs.
|
||||
|
||||
Similar to mulu2, except the two inputs T1 and T2 are signed.
|
||||
|
||||
* mulsh_i32/i64 t0, t1, t2
|
||||
* muluh_i32/i64 t0, t1, t2
|
||||
|
||||
Provide the high part of a signed or unsigned multiply, respectively.
|
||||
If mulu2/muls2 are not provided by the backend, the tcg-op generator
|
||||
can obtain the same results can be obtained by emitting a pair of
|
||||
opcodes, mul+muluh/mulsh.
|
||||
|
||||
********* Memory Barrier support
|
||||
|
||||
* mb <$arg>
|
||||
|
||||
Generate a target memory barrier instruction to ensure memory ordering as being
|
||||
enforced by a corresponding guest memory barrier instruction. The ordering
|
||||
enforced by the backend may be stricter than the ordering required by the guest.
|
||||
It cannot be weaker. This opcode takes a constant argument which is required to
|
||||
generate the appropriate barrier instruction. The backend should take care to
|
||||
emit the target barrier instruction only when necessary i.e., for SMP guests and
|
||||
when MTTCG is enabled.
|
||||
|
||||
The guest translators should generate this opcode for all guest instructions
|
||||
which have ordering side effects.
|
||||
|
||||
Please see docs/devel/atomics.txt for more information on memory barriers.
|
||||
|
||||
********* 64-bit guest on 32-bit host support
|
||||
|
||||
The following opcodes are internal to TCG. Thus they are to be implemented by
|
||||
@@ -425,6 +492,14 @@ current TB was linked to this TB. Otherwise execute the next
|
||||
instructions. Only indices 0 and 1 are valid and tcg_gen_goto_tb may be issued
|
||||
at most once with each slot index per TB.
|
||||
|
||||
* lookup_and_goto_ptr tb_addr
|
||||
|
||||
Look up a TB address ('tb_addr') and jump to it if valid. If not valid,
|
||||
jump to the TCG epilogue to go back to the exec loop.
|
||||
|
||||
This operation is optional. If the TCG backend does not implement the
|
||||
goto_ptr opcode, emitting this op is equivalent to emitting exit_tb(0).
|
||||
|
||||
* qemu_ld_i32/i64 t0, t1, flags, memidx
|
||||
* qemu_st_i32/i64 t0, t1, flags, memidx
|
||||
|
||||
@@ -437,12 +512,132 @@ Both t0 and t1 may be split into little-endian ordered pairs of registers
|
||||
if dealing with 64-bit quantities on a 32-bit host.
|
||||
|
||||
The memidx selects the qemu tlb index to use (e.g. user or kernel access).
|
||||
The flags are the TCGMemOp bits, selecting the sign, width, and endianness
|
||||
The flags are the MemOp bits, selecting the sign, width, and endianness
|
||||
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.
|
||||
|
||||
* abs_vec v0, v1
|
||||
|
||||
Similarly, v0 = v1 < 0 ? -v1 : v1, in elements across the vector.
|
||||
|
||||
* smin_vec:
|
||||
* umin_vec:
|
||||
|
||||
Similarly, v0 = MIN(v1, v2), for signed and unsigned element types.
|
||||
|
||||
* smax_vec:
|
||||
* umax_vec:
|
||||
|
||||
Similarly, v0 = MAX(v1, v2), for signed and unsigned element types.
|
||||
|
||||
* ssadd_vec:
|
||||
* sssub_vec:
|
||||
* usadd_vec:
|
||||
* ussub_vec:
|
||||
|
||||
Signed and unsigned saturating addition and subtraction. If the true
|
||||
result is not representable within the element type, the element is
|
||||
set to the minimum or maximum value for the type.
|
||||
|
||||
* 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 complement.
|
||||
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.
|
||||
|
||||
* bitsel_vec v0, v1, v2, v3
|
||||
|
||||
Bitwise select, v0 = (v2 & v1) | (v3 & ~v1), across the entire vector.
|
||||
|
||||
* cmpsel_vec v0, c1, c2, v3, v4, cond
|
||||
|
||||
Select elements based on comparison results:
|
||||
for (i = 0; i < n; ++i) {
|
||||
v0[i] = (c1[i] cond c2[i]) ? v3[i] : v4[i].
|
||||
}
|
||||
|
||||
*********
|
||||
|
||||
Note 1: Some shortcuts are defined when the last operand is known to be
|
||||
@@ -454,8 +649,9 @@ function tcg_gen_xxx(args).
|
||||
|
||||
4) Backend
|
||||
|
||||
tcg-target.h contains the target specific definitions. tcg-target.c
|
||||
contains the target specific code.
|
||||
tcg-target.h contains the target specific definitions. tcg-target.inc.c
|
||||
contains the target specific code; it is #included by tcg/tcg.c, rather
|
||||
than being a standalone C file.
|
||||
|
||||
4.1) Assumptions
|
||||
|
||||
@@ -466,13 +662,25 @@ On a 32 bit target, all 64 bit operations are converted to 32 bits. A
|
||||
few specific operations must be implemented to allow it (see add2_i32,
|
||||
sub2_i32, brcond2_i32).
|
||||
|
||||
On a 64 bit target, the values are transferred between 32 and 64-bit
|
||||
registers using the following ops:
|
||||
- trunc_shr_i64_i32
|
||||
- ext_i32_i64
|
||||
- extu_i32_i64
|
||||
|
||||
They ensure that the values are correctly truncated or extended when
|
||||
moved from a 32-bit to a 64-bit register or vice-versa. Note that the
|
||||
trunc_shr_i64_i32 is an optional op. It is not necessary to implement
|
||||
it if all the following conditions are met:
|
||||
- 64-bit registers can hold 32-bit values
|
||||
- 32-bit values in a 64-bit register do not need to stay zero or
|
||||
sign extended
|
||||
- all 32-bit TCG ops ignore the high part of 64-bit registers
|
||||
|
||||
Floating point operations are not supported in this version. A
|
||||
previous incarnation of the code generator had full support of them,
|
||||
but it is better to concentrate on integer operations first.
|
||||
|
||||
On a 64 bit target, no assumption is made in TCG about the storage of
|
||||
the 32 bit values in 64 bit registers.
|
||||
|
||||
4.2) Constraints
|
||||
|
||||
GCC like constraints are used to define the constraints of every
|
||||
@@ -482,24 +690,29 @@ version. Aliases are specified in the input operands as for GCC.
|
||||
The same register may be used for both an input and an output, even when
|
||||
they are not explicitly aliased. If an op expands to multiple target
|
||||
instructions then care must be taken to avoid clobbering input values.
|
||||
GCC style "early clobber" outputs are not currently supported.
|
||||
GCC style "early clobber" outputs are supported, with '&'.
|
||||
|
||||
A target can define specific register or constant constraints. If an
|
||||
operation uses a constant input constraint which does not allow all
|
||||
constants, it must also accept registers in order to have a fallback.
|
||||
The constraint 'i' is defined generically to accept any constant.
|
||||
The constraint 'r' is not defined generically, but is consistently
|
||||
used by each backend to indicate all registers.
|
||||
|
||||
The movi_i32 and movi_i64 operations must accept any constants.
|
||||
|
||||
The mov_i32 and mov_i64 operations must accept any registers of the
|
||||
same type.
|
||||
|
||||
The ld/st instructions must accept signed 32 bit constant offsets. It
|
||||
can be implemented by reserving a specific register to compute the
|
||||
address if the offset is too big.
|
||||
The ld/st/sti instructions must accept signed 32 bit constant offsets.
|
||||
This can be implemented by reserving a specific register in which to
|
||||
compute the address if the offset is too big.
|
||||
|
||||
The ld/st instructions must accept any destination (ld) or source (st)
|
||||
register.
|
||||
|
||||
The sti instruction may fail if it cannot store the given constant.
|
||||
|
||||
4.3) Function call assumptions
|
||||
|
||||
- The only supported types for parameters and return value are: 32 and
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
- Add new instructions such as: clz, ctz, popcnt.
|
||||
|
||||
- See if it is worth exporting mul2, mulu2, div2, divu2.
|
||||
|
||||
- Support of globals saved in fixed registers between TBs.
|
||||
|
||||
Ideas:
|
||||
|
||||
- Move the slow part of the qemu_ld/st ops after the end of the TB.
|
||||
|
||||
- Change exception syntax to get closer to QOP system (exception
|
||||
parameters given with a specific instruction).
|
||||
|
||||
- Add float and vector support.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,15 @@
|
||||
* See the COPYING file in the top-level directory for details.
|
||||
*/
|
||||
|
||||
#ifndef TCG_TARGET_AARCH64
|
||||
#define TCG_TARGET_AARCH64 1
|
||||
#ifndef AARCH64_TCG_TARGET_H
|
||||
#define AARCH64_TCG_TARGET_H
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 24
|
||||
#undef TCG_TARGET_STACK_GROWSUP
|
||||
|
||||
typedef enum {
|
||||
@@ -30,13 +35,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
|
||||
@@ -61,7 +75,13 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_eqv_i32 1
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 1
|
||||
#define TCG_TARGET_HAS_ctz_i32 1
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_extract_i32 1
|
||||
#define TCG_TARGET_HAS_sextract_i32 1
|
||||
#define TCG_TARGET_HAS_extract2_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
@@ -69,7 +89,9 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
@@ -90,7 +112,13 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_eqv_i64 1
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 1
|
||||
#define TCG_TARGET_HAS_ctz_i64 1
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_extract_i64 1
|
||||
#define TCG_TARGET_HAS_sextract_i64 1
|
||||
#define TCG_TARGET_HAS_extract2_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
@@ -98,10 +126,48 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 1
|
||||
#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_abs_vec 1
|
||||
#define TCG_TARGET_HAS_shi_vec 1
|
||||
#define TCG_TARGET_HAS_shs_vec 0
|
||||
#define TCG_TARGET_HAS_shv_vec 1
|
||||
#define TCG_TARGET_HAS_cmp_vec 1
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
#define TCG_TARGET_HAS_sat_vec 1
|
||||
#define TCG_TARGET_HAS_minmax_vec 1
|
||||
#define TCG_TARGET_HAS_bitsel_vec 1
|
||||
#define TCG_TARGET_HAS_cmpsel_vec 0
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
/*
|
||||
* On Intel-based Mac computers, this function does nothing.
|
||||
* Source: https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon?language=objc
|
||||
*/
|
||||
sys_icache_invalidate((char *)start, stop - start);
|
||||
#else
|
||||
__builtin___clear_cache((char *)start, (char *)stop);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* TCG_TARGET_AARCH64 */
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif /* AARCH64_TCG_TARGET_H */
|
||||
|
||||
2927
qemu/tcg/aarch64/tcg-target.inc.c
Normal file
2927
qemu/tcg/aarch64/tcg-target.inc.c
Normal file
File diff suppressed because it is too large
Load Diff
14
qemu/tcg/aarch64/tcg-target.opc.h
Normal file
14
qemu/tcg/aarch64/tcg-target.opc.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Linaro
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See the COPYING file in the top-level directory for details.
|
||||
*
|
||||
* 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(aa64_sshl_vec, 1, 2, 0, IMPLVEC)
|
||||
@@ -22,11 +22,44 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_ARM
|
||||
#define TCG_TARGET_ARM 1
|
||||
|
||||
#ifndef ARM_TCG_TARGET_H
|
||||
#define ARM_TCG_TARGET_H
|
||||
|
||||
/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
|
||||
#ifndef __ARM_ARCH
|
||||
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|
||||
|| defined(__ARM_ARCH_7EM__)
|
||||
# define __ARM_ARCH 7
|
||||
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
|
||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
|
||||
# define __ARM_ARCH 6
|
||||
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
|
||||
|| defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__)
|
||||
# define __ARM_ARCH 5
|
||||
# else
|
||||
# define __ARM_ARCH 4
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern int arm_arch;
|
||||
|
||||
#if defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
|
||||
# define use_armv5t_instructions 1
|
||||
#else
|
||||
# define use_armv5t_instructions use_armv6_instructions
|
||||
#endif
|
||||
|
||||
#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
|
||||
#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
|
||||
|
||||
#undef TCG_TARGET_STACK_GROWSUP
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
|
||||
|
||||
typedef enum {
|
||||
TCG_REG_R0 = 0,
|
||||
@@ -52,8 +85,7 @@ typedef enum {
|
||||
#ifdef __ARM_ARCH_EXT_IDIV__
|
||||
#define use_idiv_instructions 1
|
||||
#else
|
||||
extern bool use_idiv_instructions_rt;
|
||||
#define use_idiv_instructions use_idiv_instructions_rt
|
||||
extern bool use_idiv_instructions;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -78,7 +110,13 @@ extern bool use_idiv_instructions_rt;
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_clz_i32 use_armv5t_instructions
|
||||
#define TCG_TARGET_HAS_ctz_i32 use_armv7_instructions
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 use_armv7_instructions
|
||||
#define TCG_TARGET_HAS_extract_i32 use_armv7_instructions
|
||||
#define TCG_TARGET_HAS_sextract_i32 use_armv7_instructions
|
||||
#define TCG_TARGET_HAS_extract2_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
@@ -86,24 +124,27 @@ extern bool use_idiv_instructions_rt;
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
|
||||
extern bool tcg_target_deposit_valid(int ofs, int len);
|
||||
#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 0
|
||||
|
||||
enum {
|
||||
TCG_AREG0 = TCG_REG_R6,
|
||||
};
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(4, 1)
|
||||
__builtin___clear_cache((char *) start, (char *) stop);
|
||||
#else
|
||||
register uintptr_t _beg __asm("a1") = start;
|
||||
register uintptr_t _end __asm("a2") = stop;
|
||||
register uintptr_t _flg __asm("a3") = 0;
|
||||
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* not defined -- call should be eliminated at compile time */
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,17 +21,19 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_I386
|
||||
#define TCG_TARGET_I386 1
|
||||
|
||||
#ifndef I386_TCG_TARGET_H
|
||||
#define I386_TCG_TARGET_H
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 1
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 31
|
||||
|
||||
#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 {
|
||||
@@ -54,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,
|
||||
@@ -62,18 +84,23 @@ typedef enum {
|
||||
TCG_REG_RBP = TCG_REG_EBP,
|
||||
TCG_REG_RSI = TCG_REG_ESI,
|
||||
TCG_REG_RDI = TCG_REG_EDI,
|
||||
|
||||
TCG_AREG0 = TCG_REG_EBP,
|
||||
TCG_REG_CALL_STACK = TCG_REG_ESP
|
||||
} TCGReg;
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_ESP
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#if defined(_WIN64) || (defined(__CYGWIN__) && defined(__x86_64__))
|
||||
#if defined(_WIN64)
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 32
|
||||
#else
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
#endif
|
||||
|
||||
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
|
||||
@@ -91,7 +118,13 @@ extern bool have_bmi1;
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 1
|
||||
#define TCG_TARGET_HAS_ctz_i32 1
|
||||
#define TCG_TARGET_HAS_ctpop_i32 have_popcnt
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_extract_i32 1
|
||||
#define TCG_TARGET_HAS_sextract_i32 1
|
||||
#define TCG_TARGET_HAS_extract2_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
@@ -99,9 +132,13 @@ extern bool have_bmi1;
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
/* Keep target addresses zero-extended in a register. */
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 (TARGET_LONG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 (TARGET_LONG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_div2_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
@@ -120,7 +157,13 @@ extern bool have_bmi1;
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 1
|
||||
#define TCG_TARGET_HAS_ctz_i64 1
|
||||
#define TCG_TARGET_HAS_ctpop_i64 have_popcnt
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_extract_i64 1
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
@@ -130,19 +173,63 @@ extern bool have_bmi1;
|
||||
#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_abs_vec 1
|
||||
#define TCG_TARGET_HAS_shi_vec 1
|
||||
#define TCG_TARGET_HAS_shs_vec 1
|
||||
#define TCG_TARGET_HAS_shv_vec have_avx2
|
||||
#define TCG_TARGET_HAS_cmp_vec 1
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
#define TCG_TARGET_HAS_sat_vec 1
|
||||
#define TCG_TARGET_HAS_minmax_vec 1
|
||||
#define TCG_TARGET_HAS_bitsel_vec 0
|
||||
#define TCG_TARGET_HAS_cmpsel_vec -1
|
||||
|
||||
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
|
||||
(((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
|
||||
((ofs) == 0 && (len) == 16))
|
||||
#define TCG_TARGET_deposit_i64_valid TCG_TARGET_deposit_i32_valid
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
# define TCG_AREG0 TCG_REG_R14
|
||||
#else
|
||||
# define TCG_AREG0 TCG_REG_EBP
|
||||
#endif
|
||||
/* Check for the possibility of high-byte extraction and, for 64-bit,
|
||||
zero-extending 32-bit right-shift. */
|
||||
#define TCG_TARGET_extract_i32_valid(ofs, len) ((ofs) == 8 && (len) == 8)
|
||||
#define TCG_TARGET_extract_i64_valid(ofs, len) \
|
||||
(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
|
||||
uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
*(int32_t *)jmp_addr = addr - (jmp_addr + 4);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
|
||||
/* This defines the natural memory order supported by this
|
||||
* architecture before guarantees made by various barrier
|
||||
* instructions.
|
||||
*
|
||||
* The x86 has a pretty strong memory ordering which only really
|
||||
* allows for some stores to be re-ordered after loads.
|
||||
*/
|
||||
#include "tcg/tcg-mo.h"
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
|
||||
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif
|
||||
|
||||
3918
qemu/tcg/i386/tcg-target.inc.c
Normal file
3918
qemu/tcg/i386/tcg-target.inc.c
Normal file
File diff suppressed because it is too large
Load Diff
35
qemu/tcg/i386/tcg-target.opc.h
Normal file
35
qemu/tcg/i386/tcg-target.opc.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Linaro
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* 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)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Tiny Code Generator for QEMU
|
||||
*
|
||||
* Copyright (c) 2009-2010 Aurelien Jarno <aurelien@aurel32.net>
|
||||
* Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_IA64
|
||||
#define TCG_TARGET_IA64 1
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 16
|
||||
typedef struct {
|
||||
uint64_t QEMU_ALIGN(16, lo);
|
||||
uint64_t hi;
|
||||
} tcg_insn_unit;
|
||||
|
||||
/* We only map the first 64 registers */
|
||||
#define TCG_TARGET_NB_REGS 64
|
||||
typedef enum {
|
||||
TCG_REG_R0 = 0,
|
||||
TCG_REG_R1,
|
||||
TCG_REG_R2,
|
||||
TCG_REG_R3,
|
||||
TCG_REG_R4,
|
||||
TCG_REG_R5,
|
||||
TCG_REG_R6,
|
||||
TCG_REG_R7,
|
||||
TCG_REG_R8,
|
||||
TCG_REG_R9,
|
||||
TCG_REG_R10,
|
||||
TCG_REG_R11,
|
||||
TCG_REG_R12,
|
||||
TCG_REG_R13,
|
||||
TCG_REG_R14,
|
||||
TCG_REG_R15,
|
||||
TCG_REG_R16,
|
||||
TCG_REG_R17,
|
||||
TCG_REG_R18,
|
||||
TCG_REG_R19,
|
||||
TCG_REG_R20,
|
||||
TCG_REG_R21,
|
||||
TCG_REG_R22,
|
||||
TCG_REG_R23,
|
||||
TCG_REG_R24,
|
||||
TCG_REG_R25,
|
||||
TCG_REG_R26,
|
||||
TCG_REG_R27,
|
||||
TCG_REG_R28,
|
||||
TCG_REG_R29,
|
||||
TCG_REG_R30,
|
||||
TCG_REG_R31,
|
||||
TCG_REG_R32,
|
||||
TCG_REG_R33,
|
||||
TCG_REG_R34,
|
||||
TCG_REG_R35,
|
||||
TCG_REG_R36,
|
||||
TCG_REG_R37,
|
||||
TCG_REG_R38,
|
||||
TCG_REG_R39,
|
||||
TCG_REG_R40,
|
||||
TCG_REG_R41,
|
||||
TCG_REG_R42,
|
||||
TCG_REG_R43,
|
||||
TCG_REG_R44,
|
||||
TCG_REG_R45,
|
||||
TCG_REG_R46,
|
||||
TCG_REG_R47,
|
||||
TCG_REG_R48,
|
||||
TCG_REG_R49,
|
||||
TCG_REG_R50,
|
||||
TCG_REG_R51,
|
||||
TCG_REG_R52,
|
||||
TCG_REG_R53,
|
||||
TCG_REG_R54,
|
||||
TCG_REG_R55,
|
||||
TCG_REG_R56,
|
||||
TCG_REG_R57,
|
||||
TCG_REG_R58,
|
||||
TCG_REG_R59,
|
||||
TCG_REG_R60,
|
||||
TCG_REG_R61,
|
||||
TCG_REG_R62,
|
||||
TCG_REG_R63,
|
||||
|
||||
TCG_AREG0 = TCG_REG_R32,
|
||||
} TCGReg;
|
||||
|
||||
#define TCG_CT_CONST_ZERO 0x100
|
||||
#define TCG_CT_CONST_S22 0x200
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_R12
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 16
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div_i32 0
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
#define TCG_TARGET_HAS_div_i64 0
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#define TCG_TARGET_HAS_andc_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i64 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i64 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||
#define TCG_TARGET_HAS_eqv_i32 1
|
||||
#define TCG_TARGET_HAS_eqv_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i64 1
|
||||
#define TCG_TARGET_HAS_ext16u_i64 1
|
||||
#define TCG_TARGET_HAS_ext32u_i64 1
|
||||
#define TCG_TARGET_HAS_nand_i32 1
|
||||
#define TCG_TARGET_HAS_nand_i64 1
|
||||
#define TCG_TARGET_HAS_nor_i32 1
|
||||
#define TCG_TARGET_HAS_nor_i64 1
|
||||
#define TCG_TARGET_HAS_orc_i32 1
|
||||
#define TCG_TARGET_HAS_orc_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i32 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
|
||||
#define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16)
|
||||
#define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16)
|
||||
|
||||
/* optional instructions automatically implemented */
|
||||
#define TCG_TARGET_HAS_neg_i32 0 /* sub r1, r0, r3 */
|
||||
#define TCG_TARGET_HAS_neg_i64 0 /* sub r1, r0, r3 */
|
||||
#define TCG_TARGET_HAS_not_i32 0 /* xor r1, -1, r3 */
|
||||
#define TCG_TARGET_HAS_not_i64 0 /* xor r1, -1, r3 */
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
start = start & ~(32UL - 1UL);
|
||||
stop = (stop + (32UL - 1UL)) & ~(32UL - 1UL);
|
||||
|
||||
for (; start < stop; start += 32UL) {
|
||||
asm volatile ("fc.i %0" :: "r" (start));
|
||||
}
|
||||
asm volatile (";;sync.i;;srlz.i;;");
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,20 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_MIPS
|
||||
#define TCG_TARGET_MIPS 1
|
||||
|
||||
#ifndef MIPS_TCG_TARGET_H
|
||||
#define MIPS_TCG_TARGET_H
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
# define TCG_TARGET_REG_BITS 32
|
||||
#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
|
||||
# define TCG_TARGET_REG_BITS 64
|
||||
#else
|
||||
# error "Unknown ABI"
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
@@ -68,9 +78,13 @@ typedef enum {
|
||||
} TCGReg;
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_TARGET_STACK_ALIGN 8
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 16
|
||||
#define TCG_TARGET_CALL_ALIGN_ARGS 1
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
# define TCG_TARGET_CALL_STACK_OFFSET 16
|
||||
#else
|
||||
# define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
#endif
|
||||
#define TCG_TARGET_CALL_ALIGN_ARGS 1
|
||||
|
||||
/* MOVN/MOVZ instructions detection */
|
||||
#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
|
||||
@@ -95,6 +109,13 @@ extern bool use_mips32_instructions;
|
||||
extern bool use_mips32r2_instructions;
|
||||
#endif
|
||||
|
||||
/* MIPS32R6 instruction set detection */
|
||||
#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6)
|
||||
#define use_mips32r6_instructions 1
|
||||
#else
|
||||
#define use_mips32r6_instructions 0
|
||||
#endif
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 1
|
||||
@@ -104,34 +125,97 @@ extern bool use_mips32r2_instructions;
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_mulu2_i32 1
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 (!use_mips32r6_instructions)
|
||||
#define TCG_TARGET_HAS_muls2_i32 (!use_mips32r6_instructions)
|
||||
#define TCG_TARGET_HAS_muluh_i32 1
|
||||
#define TCG_TARGET_HAS_mulsh_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 1
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 1
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
#define TCG_TARGET_HAS_not_i64 1
|
||||
#define TCG_TARGET_HAS_nor_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_add2_i64 0
|
||||
#define TCG_TARGET_HAS_sub2_i64 0
|
||||
#define TCG_TARGET_HAS_mulu2_i64 (!use_mips32r6_instructions)
|
||||
#define TCG_TARGET_HAS_muls2_i64 (!use_mips32r6_instructions)
|
||||
#define TCG_TARGET_HAS_muluh_i64 1
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32u_i64 1
|
||||
#endif
|
||||
|
||||
/* optional instructions detected at runtime */
|
||||
#define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions
|
||||
#define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_bswap32_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_extract_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_sextract_i32 0
|
||||
#define TCG_TARGET_HAS_extract2_i32 0
|
||||
#define TCG_TARGET_HAS_ext8s_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_clz_i32 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_ctz_i32 0
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_movcond_i64 use_movnz_instructions
|
||||
#define TCG_TARGET_HAS_bswap16_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_bswap32_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_bswap64_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_deposit_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_extract_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 0
|
||||
#define TCG_TARGET_HAS_ext8s_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_ext16s_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_rot_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_clz_i64 use_mips32r2_instructions
|
||||
#define TCG_TARGET_HAS_ctz_i64 0
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#endif
|
||||
|
||||
/* optional instructions automatically implemented */
|
||||
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
|
||||
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */
|
||||
#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_neg_i64 0 /* sub rd, zero, rt */
|
||||
#define TCG_TARGET_HAS_ext8u_i64 0 /* andi rt, rs, 0xff */
|
||||
#define TCG_TARGET_HAS_ext16u_i64 0 /* andi rt, rs, 0xffff */
|
||||
#endif
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#include <machine/sysarch.h>
|
||||
#else
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
cacheflush ((void *)start, stop-start, ICACHE);
|
||||
}
|
||||
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
2714
qemu/tcg/mips/tcg-target.inc.c
Normal file
2714
qemu/tcg/mips/tcg-target.inc.c
Normal file
File diff suppressed because it is too large
Load Diff
1243
qemu/tcg/optimize.c
1243
qemu/tcg/optimize.c
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,9 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_PPC64
|
||||
#define TCG_TARGET_PPC64 1
|
||||
|
||||
#ifndef PPC_TCG_TARGET_H
|
||||
#define PPC_TCG_TARGET_H
|
||||
|
||||
#ifdef _ARCH_PPC64
|
||||
# define TCG_TARGET_REG_BITS 64
|
||||
@@ -30,8 +31,9 @@
|
||||
# define TCG_TARGET_REG_BITS 32
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
#define TCG_TARGET_NB_REGS 64
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
|
||||
|
||||
typedef enum {
|
||||
TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3,
|
||||
@@ -43,10 +45,34 @@ typedef enum {
|
||||
TCG_REG_R24, TCG_REG_R25, TCG_REG_R26, TCG_REG_R27,
|
||||
TCG_REG_R28, TCG_REG_R29, TCG_REG_R30, TCG_REG_R31,
|
||||
|
||||
TCG_REG_V0, 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,
|
||||
|
||||
TCG_REG_CALL_STACK = TCG_REG_R1,
|
||||
TCG_AREG0 = TCG_REG_R27
|
||||
} TCGReg;
|
||||
|
||||
typedef enum {
|
||||
tcg_isa_base,
|
||||
tcg_isa_2_06,
|
||||
tcg_isa_2_07,
|
||||
tcg_isa_3_00,
|
||||
} TCGPowerISA;
|
||||
|
||||
extern TCGPowerISA have_isa;
|
||||
extern bool have_altivec;
|
||||
extern bool have_vsx;
|
||||
|
||||
#define have_isa_2_06 (have_isa >= tcg_isa_2_06)
|
||||
#define have_isa_2_07 (have_isa >= tcg_isa_2_07)
|
||||
#define have_isa_3_00 (have_isa >= tcg_isa_3_00)
|
||||
|
||||
/* optional instructions automatically implemented */
|
||||
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */
|
||||
#define TCG_TARGET_HAS_ext16u_i32 0
|
||||
@@ -66,17 +92,26 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_eqv_i32 1
|
||||
#define TCG_TARGET_HAS_nand_i32 1
|
||||
#define TCG_TARGET_HAS_nor_i32 1
|
||||
#define TCG_TARGET_HAS_clz_i32 1
|
||||
#define TCG_TARGET_HAS_ctz_i32 have_isa_3_00
|
||||
#define TCG_TARGET_HAS_ctpop_i32 have_isa_2_06
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_extract_i32 1
|
||||
#define TCG_TARGET_HAS_sextract_i32 0
|
||||
#define TCG_TARGET_HAS_extract2_i32 0
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 1
|
||||
#define TCG_TARGET_HAS_mulsh_i32 1
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_add2_i32 0
|
||||
#define TCG_TARGET_HAS_sub2_i32 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
@@ -96,7 +131,13 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_eqv_i64 1
|
||||
#define TCG_TARGET_HAS_nand_i64 1
|
||||
#define TCG_TARGET_HAS_nor_i64 1
|
||||
#define TCG_TARGET_HAS_clz_i64 1
|
||||
#define TCG_TARGET_HAS_ctz_i64 have_isa_3_00
|
||||
#define TCG_TARGET_HAS_ctpop_i64 have_isa_2_06
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_extract_i64 1
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 0
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
@@ -106,6 +147,39 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* While technically Altivec could support V64, it has no 64-bit store
|
||||
* instruction and substituting two 32-bit stores makes the generated
|
||||
* code quite large.
|
||||
*/
|
||||
#define TCG_TARGET_HAS_v64 have_vsx
|
||||
#define TCG_TARGET_HAS_v128 have_altivec
|
||||
#define TCG_TARGET_HAS_v256 0
|
||||
|
||||
#define TCG_TARGET_HAS_andc_vec 1
|
||||
#define TCG_TARGET_HAS_orc_vec have_isa_2_07
|
||||
#define TCG_TARGET_HAS_not_vec 1
|
||||
#define TCG_TARGET_HAS_neg_vec have_isa_3_00
|
||||
#define TCG_TARGET_HAS_abs_vec 0
|
||||
#define TCG_TARGET_HAS_shi_vec 0
|
||||
#define TCG_TARGET_HAS_shs_vec 0
|
||||
#define TCG_TARGET_HAS_shv_vec 1
|
||||
#define TCG_TARGET_HAS_cmp_vec 1
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
#define TCG_TARGET_HAS_sat_vec 1
|
||||
#define TCG_TARGET_HAS_minmax_vec 1
|
||||
#define TCG_TARGET_HAS_bitsel_vec have_vsx
|
||||
#define TCG_TARGET_HAS_cmpsel_vec 0
|
||||
|
||||
void flush_icache_range(uintptr_t start, uintptr_t stop);
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* TCG Backend Data: No backend data
|
||||
* Copyright (c) 2019 Linaro Limited
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -18,28 +18,16 @@
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "tcg.h"
|
||||
|
||||
typedef struct TCGBackendData {
|
||||
/* Empty */
|
||||
char dummy;
|
||||
} TCGBackendData;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize TB backend data at the beginning of the TB.
|
||||
*/
|
||||
|
||||
static inline void tcg_out_tb_init(TCGContext *s)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate TB finalization at the end of block
|
||||
*/
|
||||
|
||||
static inline void tcg_out_tb_finalize(TCGContext *s)
|
||||
{
|
||||
}
|
||||
DEF(ppc_mrgh_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(ppc_mrgl_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(ppc_msum_vec, 1, 3, 0, IMPLVEC)
|
||||
DEF(ppc_muleu_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(ppc_mulou_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(ppc_pkum_vec, 1, 2, 0, IMPLVEC)
|
||||
DEF(ppc_rotl_vec, 1, 2, 0, IMPLVEC)
|
||||
179
qemu/tcg/riscv/tcg-target.h
Normal file
179
qemu/tcg/riscv/tcg-target.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Tiny Code Generator for QEMU
|
||||
*
|
||||
* Copyright (c) 2018 SiFive, Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef RISCV_TCG_TARGET_H
|
||||
#define RISCV_TCG_TARGET_H
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
# define TCG_TARGET_REG_BITS 32
|
||||
#elif __riscv_xlen == 64
|
||||
# define TCG_TARGET_REG_BITS 64
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 20
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
TCG_REG_ZERO,
|
||||
TCG_REG_RA,
|
||||
TCG_REG_SP,
|
||||
TCG_REG_GP,
|
||||
TCG_REG_TP,
|
||||
TCG_REG_T0,
|
||||
TCG_REG_T1,
|
||||
TCG_REG_T2,
|
||||
TCG_REG_S0,
|
||||
TCG_REG_S1,
|
||||
TCG_REG_A0,
|
||||
TCG_REG_A1,
|
||||
TCG_REG_A2,
|
||||
TCG_REG_A3,
|
||||
TCG_REG_A4,
|
||||
TCG_REG_A5,
|
||||
TCG_REG_A6,
|
||||
TCG_REG_A7,
|
||||
TCG_REG_S2,
|
||||
TCG_REG_S3,
|
||||
TCG_REG_S4,
|
||||
TCG_REG_S5,
|
||||
TCG_REG_S6,
|
||||
TCG_REG_S7,
|
||||
TCG_REG_S8,
|
||||
TCG_REG_S9,
|
||||
TCG_REG_S10,
|
||||
TCG_REG_S11,
|
||||
TCG_REG_T3,
|
||||
TCG_REG_T4,
|
||||
TCG_REG_T5,
|
||||
TCG_REG_T6,
|
||||
|
||||
/* aliases */
|
||||
TCG_AREG0 = TCG_REG_S0,
|
||||
TCG_GUEST_BASE_REG = TCG_REG_S1,
|
||||
TCG_REG_TMP0 = TCG_REG_T6,
|
||||
TCG_REG_TMP1 = TCG_REG_T5,
|
||||
TCG_REG_TMP2 = TCG_REG_T4,
|
||||
} TCGReg;
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_SP
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#define TCG_TARGET_CALL_ALIGN_ARGS 1
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 1
|
||||
#define TCG_TARGET_HAS_div2_i32 0
|
||||
#define TCG_TARGET_HAS_rot_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 0
|
||||
#define TCG_TARGET_HAS_extract_i32 0
|
||||
#define TCG_TARGET_HAS_sextract_i32 0
|
||||
#define TCG_TARGET_HAS_extract2_i32 0
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 (TCG_TARGET_REG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_mulsh_i32 (TCG_TARGET_REG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 0
|
||||
#define TCG_TARGET_HAS_bswap32_i32 0
|
||||
#define TCG_TARGET_HAS_not_i32 1
|
||||
#define TCG_TARGET_HAS_neg_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i32 0
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 0
|
||||
#define TCG_TARGET_HAS_ctz_i32 0
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_direct_jump 0
|
||||
#define TCG_TARGET_HAS_brcond2 1
|
||||
#define TCG_TARGET_HAS_setcond2 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_movcond_i64 0
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 1
|
||||
#define TCG_TARGET_HAS_div2_i64 0
|
||||
#define TCG_TARGET_HAS_rot_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 0
|
||||
#define TCG_TARGET_HAS_extract_i64 0
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 1
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
#define TCG_TARGET_HAS_ext8u_i64 1
|
||||
#define TCG_TARGET_HAS_ext16u_i64 1
|
||||
#define TCG_TARGET_HAS_ext32u_i64 1
|
||||
#define TCG_TARGET_HAS_bswap16_i64 0
|
||||
#define TCG_TARGET_HAS_bswap32_i64 0
|
||||
#define TCG_TARGET_HAS_bswap64_i64 0
|
||||
#define TCG_TARGET_HAS_not_i64 1
|
||||
#define TCG_TARGET_HAS_neg_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 0
|
||||
#define TCG_TARGET_HAS_ctz_i64 0
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_mulu2_i64 0
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 1
|
||||
#define TCG_TARGET_HAS_mulsh_i64 1
|
||||
#endif
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
__builtin___clear_cache((char *)start, (char *)stop);
|
||||
}
|
||||
|
||||
/* not defined -- call should be eliminated at compile time */
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
|
||||
|
||||
#endif
|
||||
1920
qemu/tcg/riscv/tcg-target.inc.c
Normal file
1920
qemu/tcg/riscv/tcg-target.inc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -21,10 +21,12 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_S390
|
||||
#define TCG_TARGET_S390 1
|
||||
|
||||
#ifndef S390_TCG_TARGET_H
|
||||
#define S390_TCG_TARGET_H
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 2
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 19
|
||||
|
||||
typedef enum TCGReg {
|
||||
TCG_REG_R0 = 0,
|
||||
@@ -47,62 +49,87 @@ typedef enum TCGReg {
|
||||
|
||||
#define TCG_TARGET_NB_REGS 16
|
||||
|
||||
/* A list of relevant facilities used by this translator. Some of these
|
||||
are required for proper operation, and these are checked at startup. */
|
||||
|
||||
#define FACILITY_ZARCH_ACTIVE (1ULL << (63 - 2))
|
||||
#define FACILITY_LONG_DISP (1ULL << (63 - 18))
|
||||
#define FACILITY_EXT_IMM (1ULL << (63 - 21))
|
||||
#define FACILITY_GEN_INST_EXT (1ULL << (63 - 34))
|
||||
#define FACILITY_LOAD_ON_COND (1ULL << (63 - 45))
|
||||
#define FACILITY_FAST_BCR_SER FACILITY_LOAD_ON_COND
|
||||
#define FACILITY_DISTINCT_OPS FACILITY_LOAD_ON_COND
|
||||
#define FACILITY_LOAD_ON_COND2 (1ULL << (63 - 53))
|
||||
|
||||
extern uint64_t s390_facilities;
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div2_i32 1
|
||||
#define TCG_TARGET_HAS_rot_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_not_i32 0
|
||||
#define TCG_TARGET_HAS_neg_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i32 0
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 0
|
||||
#define TCG_TARGET_HAS_div2_i32 1
|
||||
#define TCG_TARGET_HAS_rot_i32 1
|
||||
#define TCG_TARGET_HAS_ext8s_i32 1
|
||||
#define TCG_TARGET_HAS_ext16s_i32 1
|
||||
#define TCG_TARGET_HAS_ext8u_i32 1
|
||||
#define TCG_TARGET_HAS_ext16u_i32 1
|
||||
#define TCG_TARGET_HAS_bswap16_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_not_i32 0
|
||||
#define TCG_TARGET_HAS_neg_i32 1
|
||||
#define TCG_TARGET_HAS_andc_i32 0
|
||||
#define TCG_TARGET_HAS_orc_i32 0
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 0
|
||||
#define TCG_TARGET_HAS_ctz_i32 0
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
#define TCG_TARGET_HAS_extract_i32 (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
#define TCG_TARGET_HAS_sextract_i32 0
|
||||
#define TCG_TARGET_HAS_extract2_i32 0
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
#define TCG_TARGET_HAS_mulu2_i32 0
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
|
||||
#define TCG_TARGET_HAS_div2_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
#define TCG_TARGET_HAS_ext8u_i64 1
|
||||
#define TCG_TARGET_HAS_ext16u_i64 1
|
||||
#define TCG_TARGET_HAS_ext32u_i64 1
|
||||
#define TCG_TARGET_HAS_bswap16_i64 1
|
||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||
#define TCG_TARGET_HAS_not_i64 0
|
||||
#define TCG_TARGET_HAS_neg_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 1
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_mulu2_i64 1
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
|
||||
extern bool tcg_target_deposit_valid(int ofs, int len);
|
||||
#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid
|
||||
#define TCG_TARGET_deposit_i64_valid tcg_target_deposit_valid
|
||||
#define TCG_TARGET_HAS_div2_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
#define TCG_TARGET_HAS_ext16s_i64 1
|
||||
#define TCG_TARGET_HAS_ext32s_i64 1
|
||||
#define TCG_TARGET_HAS_ext8u_i64 1
|
||||
#define TCG_TARGET_HAS_ext16u_i64 1
|
||||
#define TCG_TARGET_HAS_ext32u_i64 1
|
||||
#define TCG_TARGET_HAS_bswap16_i64 1
|
||||
#define TCG_TARGET_HAS_bswap32_i64 1
|
||||
#define TCG_TARGET_HAS_bswap64_i64 1
|
||||
#define TCG_TARGET_HAS_not_i64 0
|
||||
#define TCG_TARGET_HAS_neg_i64 1
|
||||
#define TCG_TARGET_HAS_andc_i64 0
|
||||
#define TCG_TARGET_HAS_orc_i64 0
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 (s390_facilities & FACILITY_EXT_IMM)
|
||||
#define TCG_TARGET_HAS_ctz_i64 0
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
#define TCG_TARGET_HAS_extract_i64 (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 0
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
#define TCG_TARGET_HAS_mulu2_i64 1
|
||||
#define TCG_TARGET_HAS_muls2_i64 0
|
||||
#define TCG_TARGET_HAS_muluh_i64 0
|
||||
#define TCG_TARGET_HAS_mulsh_i64 0
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_R15
|
||||
@@ -110,6 +137,9 @@ extern bool tcg_target_deposit_valid(int ofs, int len);
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 160
|
||||
|
||||
#define TCG_TARGET_EXTEND_ARGS 1
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
|
||||
|
||||
enum {
|
||||
TCG_AREG0 = TCG_REG_R10,
|
||||
@@ -119,4 +149,18 @@ static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
|
||||
uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
intptr_t disp = addr - (jmp_addr - 2);
|
||||
atomic_set((int32_t *)jmp_addr, disp / 2);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,12 +21,14 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TCG_TARGET_SPARC
|
||||
#define TCG_TARGET_SPARC 1
|
||||
|
||||
#ifndef SPARC_TCG_TARGET_H
|
||||
#define SPARC_TCG_TARGET_H
|
||||
|
||||
#define TCG_TARGET_REG_BITS 64
|
||||
|
||||
#define TCG_TARGET_INSN_UNIT_SIZE 4
|
||||
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 32
|
||||
#define TCG_TARGET_NB_REGS 32
|
||||
|
||||
typedef enum {
|
||||
@@ -108,7 +110,13 @@ extern bool use_vis3_instructions;
|
||||
#define TCG_TARGET_HAS_eqv_i32 0
|
||||
#define TCG_TARGET_HAS_nand_i32 0
|
||||
#define TCG_TARGET_HAS_nor_i32 0
|
||||
#define TCG_TARGET_HAS_clz_i32 0
|
||||
#define TCG_TARGET_HAS_ctz_i32 0
|
||||
#define TCG_TARGET_HAS_ctpop_i32 0
|
||||
#define TCG_TARGET_HAS_deposit_i32 0
|
||||
#define TCG_TARGET_HAS_extract_i32 0
|
||||
#define TCG_TARGET_HAS_sextract_i32 0
|
||||
#define TCG_TARGET_HAS_extract2_i32 0
|
||||
#define TCG_TARGET_HAS_movcond_i32 1
|
||||
#define TCG_TARGET_HAS_add2_i32 1
|
||||
#define TCG_TARGET_HAS_sub2_i32 1
|
||||
@@ -116,8 +124,11 @@ extern bool use_vis3_instructions;
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#define TCG_TARGET_HAS_trunc_shr_i32 1
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 1
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 1
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
#define TCG_TARGET_HAS_rem_i64 0
|
||||
#define TCG_TARGET_HAS_rot_i64 0
|
||||
@@ -137,7 +148,13 @@ extern bool use_vis3_instructions;
|
||||
#define TCG_TARGET_HAS_eqv_i64 0
|
||||
#define TCG_TARGET_HAS_nand_i64 0
|
||||
#define TCG_TARGET_HAS_nor_i64 0
|
||||
#define TCG_TARGET_HAS_clz_i64 0
|
||||
#define TCG_TARGET_HAS_ctz_i64 0
|
||||
#define TCG_TARGET_HAS_ctpop_i64 0
|
||||
#define TCG_TARGET_HAS_deposit_i64 0
|
||||
#define TCG_TARGET_HAS_extract_i64 0
|
||||
#define TCG_TARGET_HAS_sextract_i64 0
|
||||
#define TCG_TARGET_HAS_extract2_i64 0
|
||||
#define TCG_TARGET_HAS_movcond_i64 1
|
||||
#define TCG_TARGET_HAS_add2_i64 1
|
||||
#define TCG_TARGET_HAS_sub2_i64 1
|
||||
@@ -148,13 +165,9 @@ extern bool use_vis3_instructions;
|
||||
|
||||
#define TCG_AREG0 TCG_REG_I0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
FlushInstructionCache(GetCurrentProcess(), (const void*)start, stop-start);
|
||||
}
|
||||
#else
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
uintptr_t p;
|
||||
@@ -162,6 +175,9 @@ static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
__asm__ __volatile__("flush\t%0" : : "r" (p));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#define TCG_TARGET_NEED_POOL_LABELS
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,57 +20,48 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_MAX_QEMU_LDST 640
|
||||
|
||||
typedef struct TCGLabelQemuLdst {
|
||||
bool is_ld; /* qemu_ld: true, qemu_st: false */
|
||||
TCGMemOp opc;
|
||||
TCGMemOpIdx oi;
|
||||
TCGType type; /* result type of a load */
|
||||
TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */
|
||||
TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */
|
||||
TCGReg datalo_reg; /* reg index for low word to be loaded or stored */
|
||||
TCGReg datahi_reg; /* reg index for high word to be loaded or stored */
|
||||
int mem_index; /* soft MMU memory index */
|
||||
tcg_insn_unit *raddr; /* gen code addr of the next IR of qemu_ld/st IR */
|
||||
tcg_insn_unit *label_ptr[2]; /* label pointers to be updated */
|
||||
QSIMPLEQ_ENTRY(TCGLabelQemuLdst) next;
|
||||
} TCGLabelQemuLdst;
|
||||
|
||||
typedef struct TCGBackendData {
|
||||
int nb_ldst_labels;
|
||||
TCGLabelQemuLdst ldst_labels[TCG_MAX_QEMU_LDST];
|
||||
} TCGBackendData;
|
||||
|
||||
|
||||
/*
|
||||
* Initialize TB backend data at the beginning of the TB.
|
||||
*/
|
||||
|
||||
static inline void tcg_out_tb_init(TCGContext *s)
|
||||
{
|
||||
s->be->nb_ldst_labels = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate TB finalization at the end of block
|
||||
*/
|
||||
|
||||
static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
|
||||
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
|
||||
static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
|
||||
static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l);
|
||||
|
||||
static void tcg_out_tb_finalize(TCGContext *s)
|
||||
static int tcg_out_ldst_finalize(TCGContext *s)
|
||||
{
|
||||
TCGLabelQemuLdst *lb = s->be->ldst_labels;
|
||||
int i, n = s->be->nb_ldst_labels;
|
||||
TCGLabelQemuLdst *lb;
|
||||
|
||||
/* qemu_ld/st slow paths */
|
||||
for (i = 0; i < n; i++) {
|
||||
if (lb[i].is_ld) {
|
||||
tcg_out_qemu_ld_slow_path(s, lb + i);
|
||||
} else {
|
||||
tcg_out_qemu_st_slow_path(s, lb + i);
|
||||
QSIMPLEQ_FOREACH(lb, &s->ldst_labels, next) {
|
||||
if (lb->is_ld
|
||||
? !tcg_out_qemu_ld_slow_path(s, lb)
|
||||
: !tcg_out_qemu_st_slow_path(s, lb)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Test for (pending) buffer overflow. The assumption is that any
|
||||
one operation beginning below the high water mark cannot overrun
|
||||
the buffer completely. Thus we can test for overflow after
|
||||
generating code without having to check during generation. */
|
||||
if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -79,13 +70,9 @@ static void tcg_out_tb_finalize(TCGContext *s)
|
||||
|
||||
static inline TCGLabelQemuLdst *new_ldst_label(TCGContext *s)
|
||||
{
|
||||
TCGBackendData *be = s->be;
|
||||
int n = be->nb_ldst_labels;
|
||||
TCGLabelQemuLdst *l = tcg_malloc(s, sizeof(*l));
|
||||
|
||||
assert(n < TCG_MAX_QEMU_LDST);
|
||||
be->nb_ldst_labels = n + 1;
|
||||
return &be->ldst_labels[n];
|
||||
QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next);
|
||||
|
||||
return l;
|
||||
}
|
||||
#else
|
||||
#include "tcg-be-null.h"
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
3254
qemu/tcg/tcg-op-gvec.c
Normal file
3254
qemu/tcg/tcg-op-gvec.c
Normal file
File diff suppressed because it is too large
Load Diff
806
qemu/tcg/tcg-op-vec.c
Normal file
806
qemu/tcg/tcg-op-vec.c
Normal file
@@ -0,0 +1,806 @@
|
||||
/*
|
||||
* 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.1 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 "cpu.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "tcg/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
|
||||
|
||||
/*
|
||||
* Vector optional opcode tracking.
|
||||
* Except for the basic logical operations (and, or, xor), and
|
||||
* data movement (mov, ld, st, dupi), many vector opcodes are
|
||||
* optional and may not be supported on the host. Thank Intel
|
||||
* for the irregularity in their instruction set.
|
||||
*
|
||||
* The gvec expanders allow custom vector operations to be composed,
|
||||
* generally via the .fniv callback in the GVecGen* structures. At
|
||||
* the same time, in deciding whether to use this hook we need to
|
||||
* know if the host supports the required operations. This is
|
||||
* presented as an array of opcodes, terminated by 0. Each opcode
|
||||
* is assumed to be expanded with the given VECE.
|
||||
*
|
||||
* For debugging, we want to validate this array. Therefore, when
|
||||
* tcg_ctx->vec_opt_opc is non-NULL, the tcg_gen_*_vec expanders
|
||||
* will validate that their opcode is present in the list.
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
void tcg_assert_listed_vecop(TCGOpcode op)
|
||||
{
|
||||
const TCGOpcode *p = tcg_ctx->vecop_list;
|
||||
if (p) {
|
||||
for (; *p; ++p) {
|
||||
if (*p == op) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool tcg_can_emit_vecop_list(TCGContext *tcg_ctx, const TCGOpcode *list,
|
||||
TCGType type, unsigned vece)
|
||||
{
|
||||
if (list == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (; *list; ++list) {
|
||||
TCGOpcode opc = *list;
|
||||
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
switch (opc) {
|
||||
case INDEX_op_and_vec:
|
||||
case INDEX_op_or_vec:
|
||||
case INDEX_op_xor_vec:
|
||||
case INDEX_op_mov_vec:
|
||||
case INDEX_op_dup_vec:
|
||||
case INDEX_op_dupi_vec:
|
||||
case INDEX_op_dup2_vec:
|
||||
case INDEX_op_ld_vec:
|
||||
case INDEX_op_st_vec:
|
||||
case INDEX_op_bitsel_vec:
|
||||
/* These opcodes are mandatory and should not be listed. */
|
||||
g_assert_not_reached();
|
||||
case INDEX_op_not_vec:
|
||||
/* These opcodes have generic expansions using the above. */
|
||||
g_assert_not_reached();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, opc, type, vece)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The opcode list is created by front ends based on what they
|
||||
* actually invoke. We must mirror the logic in the routines
|
||||
* below for generic expansions using other opcodes.
|
||||
*/
|
||||
switch (opc) {
|
||||
case INDEX_op_neg_vec:
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_sub_vec, type, vece)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case INDEX_op_abs_vec:
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_sub_vec, type, vece)
|
||||
&& (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_smax_vec, type, vece) > 0
|
||||
|| tcg_can_emit_vec_op(tcg_ctx, INDEX_op_sari_vec, type, vece) > 0
|
||||
|| tcg_can_emit_vec_op(tcg_ctx, INDEX_op_cmp_vec, type, vece))) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case INDEX_op_cmpsel_vec:
|
||||
case INDEX_op_smin_vec:
|
||||
case INDEX_op_smax_vec:
|
||||
case INDEX_op_umin_vec:
|
||||
case INDEX_op_umax_vec:
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_cmp_vec, type, vece)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void vec_gen_2(TCGContext *tcg_ctx, TCGOpcode opc, TCGType type, unsigned vece, TCGArg r, TCGArg a)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(tcg_ctx, opc);
|
||||
TCGOP_VECL(op) = type - TCG_TYPE_V64;
|
||||
TCGOP_VECE(op) = vece;
|
||||
op->args[0] = r;
|
||||
op->args[1] = a;
|
||||
}
|
||||
|
||||
void vec_gen_3(TCGContext *tcg_ctx, TCGOpcode opc, TCGType type, unsigned vece,
|
||||
TCGArg r, TCGArg a, TCGArg b)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(tcg_ctx, 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(TCGContext *tcg_ctx, TCGOpcode opc, TCGType type, unsigned vece,
|
||||
TCGArg r, TCGArg a, TCGArg b, TCGArg c)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(tcg_ctx, 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_6(TCGContext *tcg_ctx, TCGOpcode opc, TCGType type, unsigned vece, TCGArg r,
|
||||
TCGArg a, TCGArg b, TCGArg c, TCGArg d, TCGArg e)
|
||||
{
|
||||
TCGOp *op = tcg_emit_op(tcg_ctx, 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;
|
||||
op->args[4] = d;
|
||||
op->args[5] = e;
|
||||
}
|
||||
|
||||
static void vec_gen_op2(TCGContext *tcg_ctx, TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
/* Must enough inputs for the output. */
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
vec_gen_2(tcg_ctx, opc, type, vece, temp_arg(rt), temp_arg(at));
|
||||
}
|
||||
|
||||
static void vec_gen_op3(TCGContext *tcg_ctx, TCGOpcode opc, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *bt = tcgv_vec_temp(tcg_ctx, 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(tcg_ctx, opc, type, vece, temp_arg(rt), temp_arg(at), temp_arg(bt));
|
||||
}
|
||||
|
||||
void tcg_gen_mov_vec(TCGContext *tcg_ctx, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
if (r != a) {
|
||||
vec_gen_op2(tcg_ctx, INDEX_op_mov_vec, 0, r, a);
|
||||
}
|
||||
}
|
||||
|
||||
#define MO_REG (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32)
|
||||
|
||||
static void do_dupi_vec(TCGContext *tcg_ctx, TCGv_vec r, unsigned vece, TCGArg a)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
vec_gen_2(tcg_ctx, INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a);
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_zeros_vec(TCGContext *tcg_ctx, TCGType type)
|
||||
{
|
||||
TCGv_vec ret = tcg_temp_new_vec(tcg_ctx, type);
|
||||
do_dupi_vec(tcg_ctx, ret, MO_REG, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_ones_vec(TCGContext *tcg_ctx, TCGType type)
|
||||
{
|
||||
TCGv_vec ret = tcg_temp_new_vec(tcg_ctx, type);
|
||||
do_dupi_vec(tcg_ctx, ret, MO_REG, -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_zeros_vec_matching(TCGContext *tcg_ctx, TCGv_vec m)
|
||||
{
|
||||
TCGTemp *t = tcgv_vec_temp(tcg_ctx, m);
|
||||
return tcg_const_zeros_vec(tcg_ctx, t->base_type);
|
||||
}
|
||||
|
||||
TCGv_vec tcg_const_ones_vec_matching(TCGContext *tcg_ctx, TCGv_vec m)
|
||||
{
|
||||
TCGTemp *t = tcgv_vec_temp(tcg_ctx, m);
|
||||
return tcg_const_ones_vec(tcg_ctx, t->base_type);
|
||||
}
|
||||
|
||||
void tcg_gen_dup64i_vec(TCGContext *tcg_ctx, TCGv_vec r, uint64_t a)
|
||||
{
|
||||
if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
|
||||
do_dupi_vec(tcg_ctx, r, MO_32, a);
|
||||
} else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
|
||||
do_dupi_vec(tcg_ctx, r, MO_64, a);
|
||||
} else {
|
||||
TCGv_i64 c = tcg_const_i64(tcg_ctx, a);
|
||||
tcg_gen_dup_i64_vec(tcg_ctx, MO_64, r, c);
|
||||
tcg_temp_free_i64(tcg_ctx, c);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_dup32i_vec(TCGContext *tcg_ctx, TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(tcg_ctx, r, MO_REG, dup_const(MO_32, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup16i_vec(TCGContext *tcg_ctx, TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(tcg_ctx, r, MO_REG, dup_const(MO_16, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup8i_vec(TCGContext *tcg_ctx, TCGv_vec r, uint32_t a)
|
||||
{
|
||||
do_dupi_vec(tcg_ctx, r, MO_REG, dup_const(MO_8, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dupi_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, uint64_t a)
|
||||
{
|
||||
do_dupi_vec(tcg_ctx, r, MO_REG, dup_const(vece, a));
|
||||
}
|
||||
|
||||
void tcg_gen_dup_i64_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_i64 a)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(tcg_ctx, r);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
TCGArg ai = tcgv_i64_arg(tcg_ctx, a);
|
||||
vec_gen_2(tcg_ctx, INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
#else
|
||||
if (vece == MO_64) {
|
||||
TCGArg al = tcgv_i32_arg(tcg_ctx, TCGV_LOW(tcg_ctx, a));
|
||||
TCGArg ah = tcgv_i32_arg(tcg_ctx, TCGV_HIGH(tcg_ctx, a));
|
||||
vec_gen_3(tcg_ctx, INDEX_op_dup2_vec, type, MO_64, ri, al, ah);
|
||||
} else {
|
||||
TCGArg ai = tcgv_i32_arg(tcg_ctx, TCGV_LOW(tcg_ctx, a));
|
||||
vec_gen_2(tcg_ctx, INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tcg_gen_dup_i32_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_i32 a)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(tcg_ctx, r);
|
||||
TCGArg ai = tcgv_i32_arg(tcg_ctx, a);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
vec_gen_2(tcg_ctx, INDEX_op_dup_vec, type, vece, ri, ai);
|
||||
}
|
||||
|
||||
void tcg_gen_dup_mem_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_ptr b,
|
||||
tcg_target_long ofs)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(tcg_ctx, r);
|
||||
TCGArg bi = tcgv_ptr_arg(tcg_ctx, b);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
vec_gen_3(tcg_ctx, INDEX_op_dupm_vec, type, vece, ri, bi, ofs);
|
||||
}
|
||||
|
||||
static void vec_gen_ldst(TCGContext *tcg_ctx, TCGOpcode opc, TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(tcg_ctx, r);
|
||||
TCGArg bi = tcgv_ptr_arg(tcg_ctx, b);
|
||||
TCGTemp *rt = arg_temp(ri);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
vec_gen_3(tcg_ctx, opc, type, 0, ri, bi, o);
|
||||
}
|
||||
|
||||
void tcg_gen_ld_vec(TCGContext *tcg_ctx, TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
vec_gen_ldst(tcg_ctx, INDEX_op_ld_vec, r, b, o);
|
||||
}
|
||||
|
||||
void tcg_gen_st_vec(TCGContext *tcg_ctx, TCGv_vec r, TCGv_ptr b, TCGArg o)
|
||||
{
|
||||
vec_gen_ldst(tcg_ctx, INDEX_op_st_vec, r, b, o);
|
||||
}
|
||||
|
||||
void tcg_gen_stl_vec(TCGContext *tcg_ctx, TCGv_vec r, TCGv_ptr b, TCGArg o, TCGType low_type)
|
||||
{
|
||||
TCGArg ri = tcgv_vec_arg(tcg_ctx, r);
|
||||
TCGArg bi = tcgv_ptr_arg(tcg_ctx, 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(tcg_ctx, INDEX_op_st_vec, low_type, 0, ri, bi, o);
|
||||
}
|
||||
|
||||
void tcg_gen_and_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(tcg_ctx, INDEX_op_and_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_or_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(tcg_ctx, INDEX_op_or_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_xor_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
vec_gen_op3(tcg_ctx, INDEX_op_xor_vec, 0, r, a, b);
|
||||
}
|
||||
|
||||
void tcg_gen_andc_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
if (TCG_TARGET_HAS_andc_vec) {
|
||||
vec_gen_op3(tcg_ctx, INDEX_op_andc_vec, 0, r, a, b);
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(tcg_ctx, r);
|
||||
tcg_gen_not_vec(tcg_ctx, 0, t, b);
|
||||
tcg_gen_and_vec(tcg_ctx, 0, r, a, t);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_orc_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
if (TCG_TARGET_HAS_orc_vec) {
|
||||
vec_gen_op3(tcg_ctx, INDEX_op_orc_vec, 0, r, a, b);
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec_matching(tcg_ctx, r);
|
||||
tcg_gen_not_vec(tcg_ctx, 0, t, b);
|
||||
tcg_gen_or_vec(tcg_ctx, 0, r, a, t);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_nand_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
/* TODO: Add TCG_TARGET_HAS_nand_vec when adding a backend supports it. */
|
||||
tcg_gen_and_vec(tcg_ctx, 0, r, a, b);
|
||||
tcg_gen_not_vec(tcg_ctx, 0, r, r);
|
||||
}
|
||||
|
||||
void tcg_gen_nor_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
/* TODO: Add TCG_TARGET_HAS_nor_vec when adding a backend supports it. */
|
||||
tcg_gen_or_vec(tcg_ctx, 0, r, a, b);
|
||||
tcg_gen_not_vec(tcg_ctx, 0, r, r);
|
||||
}
|
||||
|
||||
void tcg_gen_eqv_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
/* TODO: Add TCG_TARGET_HAS_eqv_vec when adding a backend supports it. */
|
||||
tcg_gen_xor_vec(tcg_ctx, 0, r, a, b);
|
||||
tcg_gen_not_vec(tcg_ctx, 0, r, r);
|
||||
}
|
||||
|
||||
static bool do_op2(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGOpcode opc)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, 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_assert_listed_vecop(opc);
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, opc, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_2(tcg_ctx, opc, type, vece, ri, ai);
|
||||
} else if (can < 0) {
|
||||
const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
|
||||
tcg_expand_vec_op(tcg_ctx, opc, type, vece, ri, ai);
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void tcg_gen_not_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
|
||||
|
||||
if (!TCG_TARGET_HAS_not_vec || !do_op2(tcg_ctx, vece, r, a, INDEX_op_not_vec)) {
|
||||
TCGv_vec t = tcg_const_ones_vec_matching(tcg_ctx, r);
|
||||
tcg_gen_xor_vec(tcg_ctx, 0, r, a, t);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
|
||||
void tcg_gen_neg_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
const TCGOpcode *hold_list;
|
||||
|
||||
tcg_assert_listed_vecop(INDEX_op_neg_vec);
|
||||
hold_list = tcg_swap_vecop_list(NULL);
|
||||
|
||||
if (!TCG_TARGET_HAS_neg_vec || !do_op2(tcg_ctx, vece, r, a, INDEX_op_neg_vec)) {
|
||||
TCGv_vec t = tcg_const_zeros_vec_matching(tcg_ctx, r);
|
||||
tcg_gen_sub_vec(tcg_ctx, vece, r, t, a);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
|
||||
void tcg_gen_abs_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a)
|
||||
{
|
||||
const TCGOpcode *hold_list;
|
||||
|
||||
tcg_assert_listed_vecop(INDEX_op_abs_vec);
|
||||
hold_list = tcg_swap_vecop_list(NULL);
|
||||
|
||||
if (!do_op2(tcg_ctx, vece, r, a, INDEX_op_abs_vec)) {
|
||||
TCGType type = tcgv_vec_temp(tcg_ctx, r)->base_type;
|
||||
TCGv_vec t = tcg_temp_new_vec(tcg_ctx, type);
|
||||
|
||||
tcg_debug_assert(tcg_can_emit_vec_op(tcg_ctx, INDEX_op_sub_vec, type, vece));
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_smax_vec, type, vece) > 0) {
|
||||
tcg_gen_neg_vec(tcg_ctx, vece, t, a);
|
||||
tcg_gen_smax_vec(tcg_ctx, vece, r, a, t);
|
||||
} else {
|
||||
if (tcg_can_emit_vec_op(tcg_ctx, INDEX_op_sari_vec, type, vece) > 0) {
|
||||
tcg_gen_sari_vec(tcg_ctx, vece, t, a, (8 << vece) - 1);
|
||||
} else {
|
||||
do_dupi_vec(tcg_ctx, t, MO_REG, 0);
|
||||
tcg_gen_cmp_vec(tcg_ctx, TCG_COND_LT, vece, t, a, t);
|
||||
}
|
||||
tcg_gen_xor_vec(tcg_ctx, vece, r, a, t);
|
||||
tcg_gen_sub_vec(tcg_ctx, vece, r, r, t);
|
||||
}
|
||||
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
|
||||
static void do_shifti(TCGContext *tcg_ctx, TCGOpcode opc, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, 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));
|
||||
tcg_assert_listed_vecop(opc);
|
||||
|
||||
if (i == 0) {
|
||||
tcg_gen_mov_vec(tcg_ctx, r, a);
|
||||
return;
|
||||
}
|
||||
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, opc, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_3(tcg_ctx, 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. */
|
||||
const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
|
||||
tcg_debug_assert(can < 0);
|
||||
tcg_expand_vec_op(tcg_ctx, opc, type, vece, ri, ai, i);
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_shli_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(tcg_ctx, INDEX_op_shli_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_shri_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(tcg_ctx, INDEX_op_shri_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_sari_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, int64_t i)
|
||||
{
|
||||
do_shifti(tcg_ctx, INDEX_op_sari_vec, vece, r, a, i);
|
||||
}
|
||||
|
||||
void tcg_gen_cmp_vec(TCGContext *tcg_ctx, TCGCond cond, unsigned vece,
|
||||
TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *bt = tcgv_vec_temp(tcg_ctx, 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);
|
||||
tcg_assert_listed_vecop(INDEX_op_cmp_vec);
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, INDEX_op_cmp_vec, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_4(tcg_ctx, INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond);
|
||||
} else {
|
||||
const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
|
||||
tcg_debug_assert(can < 0);
|
||||
tcg_expand_vec_op(tcg_ctx, INDEX_op_cmp_vec, type, vece, ri, ai, bi, cond);
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
}
|
||||
|
||||
static bool do_op3(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a,
|
||||
TCGv_vec b, TCGOpcode opc)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *bt = tcgv_vec_temp(tcg_ctx, 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);
|
||||
tcg_assert_listed_vecop(opc);
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, opc, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_3(tcg_ctx, opc, type, vece, ri, ai, bi);
|
||||
} else if (can < 0) {
|
||||
const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
|
||||
tcg_expand_vec_op(tcg_ctx, opc, type, vece, ri, ai, bi);
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void do_op3_nofail(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a,
|
||||
TCGv_vec b, TCGOpcode opc)
|
||||
{
|
||||
bool ok = do_op3(tcg_ctx, vece, r, a, b, opc);
|
||||
tcg_debug_assert(ok);
|
||||
}
|
||||
|
||||
void tcg_gen_add_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_add_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_sub_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_sub_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_mul_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_mul_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_ssadd_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_ssadd_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_usadd_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_usadd_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_sssub_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_sssub_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_ussub_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_ussub_vec);
|
||||
}
|
||||
|
||||
static void do_minmax(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a,
|
||||
TCGv_vec b, TCGOpcode opc, TCGCond cond)
|
||||
{
|
||||
if (!do_op3(tcg_ctx, vece, r, a, b, opc)) {
|
||||
tcg_gen_cmpsel_vec(tcg_ctx, cond, vece, r, a, b, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_smin_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_minmax(tcg_ctx, vece, r, a, b, INDEX_op_smin_vec, TCG_COND_LT);
|
||||
}
|
||||
|
||||
void tcg_gen_umin_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_minmax(tcg_ctx, vece, r, a, b, INDEX_op_umin_vec, TCG_COND_LTU);
|
||||
}
|
||||
|
||||
void tcg_gen_smax_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_minmax(tcg_ctx, vece, r, a, b, INDEX_op_smax_vec, TCG_COND_GT);
|
||||
}
|
||||
|
||||
void tcg_gen_umax_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_minmax(tcg_ctx, vece, r, a, b, INDEX_op_umax_vec, TCG_COND_GTU);
|
||||
}
|
||||
|
||||
void tcg_gen_shlv_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_shlv_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_shrv_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_shrv_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_sarv_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
|
||||
{
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, b, INDEX_op_sarv_vec);
|
||||
}
|
||||
|
||||
static void do_shifts(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a,
|
||||
TCGv_i32 s, TCGOpcode opc_s, TCGOpcode opc_v)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *st = tcgv_i32_temp(tcg_ctx, s);
|
||||
TCGArg ri = temp_arg(rt);
|
||||
TCGArg ai = temp_arg(at);
|
||||
TCGArg si = temp_arg(st);
|
||||
TCGType type = rt->base_type;
|
||||
const TCGOpcode *hold_list;
|
||||
int can;
|
||||
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
tcg_assert_listed_vecop(opc_s);
|
||||
hold_list = tcg_swap_vecop_list(NULL);
|
||||
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, opc_s, type, vece);
|
||||
if (can > 0) {
|
||||
vec_gen_3(tcg_ctx, opc_s, type, vece, ri, ai, si);
|
||||
} else if (can < 0) {
|
||||
tcg_expand_vec_op(tcg_ctx, opc_s, type, vece, ri, ai, si);
|
||||
} else {
|
||||
TCGv_vec vec_s = tcg_temp_new_vec(tcg_ctx, type);
|
||||
|
||||
if (vece == MO_64) {
|
||||
TCGv_i64 s64 = tcg_temp_new_i64(tcg_ctx);
|
||||
tcg_gen_extu_i32_i64(tcg_ctx, s64, s);
|
||||
tcg_gen_dup_i64_vec(tcg_ctx, MO_64, vec_s, s64);
|
||||
tcg_temp_free_i64(tcg_ctx, s64);
|
||||
} else {
|
||||
tcg_gen_dup_i32_vec(tcg_ctx, vece, vec_s, s);
|
||||
}
|
||||
do_op3_nofail(tcg_ctx, vece, r, a, vec_s, opc_v);
|
||||
tcg_temp_free_vec(tcg_ctx, vec_s);
|
||||
}
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
|
||||
void tcg_gen_shls_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b)
|
||||
{
|
||||
do_shifts(tcg_ctx, vece, r, a, b, INDEX_op_shls_vec, INDEX_op_shlv_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_shrs_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b)
|
||||
{
|
||||
do_shifts(tcg_ctx, vece, r, a, b, INDEX_op_shrs_vec, INDEX_op_shrv_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_sars_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_i32 b)
|
||||
{
|
||||
do_shifts(tcg_ctx, vece, r, a, b, INDEX_op_sars_vec, INDEX_op_sarv_vec);
|
||||
}
|
||||
|
||||
void tcg_gen_bitsel_vec(TCGContext *tcg_ctx, unsigned vece, TCGv_vec r, TCGv_vec a,
|
||||
TCGv_vec b, TCGv_vec c)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *bt = tcgv_vec_temp(tcg_ctx, b);
|
||||
TCGTemp *ct = tcgv_vec_temp(tcg_ctx, c);
|
||||
TCGType type = rt->base_type;
|
||||
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
tcg_debug_assert(bt->base_type >= type);
|
||||
tcg_debug_assert(ct->base_type >= type);
|
||||
|
||||
if (TCG_TARGET_HAS_bitsel_vec) {
|
||||
vec_gen_4(tcg_ctx, INDEX_op_bitsel_vec, type, MO_8,
|
||||
temp_arg(rt), temp_arg(at), temp_arg(bt), temp_arg(ct));
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec(tcg_ctx, type);
|
||||
tcg_gen_and_vec(tcg_ctx, MO_8, t, a, b);
|
||||
tcg_gen_andc_vec(tcg_ctx, MO_8, r, c, a);
|
||||
tcg_gen_or_vec(tcg_ctx, MO_8, r, r, t);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_cmpsel_vec(TCGContext *tcg_ctx, TCGCond cond, unsigned vece, TCGv_vec r,
|
||||
TCGv_vec a, TCGv_vec b, TCGv_vec c, TCGv_vec d)
|
||||
{
|
||||
TCGTemp *rt = tcgv_vec_temp(tcg_ctx, r);
|
||||
TCGTemp *at = tcgv_vec_temp(tcg_ctx, a);
|
||||
TCGTemp *bt = tcgv_vec_temp(tcg_ctx, b);
|
||||
TCGTemp *ct = tcgv_vec_temp(tcg_ctx, c);
|
||||
TCGTemp *dt = tcgv_vec_temp(tcg_ctx, d);
|
||||
TCGArg ri = temp_arg(rt);
|
||||
TCGArg ai = temp_arg(at);
|
||||
TCGArg bi = temp_arg(bt);
|
||||
TCGArg ci = temp_arg(ct);
|
||||
TCGArg di = temp_arg(dt);
|
||||
TCGType type = rt->base_type;
|
||||
const TCGOpcode *hold_list;
|
||||
int can;
|
||||
|
||||
tcg_debug_assert(at->base_type >= type);
|
||||
tcg_debug_assert(bt->base_type >= type);
|
||||
tcg_debug_assert(ct->base_type >= type);
|
||||
tcg_debug_assert(dt->base_type >= type);
|
||||
|
||||
tcg_assert_listed_vecop(INDEX_op_cmpsel_vec);
|
||||
hold_list = tcg_swap_vecop_list(NULL);
|
||||
can = tcg_can_emit_vec_op(tcg_ctx, INDEX_op_cmpsel_vec, type, vece);
|
||||
|
||||
if (can > 0) {
|
||||
vec_gen_6(tcg_ctx, INDEX_op_cmpsel_vec, type, vece, ri, ai, bi, ci, di, cond);
|
||||
} else if (can < 0) {
|
||||
tcg_expand_vec_op(tcg_ctx, INDEX_op_cmpsel_vec, type, vece,
|
||||
ri, ai, bi, ci, di, cond);
|
||||
} else {
|
||||
TCGv_vec t = tcg_temp_new_vec(tcg_ctx, type);
|
||||
tcg_gen_cmp_vec(tcg_ctx, cond, vece, t, a, b);
|
||||
tcg_gen_bitsel_vec(tcg_ctx, vece, r, t, c, d);
|
||||
tcg_temp_free_vec(tcg_ctx, t);
|
||||
}
|
||||
tcg_swap_vecop_list(hold_list);
|
||||
}
|
||||
3372
qemu/tcg/tcg-op.c
Normal file
3372
qemu/tcg/tcg-op.c
Normal file
File diff suppressed because it is too large
Load Diff
2784
qemu/tcg/tcg-op.h
2784
qemu/tcg/tcg-op.h
File diff suppressed because it is too large
Load Diff
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Tiny Code Generator for QEMU
|
||||
*
|
||||
* Copyright (c) 2008 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* DEF(name, oargs, iargs, cargs, flags)
|
||||
*/
|
||||
|
||||
/* predefined ops */
|
||||
DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */
|
||||
DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT)
|
||||
DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT)
|
||||
DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT)
|
||||
DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT)
|
||||
|
||||
/* variable number of parameters */
|
||||
DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT)
|
||||
|
||||
DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
|
||||
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
|
||||
|
||||
/* variable number of parameters */
|
||||
DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT)
|
||||
|
||||
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define IMPL(X) ((0 && !(X)) ? TCG_OPF_NOT_PRESENT : 0)
|
||||
#else
|
||||
#define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0)
|
||||
#endif
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 32
|
||||
# define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT
|
||||
#else
|
||||
# define IMPL64 TCG_OPF_64BIT
|
||||
#endif
|
||||
|
||||
DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
|
||||
DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
|
||||
DEF(setcond_i32, 1, 2, 1, 0)
|
||||
DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
|
||||
/* load/store */
|
||||
DEF(ld8u_i32, 1, 1, 1, 0)
|
||||
DEF(ld8s_i32, 1, 1, 1, 0)
|
||||
DEF(ld16u_i32, 1, 1, 1, 0)
|
||||
DEF(ld16s_i32, 1, 1, 1, 0)
|
||||
DEF(ld_i32, 1, 1, 1, 0)
|
||||
DEF(st8_i32, 0, 2, 1, 0)
|
||||
DEF(st16_i32, 0, 2, 1, 0)
|
||||
DEF(st_i32, 0, 2, 1, 0)
|
||||
/* arith */
|
||||
DEF(add_i32, 1, 2, 0, 0)
|
||||
DEF(sub_i32, 1, 2, 0, 0)
|
||||
DEF(mul_i32, 1, 2, 0, 0)
|
||||
DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
|
||||
DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
|
||||
DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
|
||||
DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
|
||||
DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
|
||||
DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
|
||||
DEF(and_i32, 1, 2, 0, 0)
|
||||
DEF(or_i32, 1, 2, 0, 0)
|
||||
DEF(xor_i32, 1, 2, 0, 0)
|
||||
/* shifts/rotates */
|
||||
DEF(shl_i32, 1, 2, 0, 0)
|
||||
DEF(shr_i32, 1, 2, 0, 0)
|
||||
DEF(sar_i32, 1, 2, 0, 0)
|
||||
DEF(rotl_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32))
|
||||
DEF(rotr_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rot_i32))
|
||||
DEF(deposit_i32, 1, 2, 2, IMPL(TCG_TARGET_HAS_deposit_i32))
|
||||
|
||||
DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END)
|
||||
|
||||
DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32))
|
||||
DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32))
|
||||
DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32))
|
||||
DEF(muls2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_muls2_i32))
|
||||
DEF(muluh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i32))
|
||||
DEF(mulsh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i32))
|
||||
DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32))
|
||||
DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32))
|
||||
|
||||
DEF(ext8s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8s_i32))
|
||||
DEF(ext16s_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16s_i32))
|
||||
DEF(ext8u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext8u_i32))
|
||||
DEF(ext16u_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ext16u_i32))
|
||||
DEF(bswap16_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap16_i32))
|
||||
DEF(bswap32_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_bswap32_i32))
|
||||
DEF(not_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_not_i32))
|
||||
DEF(neg_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_neg_i32))
|
||||
DEF(andc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_andc_i32))
|
||||
DEF(orc_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_orc_i32))
|
||||
DEF(eqv_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_eqv_i32))
|
||||
DEF(nand_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nand_i32))
|
||||
DEF(nor_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_nor_i32))
|
||||
|
||||
DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
|
||||
DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
|
||||
DEF(setcond_i64, 1, 2, 1, IMPL64)
|
||||
DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
|
||||
/* load/store */
|
||||
DEF(ld8u_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld8s_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld16u_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld16s_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld32u_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld32s_i64, 1, 1, 1, IMPL64)
|
||||
DEF(ld_i64, 1, 1, 1, IMPL64)
|
||||
DEF(st8_i64, 0, 2, 1, IMPL64)
|
||||
DEF(st16_i64, 0, 2, 1, IMPL64)
|
||||
DEF(st32_i64, 0, 2, 1, IMPL64)
|
||||
DEF(st_i64, 0, 2, 1, IMPL64)
|
||||
/* arith */
|
||||
DEF(add_i64, 1, 2, 0, IMPL64)
|
||||
DEF(sub_i64, 1, 2, 0, IMPL64)
|
||||
DEF(mul_i64, 1, 2, 0, IMPL64)
|
||||
DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
|
||||
DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
|
||||
DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
|
||||
DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
|
||||
DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
|
||||
DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
|
||||
DEF(and_i64, 1, 2, 0, IMPL64)
|
||||
DEF(or_i64, 1, 2, 0, IMPL64)
|
||||
DEF(xor_i64, 1, 2, 0, IMPL64)
|
||||
/* shifts/rotates */
|
||||
DEF(shl_i64, 1, 2, 0, IMPL64)
|
||||
DEF(shr_i64, 1, 2, 0, IMPL64)
|
||||
DEF(sar_i64, 1, 2, 0, IMPL64)
|
||||
DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
|
||||
DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
|
||||
DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64))
|
||||
|
||||
DEF(trunc_shr_i32, 1, 1, 1,
|
||||
IMPL(TCG_TARGET_HAS_trunc_shr_i32)
|
||||
| (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0))
|
||||
|
||||
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64)
|
||||
DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64))
|
||||
DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64))
|
||||
DEF(ext32s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32s_i64))
|
||||
DEF(ext8u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8u_i64))
|
||||
DEF(ext16u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16u_i64))
|
||||
DEF(ext32u_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext32u_i64))
|
||||
DEF(bswap16_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap16_i64))
|
||||
DEF(bswap32_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap32_i64))
|
||||
DEF(bswap64_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_bswap64_i64))
|
||||
DEF(not_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_not_i64))
|
||||
DEF(neg_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_neg_i64))
|
||||
DEF(andc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_andc_i64))
|
||||
DEF(orc_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_orc_i64))
|
||||
DEF(eqv_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_eqv_i64))
|
||||
DEF(nand_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nand_i64))
|
||||
DEF(nor_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_nor_i64))
|
||||
|
||||
DEF(add2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_add2_i64))
|
||||
DEF(sub2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_sub2_i64))
|
||||
DEF(mulu2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulu2_i64))
|
||||
DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64))
|
||||
DEF(muluh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i64))
|
||||
DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64))
|
||||
|
||||
/* QEMU specific */
|
||||
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
|
||||
DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
|
||||
#else
|
||||
DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
|
||||
#endif
|
||||
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
|
||||
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
|
||||
|
||||
#define TLADDR_ARGS (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? 1 : 2)
|
||||
#define DATA64_ARGS (TCG_TARGET_REG_BITS == 64 ? 1 : 2)
|
||||
|
||||
DEF(qemu_ld_i32, 1, TLADDR_ARGS, 2,
|
||||
TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
|
||||
DEF(qemu_st_i32, 0, TLADDR_ARGS + 1, 2,
|
||||
TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
|
||||
DEF(qemu_ld_i64, DATA64_ARGS, TLADDR_ARGS, 2,
|
||||
TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT)
|
||||
DEF(qemu_st_i64, 0, TLADDR_ARGS + DATA64_ARGS, 2,
|
||||
TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS | TCG_OPF_64BIT)
|
||||
|
||||
#undef TLADDR_ARGS
|
||||
#undef DATA64_ARGS
|
||||
#undef IMPL
|
||||
#undef IMPL64
|
||||
#undef DEF
|
||||
158
qemu/tcg/tcg-pool.inc.c
Normal file
158
qemu/tcg/tcg-pool.inc.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* TCG Backend Data: constant pool.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
typedef struct TCGLabelPoolData {
|
||||
struct TCGLabelPoolData *next;
|
||||
tcg_insn_unit *label;
|
||||
intptr_t addend;
|
||||
int rtype;
|
||||
unsigned nlong;
|
||||
tcg_target_ulong data[];
|
||||
} TCGLabelPoolData;
|
||||
|
||||
|
||||
static TCGLabelPoolData *new_pool_alloc(TCGContext *s, int nlong, int rtype,
|
||||
tcg_insn_unit *label, intptr_t addend)
|
||||
{
|
||||
TCGLabelPoolData *n = tcg_malloc(s, sizeof(TCGLabelPoolData)
|
||||
+ sizeof(tcg_target_ulong) * nlong);
|
||||
|
||||
n->label = label;
|
||||
n->addend = addend;
|
||||
n->rtype = rtype;
|
||||
n->nlong = nlong;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void new_pool_insert(TCGContext *s, TCGLabelPoolData *n)
|
||||
{
|
||||
TCGLabelPoolData *i, **pp;
|
||||
int nlong = n->nlong;
|
||||
|
||||
/* Insertion sort on the pool. */
|
||||
for (pp = &s->pool_labels; (i = *pp) != NULL; pp = &i->next) {
|
||||
if (nlong > i->nlong) {
|
||||
break;
|
||||
}
|
||||
if (nlong < i->nlong) {
|
||||
continue;
|
||||
}
|
||||
if (memcmp(n->data, i->data, sizeof(tcg_target_ulong) * nlong) >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
n->next = *pp;
|
||||
*pp = n;
|
||||
}
|
||||
|
||||
/* The "usual" for generic integer code. */
|
||||
static inline void new_pool_label(TCGContext *s, tcg_target_ulong d, int rtype,
|
||||
tcg_insn_unit *label, intptr_t addend)
|
||||
{
|
||||
TCGLabelPoolData *n = new_pool_alloc(s, 1, rtype, label, addend);
|
||||
n->data[0] = d;
|
||||
new_pool_insert(s, n);
|
||||
}
|
||||
|
||||
/* For v64 or v128, depending on the host. */
|
||||
static inline void new_pool_l2(TCGContext *s, int rtype, tcg_insn_unit *label,
|
||||
intptr_t addend, tcg_target_ulong d0,
|
||||
tcg_target_ulong d1)
|
||||
{
|
||||
TCGLabelPoolData *n = new_pool_alloc(s, 2, rtype, label, addend);
|
||||
n->data[0] = d0;
|
||||
n->data[1] = d1;
|
||||
new_pool_insert(s, n);
|
||||
}
|
||||
|
||||
/* For v128 or v256, depending on the host. */
|
||||
static inline void new_pool_l4(TCGContext *s, int rtype, tcg_insn_unit *label,
|
||||
intptr_t addend, tcg_target_ulong d0,
|
||||
tcg_target_ulong d1, tcg_target_ulong d2,
|
||||
tcg_target_ulong d3)
|
||||
{
|
||||
TCGLabelPoolData *n = new_pool_alloc(s, 4, rtype, label, addend);
|
||||
n->data[0] = d0;
|
||||
n->data[1] = d1;
|
||||
n->data[2] = d2;
|
||||
n->data[3] = d3;
|
||||
new_pool_insert(s, n);
|
||||
}
|
||||
|
||||
/* For v256, for 32-bit host. */
|
||||
static inline void new_pool_l8(TCGContext *s, int rtype, tcg_insn_unit *label,
|
||||
intptr_t addend, tcg_target_ulong d0,
|
||||
tcg_target_ulong d1, tcg_target_ulong d2,
|
||||
tcg_target_ulong d3, tcg_target_ulong d4,
|
||||
tcg_target_ulong d5, tcg_target_ulong d6,
|
||||
tcg_target_ulong d7)
|
||||
{
|
||||
TCGLabelPoolData *n = new_pool_alloc(s, 8, rtype, label, addend);
|
||||
n->data[0] = d0;
|
||||
n->data[1] = d1;
|
||||
n->data[2] = d2;
|
||||
n->data[3] = d3;
|
||||
n->data[4] = d4;
|
||||
n->data[5] = d5;
|
||||
n->data[6] = d6;
|
||||
n->data[7] = d7;
|
||||
new_pool_insert(s, n);
|
||||
}
|
||||
|
||||
/* To be provided by cpu/tcg-target.inc.c. */
|
||||
static void tcg_out_nop_fill(tcg_insn_unit *p, int count);
|
||||
|
||||
static int tcg_out_pool_finalize(TCGContext *s)
|
||||
{
|
||||
TCGLabelPoolData *p = s->pool_labels;
|
||||
TCGLabelPoolData *l = NULL;
|
||||
char *a;
|
||||
|
||||
if (p == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ??? Round up to qemu_icache_linesize, but then do not round
|
||||
again when allocating the next TranslationBlock structure. */
|
||||
a = (void *)ROUND_UP((uintptr_t)s->code_ptr,
|
||||
sizeof(tcg_target_ulong) * p->nlong);
|
||||
tcg_out_nop_fill(s->code_ptr, (tcg_insn_unit *)a - s->code_ptr);
|
||||
s->data_gen_ptr = a;
|
||||
|
||||
for (; p != NULL; p = p->next) {
|
||||
size_t size = sizeof(tcg_target_ulong) * p->nlong;
|
||||
if (!l || l->nlong != p->nlong || memcmp(l->data, p->data, size)) {
|
||||
if (unlikely(a > (char *)s->code_gen_highwater)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(a, p->data, size);
|
||||
a += size;
|
||||
l = p;
|
||||
}
|
||||
if (!patch_reloc(p->label, p->rtype, (intptr_t)a - size, p->addend)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
s->code_ptr = (tcg_insn_unit *)a;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
DEF_HELPER_FLAGS_2(div_i32, TCG_CALL_NO_RWG_SE, s32, s32, s32)
|
||||
DEF_HELPER_FLAGS_2(rem_i32, TCG_CALL_NO_RWG_SE, s32, s32, s32)
|
||||
DEF_HELPER_FLAGS_2(divu_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(remu_i32, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_2(div_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_2(rem_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_2(divu_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(remu_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(shl_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(shr_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
DEF_HELPER_FLAGS_2(sar_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
|
||||
DEF_HELPER_FLAGS_2(mulsh_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_2(muluh_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
|
||||
4473
qemu/tcg/tcg.c
4473
qemu/tcg/tcg.c
File diff suppressed because it is too large
Load Diff
1012
qemu/tcg/tcg.h
1012
qemu/tcg/tcg.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user