aboutsummaryrefslogtreecommitdiffstats
path: root/tcg
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
committerDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
commit5d8f37ad78fc66901af50c762029a501561f3b23 (patch)
tree206790f8f21000850a98c4f9590a79e779106278 /tcg
parentcd059b15f2c7df69f4a087bd66900eb172e41d1c (diff)
downloadexternal_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.zip
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.gz
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.bz2
Merge upstream QEMU 10.0.50 into the Android source tree.
This change integrates many changes from the upstream QEMU sources. Its main purpose is to enable correct ARMv6 and ARMv7 support to the Android emulator. Due to the nature of the upstream code base, this unfortunately also required changes to many other parts of the source. Note that to ensure easier integrations in the future, some source files and directories that have heavy Android-specific customization have been renamed with an -android suffix. The original files are still there for easier integration tracking, but *never* compiled. For example: net.c net-android.c qemu-char.c qemu-char-android.c slirp/ slirp-android/ etc... Tested on linux-x86, darwin-x86 and windows host machines.
Diffstat (limited to 'tcg')
-rw-r--r--tcg/README99
-rw-r--r--tcg/TODO3
-rw-r--r--tcg/arm/tcg-target.c72
-rw-r--r--tcg/arm/tcg-target.h8
-rw-r--r--tcg/hppa/tcg-target.c4
-rw-r--r--tcg/hppa/tcg-target.h3
-rw-r--r--tcg/i386/tcg-target.c68
-rw-r--r--tcg/i386/tcg-target.h10
-rw-r--r--tcg/ppc/tcg-target.c93
-rw-r--r--tcg/ppc/tcg-target.h30
-rw-r--r--tcg/ppc64/tcg-target.c49
-rw-r--r--tcg/ppc64/tcg-target.h22
-rw-r--r--tcg/sparc/tcg-target.c108
-rw-r--r--tcg/sparc/tcg-target.h15
-rw-r--r--tcg/tcg-dyngen.c431
-rw-r--r--tcg/tcg-op.h1755
-rw-r--r--tcg/tcg-opc.h43
-rw-r--r--tcg/tcg-runtime.c2
-rw-r--r--tcg/tcg.c461
-rw-r--r--tcg/tcg.h154
-rw-r--r--tcg/x86_64/tcg-target.c88
-rw-r--r--tcg/x86_64/tcg-target.h12
22 files changed, 1940 insertions, 1590 deletions
diff --git a/tcg/README b/tcg/README
index b03432e..e672258 100644
--- a/tcg/README
+++ b/tcg/README
@@ -60,9 +60,8 @@ add_i32 t0, t1, t2 (t0 <- t1 + t2)
- Basic blocks end after branches (e.g. brcond_i32 instruction),
goto_tb and exit_tb instructions.
-- Basic blocks end before legacy dyngen operations.
-- Basic blocks start after the end of a previous basic block, at a
- set_label instruction or after a legacy dyngen operation.
+- Basic blocks start after the end of a previous basic block, or at a
+ set_label instruction.
After the end of a basic block, the content of temporaries is
destroyed, but local temporaries and globals are preserved.
@@ -205,7 +204,27 @@ t0=t1^t2
t0=~t1
-********* Shifts
+* andc_i32/i64 t0, t1, t2
+
+t0=t1&~t2
+
+* eqv_i32/i64 t0, t1, t2
+
+t0=~(t1^t2)
+
+* nand_i32/i64 t0, t1, t2
+
+t0=~(t1&t2)
+
+* nor_i32/i64 t0, t1, t2
+
+t0=~(t1|t2)
+
+* orc_i32/i64 t0, t1, t2
+
+t0=t1|~t2
+
+********* Shifts/Rotates
* shl_i32/i64 t0, t1, t2
@@ -219,6 +238,14 @@ t0=t1 >> t2 (unsigned). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
t0=t1 >> t2 (signed). Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+* rotl_i32/i64 t0, t1, t2
+
+Rotation of t2 bits to the left. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+
+* rotr_i32/i64 t0, t1, t2
+
+Rotation of t2 bits to the right. Undefined behavior if t2 < 0 or t2 >= 32 (resp 64)
+
********* Misc
* mov_i32/i64 t0, t1
@@ -236,16 +263,17 @@ ext32u_i64 t0, t1
8, 16 or 32 bit sign/zero extension (both operands must have the same type)
-* bswap16_i32 t0, t1
+* bswap16_i32/i64 t0, t1
-16 bit byte swap on a 32 bit value. The two high order bytes must be set
-to zero.
+16 bit byte swap on a 32/64 bit value. The two/six high order bytes must be
+set to zero.
-* bswap_i32 t0, t1
+* bswap32_i32/i64 t0, t1
-32 bit byte swap
+32 bit byte swap on a 32/64 bit value. With a 64 bit value, the four high
+order bytes must be set to zero.
-* bswap_i64 t0, t1
+* bswap64_i64 t0, t1
64 bit byte swap
@@ -265,6 +293,14 @@ Convert t1 (32 bit) to t0 (64 bit) and does zero extension
* trunc_i64_i32 t0, t1
Truncate t1 (64 bit) to t0 (32 bit)
+* concat_i32_i64 t0, t1, t2
+Construct t0 (64-bit) taking the low half from t1 (32 bit) and the high half
+from t2 (32 bit).
+
+* concat32_i64 t0, t1, t2
+Construct t0 (64-bit) taking the low half from t1 (64 bit) and the high half
+from t2 (64 bit).
+
********* Load/Store
* ld_i32/i64 t0, t1, offset
@@ -299,22 +335,22 @@ Exit the current TB and jump to the TB index 'index' (constant) if the
current TB was linked to this TB. Otherwise execute the next
instructions.
-* qemu_ld_i32/i64 t0, t1, flags
-qemu_ld8u_i32/i64 t0, t1, flags
-qemu_ld8s_i32/i64 t0, t1, flags
-qemu_ld16u_i32/i64 t0, t1, flags
-qemu_ld16s_i32/i64 t0, t1, flags
-qemu_ld32u_i64 t0, t1, flags
-qemu_ld32s_i64 t0, t1, flags
+* qemu_ld8u t0, t1, flags
+qemu_ld8s t0, t1, flags
+qemu_ld16u t0, t1, flags
+qemu_ld16s t0, t1, flags
+qemu_ld32u t0, t1, flags
+qemu_ld32s t0, t1, flags
+qemu_ld64 t0, t1, flags
Load data at the QEMU CPU address t1 into t0. t1 has the QEMU CPU
address type. 'flags' contains the QEMU memory index (selects user or
kernel access) for example.
-* qemu_st_i32/i64 t0, t1, flags
-qemu_st8_i32/i64 t0, t1, flags
-qemu_st16_i32/i64 t0, t1, flags
-qemu_st32_i64 t0, t1, flags
+* qemu_st8 t0, t1, flags
+qemu_st16 t0, t1, flags
+qemu_st32 t0, t1, flags
+qemu_st64 t0, t1, flags
Store the data t0 at the QEMU CPU Address t1. t1 has the QEMU CPU
address type. 'flags' contains the QEMU memory index (selects user or
@@ -354,6 +390,11 @@ GCC like constraints are used to define the constraints of every
instruction. Memory constraints are not supported in this
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.
+
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.
@@ -382,18 +423,7 @@ register.
target, functions must be able to return 2 values in registers for
64 bit return type.
-5) Migration from dyngen to TCG
-
-TCG is backward compatible with QEMU "dyngen" operations. It means
-that TCG instructions can be freely mixed with dyngen operations. It
-is expected that QEMU targets will be progressively fully converted to
-TCG. Once a target is fully converted to TCG, it will be possible
-to apply more optimizations because more registers will be free for
-the generated code.
-
-The exception model is the same as the dyngen one.
-
-6) Recommended coding rules for best performance
+5) Recommended coding rules for best performance
- Use globals to represent the parts of the QEMU CPU state which are
often modified, e.g. the integer registers and the condition
@@ -401,8 +431,7 @@ The exception model is the same as the dyngen one.
- Avoid globals stored in fixed registers. They must be used only to
store the pointer to the CPU state and possibly to store a pointer
- to a register window. The other uses are to ensure backward
- compatibility with dyngen during the porting a new target to TCG.
+ to a register window.
- Use temporaries. Use local temporaries only when really needed,
e.g. when you need to use a value after a jump. Local temporaries
diff --git a/tcg/TODO b/tcg/TODO
index 5ca35e9..f30cb75 100644
--- a/tcg/TODO
+++ b/tcg/TODO
@@ -1,5 +1,4 @@
-- Add new instructions such as: andnot, ror, rol, setcond, clz, ctz,
- popcnt.
+- Add new instructions such as: setcond, clz, ctz, popcnt.
- See if it is worth exporting mul2, mulu2, div2, divu2.
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index dee1ebc..8139da1 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -21,7 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%r0",
"%r1",
"%r2",
@@ -38,8 +40,9 @@ const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%r13",
"%r14",
};
+#endif
-int tcg_target_reg_alloc_order[] = {
+static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R0,
TCG_REG_R1,
TCG_REG_R2,
@@ -57,10 +60,10 @@ int tcg_target_reg_alloc_order[] = {
TCG_REG_R14,
};
-const int tcg_target_call_iarg_regs[4] = {
+static const int tcg_target_call_iarg_regs[4] = {
TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
};
-const int tcg_target_call_oarg_regs[2] = {
+static const int tcg_target_call_oarg_regs[2] = {
TCG_REG_R0, TCG_REG_R1
};
@@ -91,7 +94,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
}
/* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
{
const char *ct_str;
@@ -292,10 +295,19 @@ static inline void tcg_out_dat_reg2(TCGContext *s,
int cond, int opc0, int opc1, int rd0, int rd1,
int rn0, int rn1, int rm0, int rm1, int shift)
{
- tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
- (rn0 << 16) | (rd0 << 12) | shift | rm0);
- tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
- (rn1 << 16) | (rd1 << 12) | shift | rm1);
+ if (rd0 == rn1 || rd0 == rm1) {
+ tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
+ (rn0 << 16) | (8 << 12) | shift | rm0);
+ tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
+ (rn1 << 16) | (rd1 << 12) | shift | rm1);
+ tcg_out_dat_reg(s, cond, ARITH_MOV,
+ rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
+ } else {
+ tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
+ (rn0 << 16) | (rd0 << 12) | shift | rm0);
+ tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
+ (rn1 << 16) | (rd1 << 12) | shift | rm1);
+ }
}
static inline void tcg_out_dat_imm(TCGContext *s,
@@ -846,10 +858,10 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
else
data_reg2 = 0; /* surpress warning */
addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
- addr_reg2 = *args++;
-#endif
#ifdef CONFIG_SOFTMMU
+# if TARGET_LONG_BITS == 64
+ addr_reg2 = *args++;
+# endif
mem_index = *args;
s_bits = opc & 3;
@@ -999,8 +1011,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
case 3:
/* TODO: use block load -
* check that data_reg2 > data_reg or the other way */
- tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
- tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
+ if (data_reg == addr_reg) {
+ tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
+ tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
+ } else {
+ tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
+ tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
+ }
break;
}
#endif
@@ -1024,10 +1041,10 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
else
data_reg2 = 0; /* surpress warning */
addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
- addr_reg2 = *args++;
-#endif
#ifdef CONFIG_SOFTMMU
+# if TARGET_LONG_BITS == 64
+ addr_reg2 = *args++;
+# endif
mem_index = *args;
s_bits = opc & 3;
@@ -1229,19 +1246,24 @@ static inline void tcg_out_op(TCGContext *s, int opc,
if (args[0] >> 8)
tcg_out32(s, args[0]);
#else
- if (args[0] >> 8)
- tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
- else
- tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
- tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
- if (args[0] >> 8)
- tcg_out32(s, args[0]);
+ {
+ uint8_t *ld_ptr = s->code_ptr;
+ if (args[0] >> 8)
+ tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
+ else
+ tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
+ tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
+ if (args[0] >> 8) {
+ *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
+ tcg_out32(s, args[0]);
+ }
+ }
#endif
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* Direct jump method */
-#if 1
+#if defined(USE_DIRECT_JUMP)
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
tcg_out_b(s, COND_AL, 8);
#else
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 6c180af..8f5016f 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -28,7 +28,7 @@
#undef TCG_TARGET_WORDS_BIGENDIAN
#undef TCG_TARGET_HAS_div_i32
#undef TCG_TARGET_HAS_div_i64
-#undef TCG_TARGET_HAS_bswap_i32
+#undef TCG_TARGET_HAS_bswap32_i32
#define TCG_TARGET_HAS_ext8s_i32
#define TCG_TARGET_HAS_ext16s_i32
#define TCG_TARGET_HAS_neg_i32
@@ -64,13 +64,17 @@ enum {
TCG_AREG0 = TCG_REG_R7,
TCG_AREG1 = TCG_REG_R4,
TCG_AREG2 = TCG_REG_R5,
- TCG_AREG3 = TCG_REG_R6,
};
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
+#if QEMU_GNUC_PREREQ(4, 1)
+ void __clear_cache(char *beg, char *end);
+ __clear_cache((char *) start, (char *) stop);
+#else
register unsigned long _beg __asm ("a1") = start;
register unsigned long _end __asm ("a2") = stop;
register unsigned long _flg __asm ("a3") = 0;
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
+#endif
}
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 3affd26..5960c03 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%r0",
"%r1",
@@ -56,6 +57,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%sp",
"%r31",
};
+#endif
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R4,
@@ -106,7 +108,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
}
/* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
{
const char *ct_str;
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index 8e2693d..7ab6f0c 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -78,13 +78,12 @@ enum {
//#define TCG_TARGET_HAS_ext8s_i32
//#define TCG_TARGET_HAS_ext16s_i32
//#define TCG_TARGET_HAS_bswap16_i32
-//#define TCG_TARGET_HAS_bswap_i32
+//#define TCG_TARGET_HAS_bswap32_i32
/* Note: must be synced with dyngen-exec.h */
#define TCG_AREG0 TCG_REG_R17
#define TCG_AREG1 TCG_REG_R14
#define TCG_AREG2 TCG_REG_R15
-#define TCG_AREG3 TCG_REG_R16
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 08bb783..e0fd434 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -21,7 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%eax",
"%ecx",
"%edx",
@@ -31,8 +33,9 @@ const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%esi",
"%edi",
};
+#endif
-int tcg_target_reg_alloc_order[] = {
+static const int tcg_target_reg_alloc_order[] = {
TCG_REG_EAX,
TCG_REG_EDX,
TCG_REG_ECX,
@@ -42,8 +45,8 @@ int tcg_target_reg_alloc_order[] = {
TCG_REG_EBP,
};
-const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
-const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
+static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
+static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
static uint8_t *tb_ret_addr;
@@ -80,7 +83,7 @@ static inline int tcg_target_get_call_iarg_regs_count(int flags)
}
/* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
{
const char *ct_str;
@@ -155,6 +158,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ARITH_XOR 6
#define ARITH_CMP 7
+#define SHIFT_ROL 0
+#define SHIFT_ROR 1
#define SHIFT_SHL 4
#define SHIFT_SHR 5
#define SHIFT_SAR 7
@@ -282,7 +287,7 @@ static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val)
}
}
-void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
+static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
{
if (val != 0)
tgen_arithi(s, ARITH_ADD, reg, val);
@@ -522,7 +527,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
break;
case 0:
+ /* movzbl */
+ tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
+ break;
case 1:
+ /* movzwl */
+ tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
+ break;
case 2:
default:
tcg_out_mov(s, data_reg, TCG_REG_EAX);
@@ -989,7 +1000,13 @@ static inline void tcg_out_op(TCGContext *s, int opc,
case INDEX_op_sar_i32:
c = SHIFT_SAR;
goto gen_shift32;
-
+ case INDEX_op_rotl_i32:
+ c = SHIFT_ROL;
+ goto gen_shift32;
+ case INDEX_op_rotr_i32:
+ c = SHIFT_ROR;
+ goto gen_shift32;
+
case INDEX_op_add2_i32:
if (const_args[4])
tgen_arithi(s, ARITH_ADD, args[0], args[4]);
@@ -1017,6 +1034,30 @@ static inline void tcg_out_op(TCGContext *s, int opc,
tcg_out_brcond2(s, args, const_args);
break;
+ case INDEX_op_bswap16_i32:
+ tcg_out8(s, 0x66);
+ tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
+ tcg_out8(s, 8);
+ break;
+ case INDEX_op_bswap32_i32:
+ tcg_out_opc(s, (0xc8 + args[0]) | P_EXT);
+ break;
+
+ case INDEX_op_neg_i32:
+ tcg_out_modrm(s, 0xf7, 3, args[0]);
+ break;
+
+ case INDEX_op_not_i32:
+ tcg_out_modrm(s, 0xf7, 2, args[0]);
+ break;
+
+ case INDEX_op_ext8s_i32:
+ tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
+ break;
+ case INDEX_op_ext16s_i32:
+ tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
+ break;
+
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld(s, args, 0);
break;
@@ -1084,6 +1125,9 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_shl_i32, { "r", "0", "ci" } },
{ INDEX_op_shr_i32, { "r", "0", "ci" } },
{ INDEX_op_sar_i32, { "r", "0", "ci" } },
+ { INDEX_op_sar_i32, { "r", "0", "ci" } },
+ { INDEX_op_rotl_i32, { "r", "0", "ci" } },
+ { INDEX_op_rotr_i32, { "r", "0", "ci" } },
{ INDEX_op_brcond_i32, { "r", "ri" } },
@@ -1091,6 +1135,16 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
{ INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
+ { INDEX_op_bswap16_i32, { "r", "0" } },
+ { INDEX_op_bswap32_i32, { "r", "0" } },
+
+ { INDEX_op_neg_i32, { "r", "0" } },
+
+ { INDEX_op_not_i32, { "r", "0" } },
+
+ { INDEX_op_ext8s_i32, { "r", "q" } },
+ { INDEX_op_ext16s_i32, { "r", "r" } },
+
#if TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index 37fdaa5..301a5bf 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -44,11 +44,19 @@ enum {
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET 0
+/* optional instructions */
+#define TCG_TARGET_HAS_bswap16_i32
+#define TCG_TARGET_HAS_bswap32_i32
+#define TCG_TARGET_HAS_neg_i32
+#define TCG_TARGET_HAS_not_i32
+#define TCG_TARGET_HAS_ext8s_i32
+#define TCG_TARGET_HAS_ext16s_i32
+#define TCG_TARGET_HAS_rot_i32
+
/* Note: must be synced with dyngen-exec.h */
#define TCG_AREG0 TCG_REG_EBP
#define TCG_AREG1 TCG_REG_EBX
#define TCG_AREG2 TCG_REG_ESI
-#define TCG_AREG3 TCG_REG_EDI
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index ad17468..e3f4b59 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -26,10 +26,13 @@ static uint8_t *tb_ret_addr;
#ifdef __APPLE__
#define LINKAGE_AREA_SIZE 24
-#define BACK_CHAIN_OFFSET 8
+#define LR_OFFSET 8
+#elif defined _AIX
+#define LINKAGE_AREA_SIZE 52
+#define LR_OFFSET 8
#else
#define LINKAGE_AREA_SIZE 8
-#define BACK_CHAIN_OFFSET 4
+#define LR_OFFSET 4
#endif
#define FAST_PATH
@@ -39,6 +42,7 @@ static uint8_t *tb_ret_addr;
#define ADDEND_OFFSET 4
#endif
+#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"r0",
"r1",
@@ -73,6 +77,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"r30",
"r31"
};
+#endif
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R14,
@@ -104,10 +109,9 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R11,
#endif
TCG_REG_R12,
+#ifndef __linux__
TCG_REG_R13,
- TCG_REG_R0,
- TCG_REG_R1,
- TCG_REG_R2,
+#endif
TCG_REG_R24,
TCG_REG_R25,
TCG_REG_R26,
@@ -135,6 +139,9 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R11,
TCG_REG_R13,
#endif
+#ifdef _AIX
+ TCG_REG_R13,
+#endif
TCG_REG_R14,
TCG_REG_R15,
TCG_REG_R16,
@@ -145,6 +152,11 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R21,
TCG_REG_R22,
TCG_REG_R23,
+ TCG_REG_R24,
+ TCG_REG_R25,
+ TCG_REG_R26,
+ /* TCG_REG_R27, */ /* currently used for the global env, so no
+ need to save */
TCG_REG_R28,
TCG_REG_R29,
TCG_REG_R30,
@@ -204,7 +216,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
/* maximum number of register used for input function arguments */
static int tcg_target_get_call_iarg_regs_count(int flags)
{
- return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
+ return ARRAY_SIZE (tcg_target_call_iarg_regs);
}
/* parse target specific constraints */
@@ -360,9 +372,6 @@ static int tcg_target_const_match(tcg_target_long val,
#define SRW XO31(536)
#define SRAW XO31(792)
-#define LMW OPCD(46)
-#define STMW OPCD(47)
-
#define TW XO31(4)
#define TRAP (TW | TO (31))
@@ -453,6 +462,24 @@ static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
}
}
+#ifdef _AIX
+static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg)
+{
+ int reg;
+
+ if (const_arg) {
+ reg = 2;
+ tcg_out_movi (s, TCG_TYPE_I32, reg, arg);
+ }
+ else reg = arg;
+
+ tcg_out32 (s, LWZ | RT (0) | RA (reg));
+ tcg_out32 (s, MTSPR | RA (0) | CTR);
+ tcg_out32 (s, LWZ | RT (2) | RA (reg) | 4);
+ tcg_out32 (s, BCCTR | BO_ALWAYS | LK);
+}
+#endif
+
#if defined(CONFIG_SOFTMMU)
#include "../../softmmu_defs.h"
@@ -474,9 +501,9 @@ static void *qemu_st_helpers[4] = {
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
{
- int addr_reg, data_reg, data_reg2, r0, mem_index, s_bits, bswap;
+ int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
#ifdef CONFIG_SOFTMMU
- int r1, r2;
+ int r2;
void *label1_ptr, *label2_ptr;
#endif
#if TARGET_LONG_BITS == 64
@@ -546,7 +573,11 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
#endif
+#ifdef _AIX
+ tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
+#else
tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]);
+#endif
switch (opc) {
case 0|4:
tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
@@ -599,6 +630,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
#else /* !CONFIG_SOFTMMU */
r0 = addr_reg;
+ r1 = 3;
#endif
#ifdef TARGET_WORDS_BIGENDIAN
@@ -632,17 +664,9 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
break;
case 3:
if (bswap) {
- if (r0 == data_reg) {
- tcg_out32 (s, LWBRX | RT (0) | RB (r0));
- tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
- tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
- tcg_out_mov (s, data_reg, 0);
- }
- else {
- tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
- tcg_out32 (s, ADDI | RT (r0) | RA (r0) | 4);
- tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r0));
- }
+ tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
+ tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
+ tcg_out32 (s, LWBRX | RT (data_reg2) | RB (r1));
}
else {
if (r0 == data_reg2) {
@@ -771,7 +795,11 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
ir++;
tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
+#ifdef _AIX
+ tcg_out_call (s, (tcg_target_long) qemu_st_helpers[opc], 1);
+#else
tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]);
+#endif
label2_ptr = s->code_ptr;
tcg_out32 (s, B);
@@ -841,6 +869,16 @@ void tcg_target_qemu_prologue (TCGContext *s)
;
frame_size = (frame_size + 15) & ~15;
+#ifdef _AIX
+ {
+ uint32_t addr;
+
+ /* First emit adhoc function descriptor */
+ addr = (uint32_t) s->code_ptr + 12;
+ tcg_out32 (s, addr); /* entry point */
+ s->code_ptr += 8; /* skip TOC and environment pointer */
+ }
+#endif
tcg_out32 (s, MFSPR | RT (0) | LR);
tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
for (i = 0; i < ARRAY_SIZE (tcg_target_callee_save_regs); ++i)
@@ -850,7 +888,7 @@ void tcg_target_qemu_prologue (TCGContext *s)
| (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
)
);
- tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + BACK_CHAIN_OFFSET));
+ tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size + LR_OFFSET));
tcg_out32 (s, MTSPR | RS (3) | CTR);
tcg_out32 (s, BCCTR | BO_ALWAYS);
@@ -863,7 +901,7 @@ void tcg_target_qemu_prologue (TCGContext *s)
| (i * 4 + LINKAGE_AREA_SIZE + TCG_STATIC_CALL_ARGS_SIZE)
)
);
- tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + BACK_CHAIN_OFFSET));
+ tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size + LR_OFFSET));
tcg_out32 (s, MTSPR | RS (0) | LR);
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
tcg_out32 (s, BCLR | BO_ALWAYS);
@@ -1111,6 +1149,9 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
}
break;
case INDEX_op_call:
+#ifdef _AIX
+ tcg_out_call (s, args[0], const_args[0]);
+#else
if (const_args[0]) {
tcg_out_b (s, LK, args[0]);
}
@@ -1118,6 +1159,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out32 (s, MTSPR | RS (args[0]) | LR);
tcg_out32 (s, BCLR | BO_ALWAYS | LK);
}
+#endif
break;
case INDEX_op_jmp:
if (const_args[0]) {
@@ -1487,6 +1529,9 @@ void tcg_target_init(TCGContext *s)
#ifndef __APPLE__
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2);
#endif
+#ifdef __linux__
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13);
+#endif
tcg_add_target_add_op_defs(ppc_op_defs);
}
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index d46c19d..5faf730 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -65,11 +65,15 @@ enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_R1
#define TCG_TARGET_STACK_ALIGN 16
-#ifdef __APPLE__
+#if defined __APPLE__
#define TCG_TARGET_CALL_STACK_OFFSET 24
-#else
+#elif defined _AIX
+#define TCG_TARGET_CALL_STACK_OFFSET 52
+#elif defined __linux__
#define TCG_TARGET_CALL_ALIGN_ARGS 1
#define TCG_TARGET_CALL_STACK_OFFSET 8
+#else
+#error Unsupported system
#endif
/* optional instructions */
@@ -81,25 +85,3 @@ enum {
#define TCG_AREG0 TCG_REG_R27
#define TCG_AREG1 TCG_REG_R24
#define TCG_AREG2 TCG_REG_R25
-#define TCG_AREG3 TCG_REG_R26
-
-/* taken directly from tcg-dyngen.c */
-#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
-
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- unsigned long p;
-
- start &= ~(MIN_CACHE_LINE_SIZE - 1);
- stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
-
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- asm volatile ("isync" : : : "memory");
-}
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 6b16efa..a2f85ff 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -42,6 +42,7 @@ static uint8_t *tb_ret_addr;
#define CMP_L (1<<21)
#endif
+#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"r0",
"r1",
@@ -76,6 +77,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"r30",
"r31"
};
+#endif
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R14,
@@ -102,10 +104,6 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_R10,
TCG_REG_R11,
TCG_REG_R12,
- TCG_REG_R13,
- TCG_REG_R0,
- TCG_REG_R1,
- TCG_REG_R2,
TCG_REG_R24,
TCG_REG_R25,
TCG_REG_R26,
@@ -138,6 +136,11 @@ static const int tcg_target_callee_save_regs[] = {
TCG_REG_R21,
TCG_REG_R22,
TCG_REG_R23,
+ TCG_REG_R24,
+ TCG_REG_R25,
+ TCG_REG_R26,
+ /* TCG_REG_R27, */ /* currently used for the global env, so no
+ need to save */
TCG_REG_R28,
TCG_REG_R29,
TCG_REG_R30,
@@ -197,7 +200,7 @@ static void patch_reloc (uint8_t *code_ptr, int type,
/* maximum number of register used for input function arguments */
static int tcg_target_get_call_iarg_regs_count (int flags)
{
- return sizeof (tcg_target_call_iarg_regs) / sizeof (tcg_target_call_iarg_regs[0]);
+ return ARRAY_SIZE (tcg_target_call_iarg_regs);
}
/* parse target specific constraints */
@@ -303,6 +306,7 @@ static int tcg_target_const_match (tcg_target_long val,
#define RLDICL XO30( 0)
#define RLDICR XO30( 1)
+#define RLDIMI XO30( 3)
#define BCLR XO19( 16)
#define BCCTR XO19(528)
@@ -365,9 +369,6 @@ static int tcg_target_const_match (tcg_target_long val,
#define SRAD XO31(794)
#define SRADI XO31(413<<1)
-#define LMW OPCD( 46)
-#define STMW OPCD( 47)
-
#define TW XO31( 4)
#define TRAP (TW | TO (31))
@@ -494,6 +495,17 @@ static void tcg_out_ldst (TCGContext *s, int ret, int addr,
}
}
+static void tcg_out_ldsta (TCGContext *s, int ret, int addr,
+ int offset, int op1, int op2)
+{
+ if (offset == (int16_t) (offset & ~3))
+ tcg_out32 (s, op1 | RT (ret) | RA (addr) | (offset & 0xffff));
+ else {
+ tcg_out_movi (s, TCG_TYPE_I64, 0, offset);
+ tcg_out32 (s, op2 | RT (ret) | RA (addr) | RB (0));
+ }
+}
+
static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
{
tcg_target_long disp;
@@ -691,11 +703,10 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
break;
case 3:
if (bswap) {
- tcg_out32 (s, LWBRX | RT (0) | RB (r0));
- tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
- tcg_out32 (s, LWBRX | RT (data_reg) | RB (r1));
- tcg_out_rld (s, RLDICR, data_reg, data_reg, 32, 31);
- tcg_out32 (s, OR | SAB (0, data_reg, data_reg));
+ tcg_out_movi32 (s, 0, 4);
+ tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
+ tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
+ tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
}
else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
break;
@@ -858,7 +869,7 @@ static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
if (type == TCG_TYPE_I32)
tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
else
- tcg_out_ldst (s, ret, arg1, arg2, LD, LDX);
+ tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
}
static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
@@ -867,7 +878,7 @@ static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
if (type == TCG_TYPE_I32)
tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
else
- tcg_out_ldst (s, arg, arg1, arg2, STD, STDX);
+ tcg_out_ldsta (s, arg, arg1, arg2, STD, STDX);
}
static void ppc_addi32 (TCGContext *s, int rt, int ra, tcg_target_long si)
@@ -888,7 +899,7 @@ static void ppc_addi64 (TCGContext *s, int rt, int ra, tcg_target_long si)
{
/* XXX: suboptimal */
if (si == (int16_t) si
- || (((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0)
+ || ((((uint64_t) si >> 31) == 0) && (si & 0x8000) == 0))
ppc_addi32 (s, rt, ra, si);
else {
tcg_out_movi (s, TCG_TYPE_I64, 0, si);
@@ -1086,10 +1097,10 @@ static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args,
tcg_out_ldst (s, args[0], args[1], args[2], LWZ, LWZX);
break;
case INDEX_op_ld32s_i64:
- tcg_out_ldst (s, args[0], args[1], args[2], LWA, LWAX);
+ tcg_out_ldsta (s, args[0], args[1], args[2], LWA, LWAX);
break;
case INDEX_op_ld_i64:
- tcg_out_ldst (s, args[0], args[1], args[2], LD, LDX);
+ tcg_out_ldsta (s, args[0], args[1], args[2], LD, LDX);
break;
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
@@ -1104,7 +1115,7 @@ static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args,
tcg_out_ldst (s, args[0], args[1], args[2], STW, STWX);
break;
case INDEX_op_st_i64:
- tcg_out_ldst (s, args[0], args[1], args[2], STD, STDX);
+ tcg_out_ldsta (s, args[0], args[1], args[2], STD, STDX);
break;
case INDEX_op_add_i32:
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 2174db2..452bfda 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -81,25 +81,3 @@ enum {
#define TCG_AREG0 TCG_REG_R27
#define TCG_AREG1 TCG_REG_R24
#define TCG_AREG2 TCG_REG_R25
-#define TCG_AREG3 TCG_REG_R26
-
-/* taken directly from tcg-dyngen.c */
-#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
-
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- unsigned long p;
-
- start &= ~(MIN_CACHE_LINE_SIZE - 1);
- stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
-
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- asm volatile ("isync" : : : "memory");
-}
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index f36796d..23cd9cd 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%g0",
"%g1",
@@ -56,6 +57,7 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%i6",
"%i7",
};
+#endif
static const int tcg_target_reg_alloc_order[] = {
TCG_REG_L0,
@@ -115,6 +117,13 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_abort();
*(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value;
break;
+ case R_SPARC_WDISP19:
+ value -= (long)code_ptr;
+ value >>= 2;
+ if (!check_fit_tl(value, 19))
+ tcg_abort();
+ *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x7ffff) | value;
+ break;
default:
tcg_abort();
}
@@ -183,6 +192,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define INSN_ASI(x) ((x) << 5)
#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
+#define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
#define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
#define INSN_COND(x, a) (((x) << 25) | ((a) << 29))
@@ -419,7 +429,7 @@ static inline void tcg_out_nop(TCGContext *s)
tcg_out_sethi(s, TCG_REG_G0, 0);
}
-static void tcg_out_branch(TCGContext *s, int opc, int label_index)
+static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
{
int32_t val;
TCGLabel *l = &s->labels[label_index];
@@ -434,6 +444,25 @@ static void tcg_out_branch(TCGContext *s, int opc, int label_index)
}
}
+#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
+{
+ int32_t val;
+ TCGLabel *l = &s->labels[label_index];
+
+ if (l->has_value) {
+ val = l->u.value - (tcg_target_long)s->code_ptr;
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) |
+ INSN_OFF19(l->u.value - (unsigned long)s->code_ptr)));
+ } else {
+ tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0);
+ tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) | 0));
+ }
+}
+#endif
+
static const uint8_t tcg_cond_to_bcond[10] = {
[TCG_COND_EQ] = COND_E,
[TCG_COND_NE] = COND_NE,
@@ -447,9 +476,24 @@ static const uint8_t tcg_cond_to_bcond[10] = {
[TCG_COND_GTU] = COND_GU,
};
-static void tcg_out_brcond(TCGContext *s, int cond,
- TCGArg arg1, TCGArg arg2, int const_arg2,
- int label_index)
+static void tcg_out_brcond_i32(TCGContext *s, int cond,
+ TCGArg arg1, TCGArg arg2, int const_arg2,
+ int label_index)
+{
+ if (const_arg2 && arg2 == 0)
+ /* orcc %g0, r, %g0 */
+ tcg_out_arith(s, TCG_REG_G0, TCG_REG_G0, arg1, ARITH_ORCC);
+ else
+ /* subcc r1, r2, %g0 */
+ tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
+ tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index);
+ tcg_out_nop(s);
+}
+
+#if defined(__sparc_v9__) && !defined(__sparc_v8plus__)
+static void tcg_out_brcond_i64(TCGContext *s, int cond,
+ TCGArg arg1, TCGArg arg2, int const_arg2,
+ int label_index)
{
if (const_arg2 && arg2 == 0)
/* orcc %g0, r, %g0 */
@@ -457,9 +501,10 @@ static void tcg_out_brcond(TCGContext *s, int cond,
else
/* subcc r1, r2, %g0 */
tcg_out_arith(s, TCG_REG_G0, arg1, arg2, ARITH_SUBCC);
- tcg_out_branch(s, tcg_cond_to_bcond[cond], label_index);
+ tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index);
tcg_out_nop(s);
}
+#endif
/* Generate global QEMU prologue and epilogue code */
void tcg_target_qemu_prologue(TCGContext *s)
@@ -557,7 +602,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC);
/* will become:
- be label1 */
+ be label1
+ or
+ be,pt %xcc label1 */
label1_ptr = (uint32_t *)s->code_ptr;
tcg_out32(s, 0);
@@ -576,9 +623,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_LD_OP);
/* data_reg = sign_extend(arg0) */
switch(opc) {
@@ -623,9 +672,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_nop(s);
/* label1: */
+#if TARGET_LONG_BITS == 32
+ /* be label1 */
*label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) |
INSN_OFF22((unsigned long)s->code_ptr -
(unsigned long)label1_ptr));
+#else
+ /* be,pt %xcc label1 */
+ *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr -
+ (unsigned long)label1_ptr));
+#endif
/* ld [arg1 + x], arg1 */
tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
@@ -757,7 +814,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_arith(s, TCG_REG_G0, arg0, arg2, ARITH_SUBCC);
/* will become:
- be label1 */
+ be label1
+ or
+ be,pt %xcc label1 */
label1_ptr = (uint32_t *)s->code_ptr;
tcg_out32(s, 0);
@@ -779,9 +838,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_LD_OP);
/* will become:
ba label2 */
@@ -791,10 +852,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* nop (delay slot) */
tcg_out_nop(s);
- /* label1: */
+#if TARGET_LONG_BITS == 32
+ /* be label1 */
*label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x2) |
INSN_OFF22((unsigned long)s->code_ptr -
(unsigned long)label1_ptr));
+#else
+ /* be,pt %xcc label1 */
+ *label1_ptr = (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1) |
+ (0x5 << 19) | INSN_OFF19((unsigned long)s->code_ptr -
+ (unsigned long)label1_ptr));
+#endif
/* ld [arg1 + x], arg1 */
tcg_out_ldst(s, arg1, arg1, offsetof(CPUTLBEntry, addend) -
@@ -903,13 +971,15 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
global registers */
// delay slot
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_ST_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_ST_OP);
tcg_out_ldst(s, TCG_AREG0, TCG_REG_CALL_STACK,
- TCG_TARGET_CALL_STACK_OFFSET - sizeof(long), HOST_LD_OP);
+ TCG_TARGET_CALL_STACK_OFFSET - TCG_STATIC_CALL_ARGS_SIZE -
+ sizeof(long), HOST_LD_OP);
break;
case INDEX_op_jmp:
case INDEX_op_br:
- tcg_out_branch(s, COND_A, args[0]);
+ tcg_out_branch_i32(s, COND_A, args[0]);
tcg_out_nop(s);
break;
case INDEX_op_movi_i32:
@@ -1001,8 +1071,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
#endif
case INDEX_op_brcond_i32:
- tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
- args[3]);
+ tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
+ args[3]);
break;
case INDEX_op_qemu_ld8u:
@@ -1066,8 +1136,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
goto gen_arith32;
case INDEX_op_brcond_i64:
- tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
- args[3]);
+ tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
+ args[3]);
break;
case INDEX_op_qemu_ld64:
tcg_out_qemu_ld(s, args, 3);
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 8dc07d3..97f3533 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -75,19 +75,21 @@ enum {
#define TCG_REG_CALL_STACK TCG_REG_I6
#ifdef __arch64__
// Reserve space for AREG0
-#define TCG_TARGET_STACK_MINFRAME (176 + 2 * (int)sizeof(long))
-#define TCG_TARGET_CALL_STACK_OFFSET (2047 + TCG_TARGET_STACK_MINFRAME)
+#define TCG_TARGET_STACK_MINFRAME (176 + 4 * (int)sizeof(long) + \
+ TCG_STATIC_CALL_ARGS_SIZE)
+#define TCG_TARGET_CALL_STACK_OFFSET (2047 - 16)
#define TCG_TARGET_STACK_ALIGN 16
#else
// AREG0 + one word for alignment
-#define TCG_TARGET_STACK_MINFRAME (92 + (2 + 1) * (int)sizeof(long))
+#define TCG_TARGET_STACK_MINFRAME (92 + (2 + 1) * (int)sizeof(long) + \
+ TCG_STATIC_CALL_ARGS_SIZE)
#define TCG_TARGET_CALL_STACK_OFFSET TCG_TARGET_STACK_MINFRAME
#define TCG_TARGET_STACK_ALIGN 8
#endif
/* optional instructions */
-//#define TCG_TARGET_HAS_bswap_i32
-//#define TCG_TARGET_HAS_bswap_i64
+//#define TCG_TARGET_HAS_bswap32_i32
+//#define TCG_TARGET_HAS_bswap64_i64
//#define TCG_TARGET_HAS_neg_i32
//#define TCG_TARGET_HAS_neg_i64
@@ -97,8 +99,6 @@ enum {
#define TCG_AREG0 TCG_REG_G2
#define TCG_AREG1 TCG_REG_G3
#define TCG_AREG2 TCG_REG_G4
-#define TCG_AREG3 TCG_REG_G5
-#define TCG_AREG4 TCG_REG_G6
#elif defined(__sparc_v9__)
#define TCG_AREG0 TCG_REG_G5
#define TCG_AREG1 TCG_REG_G6
@@ -107,7 +107,6 @@ enum {
#define TCG_AREG0 TCG_REG_G6
#define TCG_AREG1 TCG_REG_G1
#define TCG_AREG2 TCG_REG_G2
-#define TCG_AREG3 TCG_REG_G3
#endif
static inline void flush_icache_range(unsigned long start, unsigned long stop)
diff --git a/tcg/tcg-dyngen.c b/tcg/tcg-dyngen.c
deleted file mode 100644
index b4ceb5e..0000000
--- a/tcg/tcg-dyngen.c
+++ /dev/null
@@ -1,431 +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.
- */
-#include <assert.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-
-#include "config.h"
-#include "osdep.h"
-
-#include "tcg.h"
-
-int __op_param1, __op_param2, __op_param3;
-#if defined(__sparc__) || defined(__arm__)
- void __op_gen_label1(){}
- void __op_gen_label2(){}
- void __op_gen_label3(){}
-#else
- int __op_gen_label1, __op_gen_label2, __op_gen_label3;
-#endif
-int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
-
-#if 0
-#if defined(__s390__)
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
-#elif defined(__ia64__)
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- while (start < stop) {
- asm volatile ("fc %0" :: "r"(start));
- start += 32;
- }
- asm volatile (";;sync.i;;srlz.i;;");
-}
-#elif defined(__powerpc__)
-
-#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
-
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- unsigned long p;
-
- start &= ~(MIN_CACHE_LINE_SIZE - 1);
- stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
-
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
- asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
- }
- asm volatile ("sync" : : : "memory");
- asm volatile ("isync" : : : "memory");
-}
-#elif defined(__alpha__)
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- asm ("imb");
-}
-#elif defined(__sparc__)
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- unsigned long p;
-
- p = start & ~(8UL - 1UL);
- stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
-
- for (; p < stop; p += 8)
- __asm__ __volatile__("flush\t%0" : : "r" (p));
-}
-#elif defined(__arm__)
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- register unsigned long _beg __asm ("a1") = start;
- register unsigned long _end __asm ("a2") = stop;
- register unsigned long _flg __asm ("a3") = 0;
- __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
-}
-#elif defined(__mc68000)
-
-# include <asm/cachectl.h>
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
-}
-#elif defined(__mips__)
-
-#include <sys/cachectl.h>
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
- _flush_cache ((void *)start, stop - start, BCACHE);
-}
-#else
-#error unsupported CPU
-#endif
-
-#ifdef __alpha__
-
-register int gp asm("$29");
-
-static inline void immediate_ldah(void *p, int val) {
- uint32_t *dest = p;
- long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff;
-
- *dest &= ~0xffff;
- *dest |= high;
- *dest |= 31 << 16;
-}
-static inline void immediate_lda(void *dest, int val) {
- *(uint16_t *) dest = val;
-}
-void fix_bsr(void *p, int offset) {
- uint32_t *dest = p;
- *dest &= ~((1 << 21) - 1);
- *dest |= (offset >> 2) & ((1 << 21) - 1);
-}
-
-#endif /* __alpha__ */
-
-#ifdef __ia64
-
-/* Patch instruction with "val" where "mask" has 1 bits. */
-static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
-{
- uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
-# define insn_mask ((1UL << 41) - 1)
- unsigned long shift;
-
- b0 = b[0]; b1 = b[1];
- shift = 5 + 41 * (insn_addr % 16); /* 5 template, 3 x 41-bit insns */
- if (shift >= 64) {
- m1 = mask << (shift - 64);
- v1 = val << (shift - 64);
- } else {
- m0 = mask << shift; m1 = mask >> (64 - shift);
- v0 = val << shift; v1 = val >> (64 - shift);
- b[0] = (b0 & ~m0) | (v0 & m0);
- }
- b[1] = (b1 & ~m1) | (v1 & m1);
-}
-
-static inline void ia64_patch_imm60 (uint64_t insn_addr, uint64_t val)
-{
- ia64_patch(insn_addr,
- 0x011ffffe000UL,
- ( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
- | ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */));
- ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
-}
-
-static inline void ia64_imm64 (void *insn, uint64_t val)
-{
- /* Ignore the slot number of the relocation; GCC and Intel
- toolchains differed for some time on whether IMM64 relocs are
- against slot 1 (Intel) or slot 2 (GCC). */
- uint64_t insn_addr = (uint64_t) insn & ~3UL;
-
- ia64_patch(insn_addr + 2,
- 0x01fffefe000UL,
- ( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
- | ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */
- | ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */
- | ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */
- | ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */)
- );
- ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
-}
-
-static inline void ia64_imm60b (void *insn, uint64_t val)
-{
- /* Ignore the slot number of the relocation; GCC and Intel
- toolchains differed for some time on whether IMM64 relocs are
- against slot 1 (Intel) or slot 2 (GCC). */
- uint64_t insn_addr = (uint64_t) insn & ~3UL;
-
- if (val + ((uint64_t) 1 << 59) >= (1UL << 60))
- fprintf(stderr, "%s: value %ld out of IMM60 range\n",
- __FUNCTION__, (int64_t) val);
- ia64_patch_imm60(insn_addr + 2, val);
-}
-
-static inline void ia64_imm22 (void *insn, uint64_t val)
-{
- if (val + (1 << 21) >= (1 << 22))
- fprintf(stderr, "%s: value %li out of IMM22 range\n",
- __FUNCTION__, (int64_t)val);
- ia64_patch((uint64_t) insn, 0x01fffcfe000UL,
- ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
- | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
- | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
- | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
-}
-
-/* Like ia64_imm22(), but also clear bits 20-21. For addl, this has
- the effect of turning "addl rX=imm22,rY" into "addl
- rX=imm22,r0". */
-static inline void ia64_imm22_r0 (void *insn, uint64_t val)
-{
- if (val + (1 << 21) >= (1 << 22))
- fprintf(stderr, "%s: value %li out of IMM22 range\n",
- __FUNCTION__, (int64_t)val);
- ia64_patch((uint64_t) insn, 0x01fffcfe000UL | (0x3UL << 20),
- ( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
- | ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
- | ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
- | ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
-}
-
-static inline void ia64_imm21b (void *insn, uint64_t val)
-{
- if (val + (1 << 20) >= (1 << 21))
- fprintf(stderr, "%s: value %li out of IMM21b range\n",
- __FUNCTION__, (int64_t)val);
- ia64_patch((uint64_t) insn, 0x11ffffe000UL,
- ( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
- | ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
-}
-
-static inline void ia64_nop_b (void *insn)
-{
- ia64_patch((uint64_t) insn, (1UL << 41) - 1, 2UL << 37);
-}
-
-static inline void ia64_ldxmov(void *insn, uint64_t val)
-{
- if (val + (1 << 21) < (1 << 22))
- ia64_patch((uint64_t) insn, 0x1fff80fe000UL, 8UL << 37);
-}
-
-static inline int ia64_patch_ltoff(void *insn, uint64_t val,
- int relaxable)
-{
- if (relaxable && (val + (1 << 21) < (1 << 22))) {
- ia64_imm22_r0(insn, val);
- return 0;
- }
- return 1;
-}
-
-struct ia64_fixup {
- struct ia64_fixup *next;
- void *addr; /* address that needs to be patched */
- long value;
-};
-
-#define IA64_PLT(insn, plt_index) \
-do { \
- struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
- fixup->next = plt_fixes; \
- plt_fixes = fixup; \
- fixup->addr = (insn); \
- fixup->value = (plt_index); \
- plt_offset[(plt_index)] = 1; \
-} while (0)
-
-#define IA64_LTOFF(insn, val, relaxable) \
-do { \
- if (ia64_patch_ltoff(insn, val, relaxable)) { \
- struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
- fixup->next = ltoff_fixes; \
- ltoff_fixes = fixup; \
- fixup->addr = (insn); \
- fixup->value = (val); \
- } \
-} while (0)
-
-static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
- struct ia64_fixup *ltoff_fixes,
- uint64_t gp,
- struct ia64_fixup *plt_fixes,
- int num_plts,
- unsigned long *plt_target,
- unsigned int *plt_offset)
-{
- static const uint8_t plt_bundle[] = {
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; movl r1=GP */
- 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60,
-
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0
- };
- uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start;
- uint64_t *vp;
- struct ia64_fixup *fixup;
- unsigned int offset = 0;
- struct fdesc {
- long ip;
- long gp;
- } *fdesc;
- int i;
-
- if (plt_fixes) {
- plt_start = gen_code_ptr;
-
- for (i = 0; i < num_plts; ++i) {
- if (plt_offset[i]) {
- plt_offset[i] = offset;
- offset += sizeof(plt_bundle);
-
- fdesc = (struct fdesc *) plt_target[i];
- memcpy(gen_code_ptr, plt_bundle, sizeof(plt_bundle));
- ia64_imm64 (gen_code_ptr + 0x02, fdesc->gp);
- ia64_imm60b(gen_code_ptr + 0x12,
- (fdesc->ip - (long) (gen_code_ptr + 0x10)) >> 4);
- gen_code_ptr += sizeof(plt_bundle);
- }
- }
-
- for (fixup = plt_fixes; fixup; fixup = fixup->next)
- ia64_imm21b(fixup->addr,
- ((long) plt_start + plt_offset[fixup->value]
- - ((long) fixup->addr & ~0xf)) >> 4);
- }
-
- got_start = gen_code_ptr;
-
- /* First, create the GOT: */
- for (fixup = ltoff_fixes; fixup; fixup = fixup->next) {
- /* first check if we already have this value in the GOT: */
- for (vp = (uint64_t *) got_start; vp < (uint64_t *) gen_code_ptr; ++vp)
- if (*vp == fixup->value)
- break;
- if (vp == (uint64_t *) gen_code_ptr) {
- /* Nope, we need to put the value in the GOT: */
- *vp = fixup->value;
- gen_code_ptr += 8;
- }
- ia64_imm22(fixup->addr, (long) vp - gp);
- }
- /* Keep code ptr aligned. */
- if ((long) gen_code_ptr & 15)
- gen_code_ptr += 8;
- *gen_code_pp = gen_code_ptr;
-}
-#endif
-#endif
-
-#ifdef CONFIG_DYNGEN_OP
-
-#if defined __hppa__
-struct hppa_branch_stub {
- uint32_t *location;
- long target;
- struct hppa_branch_stub *next;
-};
-
-#define HPPA_RECORD_BRANCH(LIST, LOC, TARGET) \
-do { \
- struct hppa_branch_stub *stub = alloca(sizeof(struct hppa_branch_stub)); \
- stub->location = LOC; \
- stub->target = TARGET; \
- stub->next = LIST; \
- LIST = stub; \
-} while (0)
-
-static inline void hppa_process_stubs(struct hppa_branch_stub *stub,
- uint8_t **gen_code_pp)
-{
- uint32_t *s = (uint32_t *)*gen_code_pp;
- uint32_t *p = s + 1;
-
- if (!stub) return;
-
- for (; stub != NULL; stub = stub->next) {
- unsigned long l = (unsigned long)p;
- /* stub:
- * ldil L'target, %r1
- * be,n R'target(%sr4,%r1)
- */
- *p++ = 0x20200000 | reassemble_21(lrsel(stub->target, 0));
- *p++ = 0xe0202002 | (reassemble_17(rrsel(stub->target, 0) >> 2));
- hppa_patch17f(stub->location, l, 0);
- }
- /* b,l,n stub,%r0 */
- *s = 0xe8000002 | reassemble_17((p - s) - 2);
- *gen_code_pp = (uint8_t *)p;
-}
-#endif /* __hppa__ */
-
-const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr)
-{
- uint8_t *gen_code_ptr;
-
-#ifdef __hppa__
- struct hppa_branch_stub *hppa_stubs = NULL;
-#endif
-
- gen_code_ptr = s->code_ptr;
- switch(opc) {
-
-/* op.h is dynamically generated by dyngen.c from op.c */
-#include "op.h"
-
- default:
- tcg_abort();
- }
-
-#ifdef __hppa__
- hppa_process_stubs(hppa_stubs, &gen_code_ptr);
-#endif
-
- s->code_ptr = gen_code_ptr;
- return opparam_ptr;
-}
-#endif
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bc6be85..daeb025 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -23,17 +23,18 @@
*/
#include "tcg.h"
-#ifdef CONFIG_DYNGEN_OP
-/* legacy dyngen operations */
-#include "gen-op.h"
-#endif
-
int gen_new_label(void);
-static inline void tcg_gen_op1(int opc, TCGv arg1)
+static inline void tcg_gen_op1_i32(int opc, TCGv_i32 arg1)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+}
+
+static inline void tcg_gen_op1_i64(int opc, TCGv_i64 arg1)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
}
static inline void tcg_gen_op1i(int opc, TCGArg arg1)
@@ -42,17 +43,31 @@ static inline void tcg_gen_op1i(int opc, TCGArg arg1)
*gen_opparam_ptr++ = arg1;
}
-static inline void tcg_gen_op2(int opc, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_op2_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+}
+
+static inline void tcg_gen_op2_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
}
-static inline void tcg_gen_op2i(int opc, TCGv arg1, TCGArg arg2)
+static inline void tcg_gen_op2i_i32(int opc, TCGv_i32 arg1, TCGArg arg2)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = arg2;
+}
+
+static inline void tcg_gen_op2i_i64(int opc, TCGv_i64 arg1, TCGArg arg2)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
*gen_opparam_ptr++ = arg2;
}
@@ -63,98 +78,230 @@ static inline void tcg_gen_op2ii(int opc, TCGArg arg1, TCGArg arg2)
*gen_opparam_ptr++ = arg2;
}
-static inline void tcg_gen_op3(int opc, TCGv arg1, TCGv arg2, TCGv arg3)
+static inline void tcg_gen_op3_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
}
-static inline void tcg_gen_op3i(int opc, TCGv arg1, TCGv arg2, TCGArg arg3)
+static inline void tcg_gen_op3_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+}
+
+static inline void tcg_gen_op3i_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGArg arg3)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
*gen_opparam_ptr++ = arg3;
}
-static inline void tcg_gen_op4(int opc, TCGv arg1, TCGv arg2, TCGv arg3,
- TCGv arg4)
+static inline void tcg_gen_op3i_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGArg arg3)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = arg3;
+}
+
+static inline void tcg_gen_ldst_op_i32(int opc, TCGv_i32 val, TCGv_ptr base,
+ TCGArg offset)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(val);
+ *gen_opparam_ptr++ = GET_TCGV_PTR(base);
+ *gen_opparam_ptr++ = offset;
+}
+
+static inline void tcg_gen_ldst_op_i64(int opc, TCGv_i64 val, TCGv_ptr base,
+ TCGArg offset)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(val);
+ *gen_opparam_ptr++ = GET_TCGV_PTR(base);
+ *gen_opparam_ptr++ = offset;
+}
+
+static inline void tcg_gen_qemu_ldst_op_i64_i32(int opc, TCGv_i64 val, TCGv_i32 addr,
+ TCGArg mem_index)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(val);
+ *gen_opparam_ptr++ = GET_TCGV_I32(addr);
+ *gen_opparam_ptr++ = mem_index;
+}
+
+static inline void tcg_gen_qemu_ldst_op_i64_i64(int opc, TCGv_i64 val, TCGv_i64 addr,
+ TCGArg mem_index)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(val);
+ *gen_opparam_ptr++ = GET_TCGV_I64(addr);
+ *gen_opparam_ptr++ = mem_index;
+}
+
+static inline void tcg_gen_op4_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGv_i32 arg4)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+}
+
+static inline void tcg_gen_op4_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGv_i64 arg4)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+}
+
+static inline void tcg_gen_op4i_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGArg arg4)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = arg4;
+}
+
+static inline void tcg_gen_op4i_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGArg arg4)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
- *gen_opparam_ptr++ = GET_TCGV(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = arg4;
}
-static inline void tcg_gen_op4i(int opc, TCGv arg1, TCGv arg2, TCGv arg3,
- TCGArg arg4)
+static inline void tcg_gen_op4ii_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGArg arg3, TCGArg arg4)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = arg3;
*gen_opparam_ptr++ = arg4;
}
-static inline void tcg_gen_op4ii(int opc, TCGv arg1, TCGv arg2, TCGArg arg3,
- TCGArg arg4)
+static inline void tcg_gen_op4ii_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGArg arg3, TCGArg arg4)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
*gen_opparam_ptr++ = arg3;
*gen_opparam_ptr++ = arg4;
}
-static inline void tcg_gen_op5(int opc, TCGv arg1, TCGv arg2,
- TCGv arg3, TCGv arg4,
- TCGv arg5)
+static inline void tcg_gen_op5_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg5);
+}
+
+static inline void tcg_gen_op5_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGv_i64 arg4, TCGv_i64 arg5)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
- *gen_opparam_ptr++ = GET_TCGV(arg4);
- *gen_opparam_ptr++ = GET_TCGV(arg5);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg5);
}
-static inline void tcg_gen_op5i(int opc, TCGv arg1, TCGv arg2,
- TCGv arg3, TCGv arg4,
- TCGArg arg5)
+static inline void tcg_gen_op5i_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGv_i32 arg4, TCGArg arg5)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
- *gen_opparam_ptr++ = GET_TCGV(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
*gen_opparam_ptr++ = arg5;
}
-static inline void tcg_gen_op6(int opc, TCGv arg1, TCGv arg2,
- TCGv arg3, TCGv arg4,
- TCGv arg5, TCGv arg6)
+static inline void tcg_gen_op5i_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGv_i64 arg4, TCGArg arg5)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
- *gen_opparam_ptr++ = GET_TCGV(arg4);
- *gen_opparam_ptr++ = GET_TCGV(arg5);
- *gen_opparam_ptr++ = GET_TCGV(arg6);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+ *gen_opparam_ptr++ = arg5;
+}
+
+static inline void tcg_gen_op6_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5,
+ TCGv_i32 arg6)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg5);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg6);
}
-static inline void tcg_gen_op6ii(int opc, TCGv arg1, TCGv arg2,
- TCGv arg3, TCGv arg4,
- TCGArg arg5, TCGArg arg6)
+static inline void tcg_gen_op6_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGv_i64 arg4, TCGv_i64 arg5,
+ TCGv_i64 arg6)
{
*gen_opc_ptr++ = opc;
- *gen_opparam_ptr++ = GET_TCGV(arg1);
- *gen_opparam_ptr++ = GET_TCGV(arg2);
- *gen_opparam_ptr++ = GET_TCGV(arg3);
- *gen_opparam_ptr++ = GET_TCGV(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg5);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg6);
+}
+
+static inline void tcg_gen_op6ii_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
+ TCGv_i32 arg3, TCGv_i32 arg4, TCGArg arg5,
+ TCGArg arg6)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg4);
+ *gen_opparam_ptr++ = arg5;
+ *gen_opparam_ptr++ = arg6;
+}
+
+static inline void tcg_gen_op6ii_i64(int opc, TCGv_i64 arg1, TCGv_i64 arg2,
+ TCGv_i64 arg3, TCGv_i64 arg4, TCGArg arg5,
+ TCGArg arg6)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg4);
*gen_opparam_ptr++ = arg5;
*gen_opparam_ptr++ = arg6;
}
@@ -169,232 +316,134 @@ static inline void tcg_gen_br(int label)
tcg_gen_op1i(INDEX_op_br, label);
}
-static inline void tcg_gen_mov_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 arg)
{
- if (GET_TCGV(ret) != GET_TCGV(arg))
- tcg_gen_op2(INDEX_op_mov_i32, ret, arg);
+ if (!TCGV_EQUAL_I32(ret, arg))
+ tcg_gen_op2_i32(INDEX_op_mov_i32, ret, arg);
}
-static inline void tcg_gen_movi_i32(TCGv ret, int32_t arg)
+static inline void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
{
- tcg_gen_op2i(INDEX_op_movi_i32, ret, arg);
+ tcg_gen_op2i_i32(INDEX_op_movi_i32, ret, arg);
}
/* helper calls */
-#define TCG_HELPER_CALL_FLAGS 0
+static inline void tcg_gen_helperN(void *func, int flags, int sizemask,
+ TCGArg ret, int nargs, TCGArg *args)
+{
+ TCGv_ptr fn;
+ fn = tcg_const_ptr((tcg_target_long)func);
+ tcg_gen_callN(&tcg_ctx, fn, flags, sizemask, ret,
+ nargs, args);
+ tcg_temp_free_ptr(fn);
+}
-static inline void tcg_gen_helper_0_0(void *func)
+/* FIXME: Should this be pure? */
+static inline void tcg_gen_helper64(void *func, TCGv_i64 ret,
+ TCGv_i64 a, TCGv_i64 b)
{
- TCGv t0;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 0, NULL, 0, NULL);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_0_1(void *func, TCGv arg)
-{
- TCGv t0;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 0, NULL, 1, &arg);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_0_2(void *func, TCGv arg1, TCGv arg2)
-{
- TCGv args[2];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 0, NULL, 2, args);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_0_3(void *func,
- TCGv arg1, TCGv arg2, TCGv arg3)
-{
- TCGv args[3];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- args[2] = arg3;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 0, NULL, 3, args);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_0_4(void *func, TCGv arg1, TCGv arg2,
- TCGv arg3, TCGv arg4)
-{
- TCGv args[4];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- args[2] = arg3;
- args[3] = arg4;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 0, NULL, 4, args);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_1_0(void *func, TCGv ret)
-{
- TCGv t0;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 1, &ret, 0, NULL);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_1_1(void *func, TCGv ret, TCGv arg1)
-{
- TCGv t0;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 1, &ret, 1, &arg1);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_1_2(void *func, TCGv ret,
- TCGv arg1, TCGv arg2)
-{
- TCGv args[2];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 1, &ret, 2, args);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_1_3(void *func, TCGv ret,
- TCGv arg1, TCGv arg2, TCGv arg3)
-{
- TCGv args[3];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- args[2] = arg3;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 1, &ret, 3, args);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_helper_1_4(void *func, TCGv ret,
- TCGv arg1, TCGv arg2, TCGv arg3,
- TCGv arg4)
-{
- TCGv args[4];
- TCGv t0;
- args[0] = arg1;
- args[1] = arg2;
- args[2] = arg3;
- args[3] = arg4;
- t0 = tcg_const_ptr((tcg_target_long)func);
- tcg_gen_call(&tcg_ctx,
- t0, TCG_HELPER_CALL_FLAGS,
- 1, &ret, 4, args);
- tcg_temp_free(t0);
+ TCGv_ptr fn;
+ TCGArg args[2];
+ fn = tcg_const_ptr((tcg_target_long)func);
+ args[0] = GET_TCGV_I64(a);
+ args[1] = GET_TCGV_I64(b);
+ tcg_gen_callN(&tcg_ctx, fn, 0, 7, GET_TCGV_I64(ret), 2, args);
+ tcg_temp_free_ptr(fn);
}
/* 32 bit ops */
-static inline void tcg_gen_ld8u_i32(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld8u_i32, ret, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_ld8u_i32, ret, arg2, offset);
}
-static inline void tcg_gen_ld8s_i32(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld8s_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld8s_i32, ret, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_ld8s_i32, ret, arg2, offset);
}
-static inline void tcg_gen_ld16u_i32(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld16u_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld16u_i32, ret, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_ld16u_i32, ret, arg2, offset);
}
-static inline void tcg_gen_ld16s_i32(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld16s_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld16s_i32, ret, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_ld16s_i32, ret, arg2, offset);
}
-static inline void tcg_gen_ld_i32(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld_i32(TCGv_i32 ret, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld_i32, ret, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_ld_i32, ret, arg2, offset);
}
-static inline void tcg_gen_st8_i32(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st8_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st8_i32, arg1, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_st8_i32, arg1, arg2, offset);
}
-static inline void tcg_gen_st16_i32(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st16_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st16_i32, arg1, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_st16_i32, arg1, arg2, offset);
}
-static inline void tcg_gen_st_i32(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st_i32(TCGv_i32 arg1, TCGv_ptr arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st_i32, arg1, arg2, offset);
+ tcg_gen_ldst_op_i32(INDEX_op_st_i32, arg1, arg2, offset);
}
-static inline void tcg_gen_add_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_add_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_add_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_add_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_addi_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_add_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_sub_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_sub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_sub_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_sub_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_subi_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2)
+{
+ TCGv_i32 t0 = tcg_const_i32(arg1);
+ tcg_gen_sub_i32(ret, t0, arg2);
+ tcg_temp_free_i32(t0);
+}
+
+static inline void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_sub_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_and_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_and_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_and_i32, ret, arg1, arg2);
+ if (TCGV_EQUAL_I32(arg1, arg2)) {
+ tcg_gen_mov_i32(ret, arg1);
+ } else {
+ tcg_gen_op3_i32(INDEX_op_and_i32, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_andi_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0) {
@@ -402,18 +451,22 @@ static inline void tcg_gen_andi_i32(TCGv ret, TCGv arg1, int32_t arg2)
} else if (arg2 == 0xffffffff) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_and_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_or_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_or_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_or_i32, ret, arg1, arg2);
+ if (TCGV_EQUAL_I32(arg1, arg2)) {
+ tcg_gen_mov_i32(ret, arg1);
+ } else {
+ tcg_gen_op3_i32(INDEX_op_or_i32, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_ori_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0xffffffff) {
@@ -421,688 +474,715 @@ static inline void tcg_gen_ori_i32(TCGv ret, TCGv arg1, int32_t arg2)
} else if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_or_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_xor_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_xor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_xor_i32, ret, arg1, arg2);
+ if (TCGV_EQUAL_I32(arg1, arg2)) {
+ tcg_gen_movi_i32(ret, 0);
+ } else {
+ tcg_gen_op3_i32(INDEX_op_xor_i32, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_xori_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
/* some cases can be optimized here */
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_xor_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_shl_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_shl_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_shl_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_shli_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_shl_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_shr_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_shr_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_shr_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_shri_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_shri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_shr_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_sar_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_sar_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_sar_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_sar_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_sari_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_sari_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i32(ret, arg1);
} else {
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_sar_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
}
-static inline void tcg_gen_brcond_i32(int cond, TCGv arg1, TCGv arg2,
+static inline void tcg_gen_brcond_i32(int cond, TCGv_i32 arg1, TCGv_i32 arg2,
int label_index)
{
- tcg_gen_op4ii(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
+ tcg_gen_op4ii_i32(INDEX_op_brcond_i32, arg1, arg2, cond, label_index);
}
-static inline void tcg_gen_brcondi_i32(int cond, TCGv arg1, int32_t arg2,
+static inline void tcg_gen_brcondi_i32(int cond, TCGv_i32 arg1, int32_t arg2,
int label_index)
{
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_brcond_i32(cond, arg1, t0, label_index);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
-static inline void tcg_gen_mul_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_mul_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_mul_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_mul_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_muli_i32(TCGv ret, TCGv arg1, int32_t arg2)
+static inline void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
{
- TCGv t0 = tcg_const_i32(arg2);
+ TCGv_i32 t0 = tcg_const_i32(arg2);
tcg_gen_mul_i32(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
}
#ifdef TCG_TARGET_HAS_div_i32
-static inline void tcg_gen_div_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_div_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_div_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_rem_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_rem_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_divu_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_divu_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_divu_i32, ret, arg1, arg2);
}
-static inline void tcg_gen_remu_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- tcg_gen_op3(INDEX_op_remu_i32, ret, arg1, arg2);
+ tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
}
#else
-static inline void tcg_gen_div_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
tcg_gen_sari_i32(t0, arg1, 31);
- tcg_gen_op5(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i32(INDEX_op_div2_i32, ret, t0, arg1, t0, arg2);
+ tcg_temp_free_i32(t0);
}
-static inline void tcg_gen_rem_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
tcg_gen_sari_i32(t0, arg1, 31);
- tcg_gen_op5(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i32(INDEX_op_div2_i32, t0, ret, arg1, t0, arg2);
+ tcg_temp_free_i32(t0);
}
-static inline void tcg_gen_divu_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
tcg_gen_movi_i32(t0, 0);
- tcg_gen_op5(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i32(INDEX_op_divu2_i32, ret, t0, arg1, t0, arg2);
+ tcg_temp_free_i32(t0);
}
-static inline void tcg_gen_remu_i32(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
tcg_gen_movi_i32(t0, 0);
- tcg_gen_op5(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i32(INDEX_op_divu2_i32, t0, ret, arg1, t0, arg2);
+ tcg_temp_free_i32(t0);
}
#endif
#if TCG_TARGET_REG_BITS == 32
-static inline void tcg_gen_mov_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- if (GET_TCGV(ret) != GET_TCGV(arg)) {
- tcg_gen_mov_i32(ret, arg);
+ if (!TCGV_EQUAL_I64(ret, arg)) {
+ tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
}
}
-static inline void tcg_gen_movi_i64(TCGv ret, int64_t arg)
+static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
{
- tcg_gen_movi_i32(ret, arg);
+ tcg_gen_movi_i32(TCGV_LOW(ret), arg);
tcg_gen_movi_i32(TCGV_HIGH(ret), arg >> 32);
}
-static inline void tcg_gen_ld8u_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld8u_i32(ret, arg2, offset);
+ tcg_gen_ld8u_i32(TCGV_LOW(ret), arg2, offset);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ld8s_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld8s_i32(ret, arg2, offset);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_ld8s_i32(TCGV_LOW(ret), arg2, offset);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), 31);
}
-static inline void tcg_gen_ld16u_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld16u_i32(ret, arg2, offset);
+ tcg_gen_ld16u_i32(TCGV_LOW(ret), arg2, offset);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ld16s_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld16s_i32(ret, arg2, offset);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_ld16s_i32(TCGV_LOW(ret), arg2, offset);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
}
-static inline void tcg_gen_ld32u_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld_i32(ret, arg2, offset);
+ tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ld32s_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_ld_i32(ret, arg2, offset);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
}
-static inline void tcg_gen_ld_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_ptr arg2,
+ tcg_target_long offset)
{
/* since arg2 and ret have different types, they cannot be the
same temporary */
#ifdef TCG_TARGET_WORDS_BIGENDIAN
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset);
- tcg_gen_ld_i32(ret, arg2, offset + 4);
+ tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset + 4);
#else
- tcg_gen_ld_i32(ret, arg2, offset);
+ tcg_gen_ld_i32(TCGV_LOW(ret), arg2, offset);
tcg_gen_ld_i32(TCGV_HIGH(ret), arg2, offset + 4);
#endif
}
-static inline void tcg_gen_st8_i64(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_st8_i32(arg1, arg2, offset);
+ tcg_gen_st8_i32(TCGV_LOW(arg1), arg2, offset);
}
-static inline void tcg_gen_st16_i64(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_st16_i32(arg1, arg2, offset);
+ tcg_gen_st16_i32(TCGV_LOW(arg1), arg2, offset);
}
-static inline void tcg_gen_st32_i64(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_ptr arg2,
+ tcg_target_long offset)
{
- tcg_gen_st_i32(arg1, arg2, offset);
+ tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
}
-static inline void tcg_gen_st_i64(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_ptr arg2,
+ tcg_target_long offset)
{
#ifdef TCG_TARGET_WORDS_BIGENDIAN
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset);
- tcg_gen_st_i32(arg1, arg2, offset + 4);
+ tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset + 4);
#else
- tcg_gen_st_i32(arg1, arg2, offset);
+ tcg_gen_st_i32(TCGV_LOW(arg1), arg2, offset);
tcg_gen_st_i32(TCGV_HIGH(arg1), arg2, offset + 4);
#endif
}
-static inline void tcg_gen_add_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op6(INDEX_op_add2_i32, ret, TCGV_HIGH(ret),
- arg1, TCGV_HIGH(arg1), arg2, TCGV_HIGH(arg2));
+ tcg_gen_op6_i32(INDEX_op_add2_i32, TCGV_LOW(ret), TCGV_HIGH(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2));
}
-static inline void tcg_gen_addi_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_add_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_gen_op6_i32(INDEX_op_sub2_i32, TCGV_LOW(ret), TCGV_HIGH(ret),
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2));
}
-static inline void tcg_gen_sub_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op6(INDEX_op_sub2_i32, ret, TCGV_HIGH(ret),
- arg1, TCGV_HIGH(arg1), arg2, TCGV_HIGH(arg2));
-}
-
-static inline void tcg_gen_subi_i64(TCGv ret, TCGv arg1, int64_t arg2)
-{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_sub_i64(ret, arg1, t0);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_and_i64(TCGv ret, TCGv arg1, TCGv arg2)
-{
- tcg_gen_and_i32(ret, arg1, arg2);
+ tcg_gen_and_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
tcg_gen_and_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
}
-static inline void tcg_gen_andi_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- tcg_gen_andi_i32(ret, arg1, arg2);
+ tcg_gen_andi_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
tcg_gen_andi_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
}
-static inline void tcg_gen_or_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_or_i32(ret, arg1, arg2);
+ tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
}
-static inline void tcg_gen_ori_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- tcg_gen_ori_i32(ret, arg1, arg2);
+ tcg_gen_ori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
tcg_gen_ori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
}
-static inline void tcg_gen_xor_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_xor_i32(ret, arg1, arg2);
+ tcg_gen_xor_i32(TCGV_LOW(ret), TCGV_LOW(arg1), TCGV_LOW(arg2));
tcg_gen_xor_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), TCGV_HIGH(arg2));
}
-static inline void tcg_gen_xori_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- tcg_gen_xori_i32(ret, arg1, arg2);
+ tcg_gen_xori_i32(TCGV_LOW(ret), TCGV_LOW(arg1), arg2);
tcg_gen_xori_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), arg2 >> 32);
}
/* XXX: use generic code when basic block handling is OK or CPU
specific code (x86) */
-static inline void tcg_gen_shl_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_shl_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_shl_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_shli_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
tcg_gen_shifti_i64(ret, arg1, arg2, 0, 0);
}
-static inline void tcg_gen_shr_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_shr_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_shr_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_shri_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
tcg_gen_shifti_i64(ret, arg1, arg2, 1, 0);
}
-static inline void tcg_gen_sar_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_sar_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_sar_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_sari_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
tcg_gen_shifti_i64(ret, arg1, arg2, 1, 1);
}
-static inline void tcg_gen_brcond_i64(int cond, TCGv arg1, TCGv arg2,
+static inline void tcg_gen_brcond_i64(int cond, TCGv_i64 arg1, TCGv_i64 arg2,
int label_index)
{
- tcg_gen_op6ii(INDEX_op_brcond2_i32,
- arg1, TCGV_HIGH(arg1), arg2, TCGV_HIGH(arg2),
- cond, label_index);
+ tcg_gen_op6ii_i32(INDEX_op_brcond2_i32,
+ TCGV_LOW(arg1), TCGV_HIGH(arg1), TCGV_LOW(arg2),
+ TCGV_HIGH(arg2), cond, label_index);
}
-static inline void tcg_gen_mul_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0, t1;
-
- t0 = tcg_temp_new(TCG_TYPE_I64);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i64 t0;
+ TCGv_i32 t1;
- tcg_gen_op4(INDEX_op_mulu2_i32, t0, TCGV_HIGH(t0), arg1, arg2);
-
- tcg_gen_mul_i32(t1, arg1, TCGV_HIGH(arg2));
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i32();
+
+ tcg_gen_op4_i32(INDEX_op_mulu2_i32, TCGV_LOW(t0), TCGV_HIGH(t0),
+ TCGV_LOW(arg1), TCGV_LOW(arg2));
+
+ tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2));
tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
- tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), arg2);
+ tcg_gen_mul_i32(t1, TCGV_HIGH(arg1), TCGV_LOW(arg2));
tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1);
-
- tcg_gen_mov_i64(ret, t0);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-static inline void tcg_gen_muli_i64(TCGv ret, TCGv arg1, int64_t arg2)
-{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_mul_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_gen_mov_i64(ret, t0);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i32(t1);
}
-static inline void tcg_gen_div_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_div_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_div_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_rem_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_rem_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_rem_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_divu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_divu_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_divu_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_remu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_helper_1_2(tcg_helper_remu_i64, ret, arg1, arg2);
+ tcg_gen_helper64(tcg_helper_remu_i64, ret, arg1, arg2);
}
#else
-static inline void tcg_gen_mov_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- if (GET_TCGV(ret) != GET_TCGV(arg))
- tcg_gen_op2(INDEX_op_mov_i64, ret, arg);
+ if (!TCGV_EQUAL_I64(ret, arg))
+ tcg_gen_op2_i64(INDEX_op_mov_i64, ret, arg);
}
-static inline void tcg_gen_movi_i64(TCGv ret, int64_t arg)
+static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
{
- tcg_gen_op2i(INDEX_op_movi_i64, ret, arg);
+ tcg_gen_op2i_i64(INDEX_op_movi_i64, ret, arg);
}
-static inline void tcg_gen_ld8u_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld8u_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld8u_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld8s_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld8s_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld8s_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld16u_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld16u_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld16u_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld16s_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld16s_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld16s_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld16s_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld32u_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld32u_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld32u_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld32u_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld32s_i64(TCGv ret, TCGv arg2,
+static inline void tcg_gen_ld32s_i64(TCGv_i64 ret, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld32s_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld32s_i64, ret, arg2, offset);
}
-static inline void tcg_gen_ld_i64(TCGv ret, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_ld_i64(TCGv_i64 ret, TCGv_i64 arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_ld_i64, ret, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_ld_i64, ret, arg2, offset);
}
-static inline void tcg_gen_st8_i64(TCGv arg1, TCGv arg2,
+static inline void tcg_gen_st8_i64(TCGv_i64 arg1, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st8_i64, arg1, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_st8_i64, arg1, arg2, offset);
}
-static inline void tcg_gen_st16_i64(TCGv arg1, TCGv arg2,
+static inline void tcg_gen_st16_i64(TCGv_i64 arg1, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st16_i64, arg1, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_st16_i64, arg1, arg2, offset);
}
-static inline void tcg_gen_st32_i64(TCGv arg1, TCGv arg2,
+static inline void tcg_gen_st32_i64(TCGv_i64 arg1, TCGv_i64 arg2,
tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st32_i64, arg1, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_st32_i64, arg1, arg2, offset);
}
-static inline void tcg_gen_st_i64(TCGv arg1, TCGv arg2, tcg_target_long offset)
+static inline void tcg_gen_st_i64(TCGv_i64 arg1, TCGv_i64 arg2, tcg_target_long offset)
{
- tcg_gen_op3i(INDEX_op_st_i64, arg1, arg2, offset);
+ tcg_gen_ldst_op_i64(INDEX_op_st_i64, arg1, arg2, offset);
}
-static inline void tcg_gen_add_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_add_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_add_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_add_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_addi_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_add_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_gen_op3_i64(INDEX_op_sub_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_sub_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_and_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_sub_i64, ret, arg1, arg2);
-}
-
-static inline void tcg_gen_subi_i64(TCGv ret, TCGv arg1, int64_t arg2)
-{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_sub_i64(ret, arg1, t0);
- tcg_temp_free(t0);
-}
-
-static inline void tcg_gen_and_i64(TCGv ret, TCGv arg1, TCGv arg2)
-{
- tcg_gen_op3(INDEX_op_and_i64, ret, arg1, arg2);
+ if (TCGV_EQUAL_I64(arg1, arg2)) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+ tcg_gen_op3_i64(INDEX_op_and_i64, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_andi_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_andi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_and_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_or_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_or_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_or_i64, ret, arg1, arg2);
+ if (TCGV_EQUAL_I64(arg1, arg2)) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+ tcg_gen_op3_i64(INDEX_op_or_i64, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_ori_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_ori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_or_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_xor_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_xor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_xor_i64, ret, arg1, arg2);
+ if (TCGV_EQUAL_I64(arg1, arg2)) {
+ tcg_gen_movi_i64(ret, 0);
+ } else {
+ tcg_gen_op3_i64(INDEX_op_xor_i64, ret, arg1, arg2);
+ }
}
-static inline void tcg_gen_xori_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_xori_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_xor_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_shl_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_shl_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_shl_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_shli_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_shli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_shl_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
}
-static inline void tcg_gen_shr_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_shr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_shr_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_shr_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_shri_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_shri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_shr_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
}
-static inline void tcg_gen_sar_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_sar_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_sar_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_sar_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_sari_i64(TCGv ret, TCGv arg1, int64_t arg2)
+static inline void tcg_gen_sari_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
{
if (arg2 == 0) {
tcg_gen_mov_i64(ret, arg1);
} else {
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_sar_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
}
-static inline void tcg_gen_brcond_i64(int cond, TCGv arg1, TCGv arg2,
+static inline void tcg_gen_brcond_i64(int cond, TCGv_i64 arg1, TCGv_i64 arg2,
int label_index)
{
- tcg_gen_op4ii(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
+ tcg_gen_op4ii_i64(INDEX_op_brcond_i64, arg1, arg2, cond, label_index);
}
-static inline void tcg_gen_mul_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_mul_i64, ret, arg1, arg2);
-}
-
-static inline void tcg_gen_muli_i64(TCGv ret, TCGv arg1, int64_t arg2)
-{
- TCGv t0 = tcg_const_i64(arg2);
- tcg_gen_mul_i64(ret, arg1, t0);
- tcg_temp_free(t0);
+ tcg_gen_op3_i64(INDEX_op_mul_i64, ret, arg1, arg2);
}
#ifdef TCG_TARGET_HAS_div_i64
-static inline void tcg_gen_div_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_div_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_div_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_rem_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_rem_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_divu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_divu_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_divu_i64, ret, arg1, arg2);
}
-static inline void tcg_gen_remu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op3(INDEX_op_remu_i64, ret, arg1, arg2);
+ tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
}
#else
-static inline void tcg_gen_div_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
tcg_gen_sari_i64(t0, arg1, 63);
- tcg_gen_op5(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i64(INDEX_op_div2_i64, ret, t0, arg1, t0, arg2);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_rem_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
tcg_gen_sari_i64(t0, arg1, 63);
- tcg_gen_op5(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i64(INDEX_op_div2_i64, t0, ret, arg1, t0, arg2);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_divu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
tcg_gen_movi_i64(t0, 0);
- tcg_gen_op5(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i64(INDEX_op_divu2_i64, ret, t0, arg1, t0, arg2);
+ tcg_temp_free_i64(t0);
}
-static inline void tcg_gen_remu_i64(TCGv ret, TCGv arg1, TCGv arg2)
+static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
tcg_gen_movi_i64(t0, 0);
- tcg_gen_op5(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
- tcg_temp_free(t0);
+ tcg_gen_op5_i64(INDEX_op_divu2_i64, t0, ret, arg1, t0, arg2);
+ tcg_temp_free_i64(t0);
}
#endif
#endif
-static inline void tcg_gen_brcondi_i64(int cond, TCGv arg1, int64_t arg2,
+static inline void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_add_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+ }
+}
+
+static inline void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2)
+{
+ TCGv_i64 t0 = tcg_const_i64(arg1);
+ tcg_gen_sub_i64(ret, t0, arg2);
+ tcg_temp_free_i64(t0);
+}
+
+static inline void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_sub_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+ }
+}
+static inline void tcg_gen_brcondi_i64(int cond, TCGv_i64 arg1, int64_t arg2,
int label_index)
{
- TCGv t0 = tcg_const_i64(arg2);
+ TCGv_i64 t0 = tcg_const_i64(arg2);
tcg_gen_brcond_i64(cond, arg1, t0, label_index);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
}
+static inline void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
+{
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_mul_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+}
+
+
/***************************************/
/* optional operations */
-static inline void tcg_gen_ext8s_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8s_i32(TCGv_i32 ret, TCGv_i32 arg)
{
#ifdef TCG_TARGET_HAS_ext8s_i32
- tcg_gen_op2(INDEX_op_ext8s_i32, ret, arg);
+ tcg_gen_op2_i32(INDEX_op_ext8s_i32, ret, arg);
#else
tcg_gen_shli_i32(ret, arg, 24);
tcg_gen_sari_i32(ret, ret, 24);
#endif
}
-static inline void tcg_gen_ext16s_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16s_i32(TCGv_i32 ret, TCGv_i32 arg)
{
#ifdef TCG_TARGET_HAS_ext16s_i32
- tcg_gen_op2(INDEX_op_ext16s_i32, ret, arg);
+ tcg_gen_op2_i32(INDEX_op_ext16s_i32, ret, arg);
#else
tcg_gen_shli_i32(ret, arg, 16);
tcg_gen_sari_i32(ret, ret, 16);
@@ -1111,43 +1191,40 @@ static inline void tcg_gen_ext16s_i32(TCGv ret, TCGv arg)
/* These are currently just for convenience.
We assume a target will recognise these automatically . */
-static inline void tcg_gen_ext8u_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8u_i32(TCGv_i32 ret, TCGv_i32 arg)
{
tcg_gen_andi_i32(ret, arg, 0xffu);
}
-static inline void tcg_gen_ext16u_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16u_i32(TCGv_i32 ret, TCGv_i32 arg)
{
tcg_gen_andi_i32(ret, arg, 0xffffu);
}
/* Note: we assume the two high bytes are set to zero */
-static inline void tcg_gen_bswap16_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_bswap16_i32(TCGv_i32 ret, TCGv_i32 arg)
{
#ifdef TCG_TARGET_HAS_bswap16_i32
- tcg_gen_op2(INDEX_op_bswap16_i32, ret, arg);
+ tcg_gen_op2_i32(INDEX_op_bswap16_i32, ret, arg);
#else
- TCGv t0, t1;
- t0 = tcg_temp_new(TCG_TYPE_I32);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_shri_i32(t0, arg, 8);
- tcg_gen_andi_i32(t1, arg, 0x000000ff);
- tcg_gen_shli_i32(t1, t1, 8);
- tcg_gen_or_i32(ret, t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
+ tcg_gen_ext8u_i32(t0, arg);
+ tcg_gen_shli_i32(t0, t0, 8);
+ tcg_gen_shri_i32(ret, arg, 8);
+ tcg_gen_or_i32(ret, ret, t0);
+ tcg_temp_free_i32(t0);
#endif
}
-static inline void tcg_gen_bswap_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
{
-#ifdef TCG_TARGET_HAS_bswap_i32
- tcg_gen_op2(INDEX_op_bswap_i32, ret, arg);
+#ifdef TCG_TARGET_HAS_bswap32_i32
+ tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
#else
- TCGv t0, t1;
- t0 = tcg_temp_new(TCG_TYPE_I32);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0, t1;
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
tcg_gen_shli_i32(t0, arg, 24);
@@ -1161,154 +1238,212 @@ static inline void tcg_gen_bswap_i32(TCGv ret, TCGv arg)
tcg_gen_shri_i32(t1, arg, 24);
tcg_gen_or_i32(ret, t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
#endif
}
#if TCG_TARGET_REG_BITS == 32
-static inline void tcg_gen_ext8s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_ext8s_i32(ret, arg);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_ext8s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
}
-static inline void tcg_gen_ext16s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_ext16s_i32(ret, arg);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_ext16s_i32(TCGV_LOW(ret), TCGV_LOW(arg));
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
}
-static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(ret, arg);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
}
-static inline void tcg_gen_ext8u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_ext8u_i32(ret, arg);
+ tcg_gen_ext8u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ext16u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_ext16u_i32(ret, arg);
+ tcg_gen_ext16u_i32(TCGV_LOW(ret), TCGV_LOW(arg));
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ext32u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(ret, arg);
+ tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg));
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(ret, arg);
+ tcg_gen_mov_i32(ret, TCGV_LOW(arg));
}
-static inline void tcg_gen_extu_i32_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
{
- tcg_gen_mov_i32(ret, arg);
+ tcg_gen_mov_i32(TCGV_LOW(ret), arg);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
-static inline void tcg_gen_ext_i32_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
+{
+ tcg_gen_mov_i32(TCGV_LOW(ret), arg);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
+}
+
+/* Note: we assume the six high bytes are set to zero */
+static inline void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
+{
+ tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
+ tcg_gen_bswap16_i32(TCGV_LOW(ret), TCGV_LOW(arg));
+}
+
+/* Note: we assume the four high bytes are set to zero */
+static inline void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(ret, arg);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg));
+ tcg_gen_bswap32_i32(TCGV_LOW(ret), TCGV_LOW(arg));
}
-static inline void tcg_gen_bswap_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- TCGv t0, t1;
- t0 = tcg_temp_new(TCG_TYPE_I32);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0, t1;
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
- tcg_gen_bswap_i32(t0, arg);
- tcg_gen_bswap_i32(t1, TCGV_HIGH(arg));
- tcg_gen_mov_i32(ret, t1);
+ tcg_gen_bswap32_i32(t0, TCGV_LOW(arg));
+ tcg_gen_bswap32_i32(t1, TCGV_HIGH(arg));
+ tcg_gen_mov_i32(TCGV_LOW(ret), t1);
tcg_gen_mov_i32(TCGV_HIGH(ret), t0);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
}
#else
-static inline void tcg_gen_ext8s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
#ifdef TCG_TARGET_HAS_ext8s_i64
- tcg_gen_op2(INDEX_op_ext8s_i64, ret, arg);
+ tcg_gen_op2_i64(INDEX_op_ext8s_i64, ret, arg);
#else
tcg_gen_shli_i64(ret, arg, 56);
tcg_gen_sari_i64(ret, ret, 56);
#endif
}
-static inline void tcg_gen_ext16s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
#ifdef TCG_TARGET_HAS_ext16s_i64
- tcg_gen_op2(INDEX_op_ext16s_i64, ret, arg);
+ tcg_gen_op2_i64(INDEX_op_ext16s_i64, ret, arg);
#else
tcg_gen_shli_i64(ret, arg, 48);
tcg_gen_sari_i64(ret, ret, 48);
#endif
}
-static inline void tcg_gen_ext32s_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext32s_i64(TCGv_i64 ret, TCGv_i64 arg)
{
#ifdef TCG_TARGET_HAS_ext32s_i64
- tcg_gen_op2(INDEX_op_ext32s_i64, ret, arg);
+ tcg_gen_op2_i64(INDEX_op_ext32s_i64, ret, arg);
#else
tcg_gen_shli_i64(ret, arg, 32);
tcg_gen_sari_i64(ret, ret, 32);
#endif
}
-static inline void tcg_gen_ext8u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext8u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
tcg_gen_andi_i64(ret, arg, 0xffu);
}
-static inline void tcg_gen_ext16u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext16u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
tcg_gen_andi_i64(ret, arg, 0xffffu);
}
-static inline void tcg_gen_ext32u_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
{
tcg_gen_andi_i64(ret, arg, 0xffffffffu);
}
/* Note: we assume the target supports move between 32 and 64 bit
registers. This will probably break MIPS64 targets. */
-static inline void tcg_gen_trunc_i64_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{
- tcg_gen_mov_i32(ret, arg);
+ tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
}
/* Note: we assume the target supports move between 32 and 64 bit
registers */
-static inline void tcg_gen_extu_i32_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
{
- tcg_gen_andi_i64(ret, arg, 0xffffffffu);
+ tcg_gen_andi_i64(ret, MAKE_TCGV_I64(GET_TCGV_I32(arg)), 0xffffffffu);
}
/* Note: we assume the target supports move between 32 and 64 bit
registers */
-static inline void tcg_gen_ext_i32_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_ext_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
{
- tcg_gen_ext32s_i64(ret, arg);
+ tcg_gen_ext32s_i64(ret, MAKE_TCGV_I64(GET_TCGV_I32(arg)));
+}
+
+/* Note: we assume the six high bytes are set to zero */
+static inline void tcg_gen_bswap16_i64(TCGv_i64 ret, TCGv_i64 arg)
+{
+#ifdef TCG_TARGET_HAS_bswap16_i64
+ tcg_gen_op2_i64(INDEX_op_bswap16_i64, ret, arg);
+#else
+ TCGv_i64 t0 = tcg_temp_new_i64();
+
+ tcg_gen_ext8u_i64(t0, arg);
+ tcg_gen_shli_i64(t0, t0, 8);
+ tcg_gen_shri_i64(ret, arg, 8);
+ tcg_gen_or_i64(ret, ret, t0);
+ tcg_temp_free_i64(t0);
+#endif
}
-static inline void tcg_gen_bswap_i64(TCGv ret, TCGv arg)
+/* Note: we assume the four high bytes are set to zero */
+static inline void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
{
-#ifdef TCG_TARGET_HAS_bswap_i64
- tcg_gen_op2(INDEX_op_bswap_i64, ret, arg);
+#ifdef TCG_TARGET_HAS_bswap32_i64
+ tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
#else
- TCGv t0, t1;
- t0 = tcg_temp_new(TCG_TYPE_I32);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i64 t0, t1;
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ tcg_gen_shli_i64(t0, arg, 24);
+ tcg_gen_ext32u_i64(t0, t0);
+
+ tcg_gen_andi_i64(t1, arg, 0x0000ff00);
+ tcg_gen_shli_i64(t1, t1, 8);
+ tcg_gen_or_i64(t0, t0, t1);
+
+ tcg_gen_shri_i64(t1, arg, 8);
+ tcg_gen_andi_i64(t1, t1, 0x0000ff00);
+ tcg_gen_or_i64(t0, t0, t1);
+
+ tcg_gen_shri_i64(t1, arg, 24);
+ tcg_gen_or_i64(ret, t0, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+#endif
+}
+
+static inline void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
+{
+#ifdef TCG_TARGET_HAS_bswap64_i64
+ tcg_gen_op2_i64(INDEX_op_bswap64_i64, ret, arg);
+#else
+ TCGv_i32 t0, t1;
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
tcg_gen_shli_i64(t0, arg, 56);
@@ -1338,62 +1473,310 @@ static inline void tcg_gen_bswap_i64(TCGv ret, TCGv arg)
tcg_gen_shri_i64(t1, arg, 56);
tcg_gen_or_i64(ret, t0, t1);
- tcg_temp_free(t0);
- tcg_temp_free(t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
#endif
}
#endif
-static inline void tcg_gen_neg_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_neg_i32(TCGv_i32 ret, TCGv_i32 arg)
{
#ifdef TCG_TARGET_HAS_neg_i32
- tcg_gen_op2(INDEX_op_neg_i32, ret, arg);
+ tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg);
#else
- TCGv t0 = tcg_const_i32(0);
+ TCGv_i32 t0 = tcg_const_i32(0);
tcg_gen_sub_i32(ret, t0, arg);
- tcg_temp_free(t0);
+ tcg_temp_free_i32(t0);
#endif
}
-static inline void tcg_gen_neg_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_neg_i64(TCGv_i64 ret, TCGv_i64 arg)
{
#ifdef TCG_TARGET_HAS_neg_i64
- tcg_gen_op2(INDEX_op_neg_i64, ret, arg);
+ tcg_gen_op2_i64(INDEX_op_neg_i64, ret, arg);
#else
- TCGv t0 = tcg_const_i64(0);
+ TCGv_i64 t0 = tcg_const_i64(0);
tcg_gen_sub_i64(ret, t0, arg);
- tcg_temp_free(t0);
+ tcg_temp_free_i64(t0);
#endif
}
-static inline void tcg_gen_not_i32(TCGv ret, TCGv arg)
+static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 arg)
{
+#ifdef TCG_TARGET_HAS_not_i32
+ tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg);
+#else
tcg_gen_xori_i32(ret, arg, -1);
+#endif
}
-static inline void tcg_gen_not_i64(TCGv ret, TCGv arg)
+static inline void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
{
+#ifdef TCG_TARGET_HAS_not_i64
+ tcg_gen_op2_i64(INDEX_op_not_i64, ret, arg);
+#else
tcg_gen_xori_i64(ret, arg, -1);
+#endif
}
-static inline void tcg_gen_discard_i32(TCGv arg)
+static inline void tcg_gen_discard_i32(TCGv_i32 arg)
{
- tcg_gen_op1(INDEX_op_discard, arg);
+ tcg_gen_op1_i32(INDEX_op_discard, arg);
}
#if TCG_TARGET_REG_BITS == 32
-static inline void tcg_gen_discard_i64(TCGv arg)
+static inline void tcg_gen_discard_i64(TCGv_i64 arg)
{
- tcg_gen_discard_i32(arg);
+ tcg_gen_discard_i32(TCGV_LOW(arg));
tcg_gen_discard_i32(TCGV_HIGH(arg));
}
#else
-static inline void tcg_gen_discard_i64(TCGv arg)
+static inline void tcg_gen_discard_i64(TCGv_i64 arg)
+{
+ tcg_gen_op1_i64(INDEX_op_discard, arg);
+}
+#endif
+
+static inline void tcg_gen_concat_i32_i64(TCGv_i64 dest, TCGv_i32 low, TCGv_i32 high)
+{
+#if TCG_TARGET_REG_BITS == 32
+ tcg_gen_mov_i32(TCGV_LOW(dest), low);
+ tcg_gen_mov_i32(TCGV_HIGH(dest), high);
+#else
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ /* This extension is only needed for type correctness.
+ We may be able to do better given target specific information. */
+ tcg_gen_extu_i32_i64(tmp, high);
+ tcg_gen_shli_i64(tmp, tmp, 32);
+ tcg_gen_extu_i32_i64(dest, low);
+ tcg_gen_or_i64(dest, dest, tmp);
+ tcg_temp_free_i64(tmp);
+#endif
+}
+
+static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low, TCGv_i64 high)
+{
+#if TCG_TARGET_REG_BITS == 32
+ tcg_gen_concat_i32_i64(dest, TCGV_LOW(low), TCGV_LOW(high));
+#else
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ tcg_gen_ext32u_i64(dest, low);
+ tcg_gen_shli_i64(tmp, high, 32);
+ tcg_gen_or_i64(dest, dest, tmp);
+ tcg_temp_free_i64(tmp);
+#endif
+}
+
+static inline void tcg_gen_andc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
+ tcg_gen_not_i32(t0, arg2);
+ tcg_gen_and_i32(ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+}
+
+static inline void tcg_gen_andc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
+ tcg_gen_not_i64(t0, arg2);
+ tcg_gen_and_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+}
+
+static inline void tcg_gen_eqv_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ tcg_gen_xor_i32(ret, arg1, arg2);
+ tcg_gen_not_i32(ret, ret);
+}
+
+static inline void tcg_gen_eqv_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+ tcg_gen_xor_i64(ret, arg1, arg2);
+ tcg_gen_not_i64(ret, ret);
+}
+
+static inline void tcg_gen_nand_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ tcg_gen_and_i32(ret, arg1, arg2);
+ tcg_gen_not_i32(ret, ret);
+}
+
+static inline void tcg_gen_nand_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+ tcg_gen_and_i64(ret, arg1, arg2);
+ tcg_gen_not_i64(ret, ret);
+}
+
+static inline void tcg_gen_nor_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ tcg_gen_or_i32(ret, arg1, arg2);
+ tcg_gen_not_i32(ret, ret);
+}
+
+static inline void tcg_gen_nor_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+ tcg_gen_or_i64(ret, arg1, arg2);
+ tcg_gen_not_i64(ret, ret);
+}
+
+static inline void tcg_gen_orc_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
+ tcg_gen_not_i32(t0, arg2);
+ tcg_gen_or_i32(ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+}
+
+static inline void tcg_gen_orc_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
+ tcg_gen_not_i64(t0, arg2);
+ tcg_gen_or_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+}
+
+static inline void tcg_gen_rotl_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+#ifdef TCG_TARGET_HAS_rot_i32
+ tcg_gen_op3_i32(INDEX_op_rotl_i32, ret, arg1, arg2);
+#else
+ TCGv_i32 t0, t1;
+
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
+ tcg_gen_shl_i32(t0, arg1, arg2);
+ tcg_gen_subfi_i32(t1, 32, arg2);
+ tcg_gen_shr_i32(t1, arg1, t1);
+ tcg_gen_or_i32(ret, t0, t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
+#endif
+}
+
+static inline void tcg_gen_rotl_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
- tcg_gen_op1(INDEX_op_discard, arg);
+#ifdef TCG_TARGET_HAS_rot_i64
+ tcg_gen_op3_i64(INDEX_op_rotl_i64, ret, arg1, arg2);
+#else
+ TCGv_i64 t0, t1;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ tcg_gen_shl_i64(t0, arg1, arg2);
+ tcg_gen_subfi_i64(t1, 64, arg2);
+ tcg_gen_shr_i64(t1, arg1, t1);
+ tcg_gen_or_i64(ret, t0, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+#endif
}
+
+static inline void tcg_gen_rotli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i32(ret, arg1);
+ } else {
+#ifdef TCG_TARGET_HAS_rot_i32
+ TCGv_i32 t0 = tcg_const_i32(arg2);
+ tcg_gen_rotl_i32(ret, arg1, t0);
+ tcg_temp_free_i32(t0);
+#else
+ TCGv_i32 t0, t1;
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
+ tcg_gen_shli_i32(t0, arg1, arg2);
+ tcg_gen_shri_i32(t1, arg1, 32 - arg2);
+ tcg_gen_or_i32(ret, t0, t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
#endif
+ }
+}
+
+static inline void tcg_gen_rotli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+#ifdef TCG_TARGET_HAS_rot_i64
+ TCGv_i64 t0 = tcg_const_i64(arg2);
+ tcg_gen_rotl_i64(ret, arg1, t0);
+ tcg_temp_free_i64(t0);
+#else
+ TCGv_i64 t0, t1;
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ tcg_gen_shli_i64(t0, arg1, arg2);
+ tcg_gen_shri_i64(t1, arg1, 64 - arg2);
+ tcg_gen_or_i64(ret, t0, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+#endif
+ }
+}
+
+static inline void tcg_gen_rotr_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
+{
+#ifdef TCG_TARGET_HAS_rot_i32
+ tcg_gen_op3_i32(INDEX_op_rotr_i32, ret, arg1, arg2);
+#else
+ TCGv_i32 t0, t1;
+
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
+ tcg_gen_shr_i32(t0, arg1, arg2);
+ tcg_gen_subfi_i32(t1, 32, arg2);
+ tcg_gen_shl_i32(t1, arg1, t1);
+ tcg_gen_or_i32(ret, t0, t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
+#endif
+}
+
+static inline void tcg_gen_rotr_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
+{
+#ifdef TCG_TARGET_HAS_rot_i64
+ tcg_gen_op3_i64(INDEX_op_rotr_i64, ret, arg1, arg2);
+#else
+ TCGv_i64 t0, t1;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ tcg_gen_shl_i64(t0, arg1, arg2);
+ tcg_gen_subfi_i64(t1, 64, arg2);
+ tcg_gen_shl_i64(t1, arg1, t1);
+ tcg_gen_or_i64(ret, t0, t1);
+ tcg_temp_free_i64(t0);
+ tcg_temp_free_i64(t1);
+#endif
+}
+
+static inline void tcg_gen_rotri_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i32(ret, arg1);
+ } else {
+ tcg_gen_rotli_i32(ret, arg1, 32 - arg2);
+ }
+}
+
+static inline void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
+{
+ /* some cases can be optimized here */
+ if (arg2 == 0) {
+ tcg_gen_mov_i64(ret, arg1);
+ } else {
+ tcg_gen_rotli_i64(ret, arg1, 64 - arg2);
+ }
+}
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
@@ -1402,6 +1785,30 @@ static inline void tcg_gen_discard_i64(TCGv arg)
#error must include QEMU headers
#endif
+#if TARGET_LONG_BITS == 32
+#define TCGv TCGv_i32
+#define tcg_temp_new() tcg_temp_new_i32()
+#define tcg_global_reg_new tcg_global_reg_new_i32
+#define tcg_global_mem_new tcg_global_mem_new_i32
+#define tcg_temp_local_new() tcg_temp_local_new_i32()
+#define tcg_temp_free tcg_temp_free_i32
+#define tcg_gen_qemu_ldst_op tcg_gen_op3i_i32
+#define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i32
+#define TCGV_UNUSED(x) TCGV_UNUSED_I32(x)
+#define TCGV_EQUAL(a, b) TCGV_EQUAL_I32(a, b)
+#else
+#define TCGv TCGv_i64
+#define tcg_temp_new() tcg_temp_new_i64()
+#define tcg_global_reg_new tcg_global_reg_new_i64
+#define tcg_global_mem_new tcg_global_mem_new_i64
+#define tcg_temp_local_new() tcg_temp_local_new_i64()
+#define tcg_temp_free tcg_temp_free_i64
+#define tcg_gen_qemu_ldst_op tcg_gen_op3i_i64
+#define tcg_gen_qemu_ldst_op_i64 tcg_gen_qemu_ldst_op_i64_i64
+#define TCGV_UNUSED(x) TCGV_UNUSED_I64(x)
+#define TCGV_EQUAL(a, b) TCGV_EQUAL_I64(a, b)
+#endif
+
/* debug info: write the PC of the corresponding QEMU CPU instruction */
static inline void tcg_gen_debug_insn_start(uint64_t pc)
{
@@ -1428,9 +1835,10 @@ static inline void tcg_gen_goto_tb(int idx)
static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld8u, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld8u, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld8u, ret, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld8u, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
#endif
}
@@ -1438,19 +1846,21 @@ static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld8s(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld8s, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld8s, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld8s, ret, addr, TCGV_HIGH(addr), mem_index);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld8s, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
#endif
}
static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld16u, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld16u, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld16u, ret, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld16u, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
#endif
}
@@ -1458,19 +1868,21 @@ static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld16s, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld16s, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld16s, ret, addr, TCGV_HIGH(addr), mem_index);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld16s, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
#endif
}
static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld32u, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld32u, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld32u, ret, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld32u, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
#endif
}
@@ -1478,57 +1890,62 @@ static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_ld32u, ret, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_ld32u, ret, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_ld32u, ret, addr, TCGV_HIGH(addr), mem_index);
- tcg_gen_sari_i32(TCGV_HIGH(ret), ret, 31);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld32u, TCGV_LOW(ret), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
+ tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
#endif
}
-static inline void tcg_gen_qemu_ld64(TCGv ret, TCGv addr, int mem_index)
+static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op4i(INDEX_op_qemu_ld64, ret, TCGV_HIGH(ret), addr, mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_ld64, TCGV_LOW(ret), TCGV_HIGH(ret), addr, mem_index);
#else
- tcg_gen_op5i(INDEX_op_qemu_ld64, ret, TCGV_HIGH(ret),
- addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op5i_i32(INDEX_op_qemu_ld64, TCGV_LOW(ret), TCGV_HIGH(ret),
+ TCGV_LOW(addr), TCGV_HIGH(addr), mem_index);
#endif
}
static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_st8, arg, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_st8, arg, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_st8, arg, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_st8, TCGV_LOW(arg), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
#endif
}
static inline void tcg_gen_qemu_st16(TCGv arg, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_st16, arg, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_st16, arg, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_st16, arg, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_st16, TCGV_LOW(arg), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
#endif
}
static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op3i(INDEX_op_qemu_st32, arg, addr, mem_index);
+ tcg_gen_op3i_i32(INDEX_op_qemu_st32, arg, addr, mem_index);
#else
- tcg_gen_op4i(INDEX_op_qemu_st32, arg, addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_st32, TCGV_LOW(arg), TCGV_LOW(addr),
+ TCGV_HIGH(addr), mem_index);
#endif
}
-static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
+static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
{
#if TARGET_LONG_BITS == 32
- tcg_gen_op4i(INDEX_op_qemu_st64, arg, TCGV_HIGH(arg), addr, mem_index);
+ tcg_gen_op4i_i32(INDEX_op_qemu_st64, TCGV_LOW(arg), TCGV_HIGH(arg), addr,
+ mem_index);
#else
- tcg_gen_op5i(INDEX_op_qemu_st64, arg, TCGV_HIGH(arg),
- addr, TCGV_HIGH(addr), mem_index);
+ tcg_gen_op5i_i32(INDEX_op_qemu_st64, TCGV_LOW(arg), TCGV_HIGH(arg),
+ TCGV_LOW(addr), TCGV_HIGH(addr), mem_index);
#endif
}
@@ -1539,57 +1956,57 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld8u(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld8u, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld8u, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_ld8s(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld8s, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld8s, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_ld16u(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld16u, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld16u, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld16s, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld16s, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld32u, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32u, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld32s, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32s, ret, addr, mem_index);
}
-static inline void tcg_gen_qemu_ld64(TCGv ret, TCGv addr, int mem_index)
+static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_ld64, ret, addr, mem_index);
+ tcg_gen_qemu_ldst_op_i64(INDEX_op_qemu_ld64, ret, addr, mem_index);
}
static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_st8, arg, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_st8, arg, addr, mem_index);
}
static inline void tcg_gen_qemu_st16(TCGv arg, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_st16, arg, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_st16, arg, addr, mem_index);
}
static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_st32, arg, addr, mem_index);
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_st32, arg, addr, mem_index);
}
-static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
+static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
{
- tcg_gen_op3i(INDEX_op_qemu_st64, arg, addr, mem_index);
+ tcg_gen_qemu_ldst_op_i64(INDEX_op_qemu_st64, arg, addr, mem_index);
}
#define tcg_gen_ld_ptr tcg_gen_ld_i64
@@ -1616,6 +2033,7 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_addi_tl tcg_gen_addi_i64
#define tcg_gen_sub_tl tcg_gen_sub_i64
#define tcg_gen_neg_tl tcg_gen_neg_i64
+#define tcg_gen_subfi_tl tcg_gen_subfi_i64
#define tcg_gen_subi_tl tcg_gen_subi_i64
#define tcg_gen_and_tl tcg_gen_and_i64
#define tcg_gen_andi_tl tcg_gen_andi_i64
@@ -1634,6 +2052,10 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_brcondi_tl tcg_gen_brcondi_i64
#define tcg_gen_mul_tl tcg_gen_mul_i64
#define tcg_gen_muli_tl tcg_gen_muli_i64
+#define tcg_gen_div_tl tcg_gen_div_i64
+#define tcg_gen_rem_tl tcg_gen_rem_i64
+#define tcg_gen_divu_tl tcg_gen_divu_i64
+#define tcg_gen_remu_tl tcg_gen_remu_i64
#define tcg_gen_discard_tl tcg_gen_discard_i64
#define tcg_gen_trunc_tl_i32 tcg_gen_trunc_i64_i32
#define tcg_gen_trunc_i64_tl tcg_gen_mov_i64
@@ -1647,7 +2069,21 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_ext16s_tl tcg_gen_ext16s_i64
#define tcg_gen_ext32u_tl tcg_gen_ext32u_i64
#define tcg_gen_ext32s_tl tcg_gen_ext32s_i64
+#define tcg_gen_bswap16_tl tcg_gen_bswap16_i64
+#define tcg_gen_bswap32_tl tcg_gen_bswap32_i64
+#define tcg_gen_bswap64_tl tcg_gen_bswap64_i64
+#define tcg_gen_concat_tl_i64 tcg_gen_concat32_i64
+#define tcg_gen_andc_tl tcg_gen_andc_i64
+#define tcg_gen_eqv_tl tcg_gen_eqv_i64
+#define tcg_gen_nand_tl tcg_gen_nand_i64
+#define tcg_gen_nor_tl tcg_gen_nor_i64
+#define tcg_gen_orc_tl tcg_gen_orc_i64
+#define tcg_gen_rotl_tl tcg_gen_rotl_i64
+#define tcg_gen_rotli_tl tcg_gen_rotli_i64
+#define tcg_gen_rotr_tl tcg_gen_rotr_i64
+#define tcg_gen_rotri_tl tcg_gen_rotri_i64
#define tcg_const_tl tcg_const_i64
+#define tcg_const_local_tl tcg_const_local_i64
#else
#define TCG_TYPE_TL TCG_TYPE_I32
#define tcg_gen_movi_tl tcg_gen_movi_i32
@@ -1667,6 +2103,7 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_addi_tl tcg_gen_addi_i32
#define tcg_gen_sub_tl tcg_gen_sub_i32
#define tcg_gen_neg_tl tcg_gen_neg_i32
+#define tcg_gen_subfi_tl tcg_gen_subfi_i32
#define tcg_gen_subi_tl tcg_gen_subi_i32
#define tcg_gen_and_tl tcg_gen_and_i32
#define tcg_gen_andi_tl tcg_gen_andi_i32
@@ -1685,6 +2122,10 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_brcondi_tl tcg_gen_brcondi_i32
#define tcg_gen_mul_tl tcg_gen_mul_i32
#define tcg_gen_muli_tl tcg_gen_muli_i32
+#define tcg_gen_div_tl tcg_gen_div_i32
+#define tcg_gen_rem_tl tcg_gen_rem_i32
+#define tcg_gen_divu_tl tcg_gen_divu_i32
+#define tcg_gen_remu_tl tcg_gen_remu_i32
#define tcg_gen_discard_tl tcg_gen_discard_i32
#define tcg_gen_trunc_tl_i32 tcg_gen_mov_i32
#define tcg_gen_trunc_i64_tl tcg_gen_trunc_i64_i32
@@ -1698,7 +2139,20 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_ext16s_tl tcg_gen_ext16s_i32
#define tcg_gen_ext32u_tl tcg_gen_mov_i32
#define tcg_gen_ext32s_tl tcg_gen_mov_i32
+#define tcg_gen_bswap16_tl tcg_gen_bswap16_i32
+#define tcg_gen_bswap32_tl tcg_gen_bswap32_i32
+#define tcg_gen_concat_tl_i64 tcg_gen_concat_i32_i64
+#define tcg_gen_andc_tl tcg_gen_andc_i32
+#define tcg_gen_eqv_tl tcg_gen_eqv_i32
+#define tcg_gen_nand_tl tcg_gen_nand_i32
+#define tcg_gen_nor_tl tcg_gen_nor_i32
+#define tcg_gen_orc_tl tcg_gen_orc_i32
+#define tcg_gen_rotl_tl tcg_gen_rotl_i32
+#define tcg_gen_rotli_tl tcg_gen_rotli_i32
+#define tcg_gen_rotr_tl tcg_gen_rotr_i32
+#define tcg_gen_rotri_tl tcg_gen_rotri_i32
#define tcg_const_tl tcg_const_i32
+#define tcg_const_local_tl tcg_const_local_i32
#endif
#if TCG_TARGET_REG_BITS == 32
@@ -1710,4 +2164,3 @@ static inline void tcg_gen_qemu_st64(TCGv arg, TCGv addr, int mem_index)
#define tcg_gen_addi_ptr tcg_gen_addi_i64
#define tcg_gen_ext_i32_ptr tcg_gen_ext_i32_i64
#endif /* TCG_TARGET_REG_BITS != 32 */
-
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 31ae550..3a095fc 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -21,10 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifdef CONFIG_DYNGEN_OP
-#include "dyngen-opc.h"
-#endif
-
#ifndef DEF2
#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs, 0)
#endif
@@ -71,10 +67,14 @@ DEF2(divu2_i32, 2, 3, 0, 0)
DEF2(and_i32, 1, 2, 0, 0)
DEF2(or_i32, 1, 2, 0, 0)
DEF2(xor_i32, 1, 2, 0, 0)
-/* shifts */
+/* shifts/rotates */
DEF2(shl_i32, 1, 2, 0, 0)
DEF2(shr_i32, 1, 2, 0, 0)
DEF2(sar_i32, 1, 2, 0, 0)
+#ifdef TCG_TARGET_HAS_rot_i32
+DEF2(rotl_i32, 1, 2, 0, 0)
+DEF2(rotr_i32, 1, 2, 0, 0)
+#endif
DEF2(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#if TCG_TARGET_REG_BITS == 32
@@ -89,8 +89,17 @@ DEF2(ext8s_i32, 1, 1, 0, 0)
#ifdef TCG_TARGET_HAS_ext16s_i32
DEF2(ext16s_i32, 1, 1, 0, 0)
#endif
-#ifdef TCG_TARGET_HAS_bswap_i32
-DEF2(bswap_i32, 1, 1, 0, 0)
+#ifdef TCG_TARGET_HAS_bswap16_i32
+DEF2(bswap16_i32, 1, 1, 0, 0)
+#endif
+#ifdef TCG_TARGET_HAS_bswap32_i32
+DEF2(bswap32_i32, 1, 1, 0, 0)
+#endif
+#ifdef TCG_TARGET_HAS_not_i32
+DEF2(not_i32, 1, 1, 0, 0)
+#endif
+#ifdef TCG_TARGET_HAS_neg_i32
+DEF2(neg_i32, 1, 1, 0, 0)
#endif
#if TCG_TARGET_REG_BITS == 64
@@ -124,10 +133,14 @@ DEF2(divu2_i64, 2, 3, 0, 0)
DEF2(and_i64, 1, 2, 0, 0)
DEF2(or_i64, 1, 2, 0, 0)
DEF2(xor_i64, 1, 2, 0, 0)
-/* shifts */
+/* shifts/rotates */
DEF2(shl_i64, 1, 2, 0, 0)
DEF2(shr_i64, 1, 2, 0, 0)
DEF2(sar_i64, 1, 2, 0, 0)
+#ifdef TCG_TARGET_HAS_rot_i64
+DEF2(rotl_i64, 1, 2, 0, 0)
+DEF2(rotr_i64, 1, 2, 0, 0)
+#endif
DEF2(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#ifdef TCG_TARGET_HAS_ext8s_i64
@@ -139,16 +152,22 @@ DEF2(ext16s_i64, 1, 1, 0, 0)
#ifdef TCG_TARGET_HAS_ext32s_i64
DEF2(ext32s_i64, 1, 1, 0, 0)
#endif
-#ifdef TCG_TARGET_HAS_bswap_i64
-DEF2(bswap_i64, 1, 1, 0, 0)
+#ifdef TCG_TARGET_HAS_bswap16_i64
+DEF2(bswap16_i64, 1, 1, 0, 0)
#endif
+#ifdef TCG_TARGET_HAS_bswap32_i64
+DEF2(bswap32_i64, 1, 1, 0, 0)
#endif
-#ifdef TCG_TARGET_HAS_neg_i32
-DEF2(neg_i32, 1, 1, 0, 0)
+#ifdef TCG_TARGET_HAS_bswap64_i64
+DEF2(bswap64_i64, 1, 1, 0, 0)
+#endif
+#ifdef TCG_TARGET_HAS_not_i64
+DEF2(not_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_neg_i64
DEF2(neg_i64, 1, 1, 0, 0)
#endif
+#endif
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
diff --git a/tcg/tcg-runtime.c b/tcg/tcg-runtime.c
index 575da43..1d77c37 100644
--- a/tcg/tcg-runtime.c
+++ b/tcg/tcg-runtime.c
@@ -29,6 +29,7 @@
#include "config.h"
#include "osdep.h"
+#include "cpu.h" // For TARGET_LONG_BITS
#include "tcg.h"
int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2)
@@ -65,4 +66,3 @@ uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2)
{
return arg1 % arg2;
}
-
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1b7bf5c..299bff6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -22,13 +22,16 @@
* THE SOFTWARE.
*/
-/* define it to suppress various consistency checks (faster) */
-#define NDEBUG
-
/* define it to use liveness analysis (better code) */
#define USE_LIVENESS_ANALYSIS
-#include <assert.h>
+#include "config.h"
+
+#ifndef DEBUG_TCG
+/* define it to suppress various consistency checks (faster) */
+#define NDEBUG
+#endif
+
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,9 +40,12 @@
#ifdef _WIN32
#include <malloc.h>
#endif
+#ifdef _AIX
+#include <alloca.h>
+#endif
-#include "config.h"
#include "qemu-common.h"
+#include "cache-utils.h"
/* Note: the long term plan is to reduce the dependancies on the QEMU
CPU definitions. Currently they are used for qemu_ld/st
@@ -55,7 +61,7 @@
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
-TCGOpDef tcg_op_defs[] = {
+static TCGOpDef tcg_op_defs[] = {
#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
#define DEF2(s, iargs, oargs, cargs, flags) { #s, iargs, oargs, cargs, iargs + oargs + cargs, flags, 0 },
#include "tcg-opc.h"
@@ -63,8 +69,8 @@ TCGOpDef tcg_op_defs[] = {
#undef DEF2
};
-TCGRegSet tcg_target_available_regs[2];
-TCGRegSet tcg_target_call_clobber_regs;
+static TCGRegSet tcg_target_available_regs[2];
+static TCGRegSet tcg_target_call_clobber_regs;
/* XXX: move that inside the context */
uint16_t *gen_opc_ptr;
@@ -267,7 +273,8 @@ static inline void tcg_temp_alloc(TCGContext *s, int n)
tcg_abort();
}
-TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
+static inline int tcg_global_reg_new_internal(TCGType type, int reg,
+ const char *name)
{
TCGContext *s = &tcg_ctx;
TCGTemp *ts;
@@ -289,48 +296,28 @@ TCGv tcg_global_reg_new(TCGType type, int reg, const char *name)
ts->name = name;
s->nb_globals++;
tcg_regset_set_reg(s->reserved_regs, reg);
- return MAKE_TCGV(idx);
+ return idx;
}
-#if TCG_TARGET_REG_BITS == 32
-/* temporary hack to avoid register shortage for tcg_qemu_st64() */
-TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
- const char *name)
+TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name)
{
- TCGContext *s = &tcg_ctx;
- TCGTemp *ts;
int idx;
- char buf[64];
- if (type != TCG_TYPE_I64)
- tcg_abort();
- idx = s->nb_globals;
- tcg_temp_alloc(s, s->nb_globals + 2);
- ts = &s->temps[s->nb_globals];
- ts->base_type = type;
- ts->type = TCG_TYPE_I32;
- ts->fixed_reg = 1;
- ts->reg = reg1;
- pstrcpy(buf, sizeof(buf), name);
- pstrcat(buf, sizeof(buf), "_0");
- ts->name = strdup(buf);
+ idx = tcg_global_reg_new_internal(TCG_TYPE_I32, reg, name);
+ return MAKE_TCGV_I32(idx);
+}
- ts++;
- ts->base_type = type;
- ts->type = TCG_TYPE_I32;
- ts->fixed_reg = 1;
- ts->reg = reg2;
- pstrcpy(buf, sizeof(buf), name);
- pstrcat(buf, sizeof(buf), "_1");
- ts->name = strdup(buf);
+TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name)
+{
+ int idx;
- s->nb_globals += 2;
- return MAKE_TCGV(idx);
+ idx = tcg_global_reg_new_internal(TCG_TYPE_I64, reg, name);
+ return MAKE_TCGV_I64(idx);
}
-#endif
-TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
- const char *name)
+static inline int tcg_global_mem_new_internal(TCGType type, int reg,
+ tcg_target_long offset,
+ const char *name)
{
TCGContext *s = &tcg_ctx;
TCGTemp *ts;
@@ -386,10 +373,28 @@ TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
ts->name = name;
s->nb_globals++;
}
- return MAKE_TCGV(idx);
+ return idx;
+}
+
+TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
+ const char *name)
+{
+ int idx;
+
+ idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name);
+ return MAKE_TCGV_I32(idx);
+}
+
+TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
+ const char *name)
+{
+ int idx;
+
+ idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name);
+ return MAKE_TCGV_I64(idx);
}
-TCGv tcg_temp_new_internal(TCGType type, int temp_local)
+static inline int tcg_temp_new_internal(TCGType type, int temp_local)
{
TCGContext *s = &tcg_ctx;
TCGTemp *ts;
@@ -437,14 +442,29 @@ TCGv tcg_temp_new_internal(TCGType type, int temp_local)
s->nb_temps++;
}
}
- return MAKE_TCGV(idx);
+ return idx;
+}
+
+TCGv_i32 tcg_temp_new_internal_i32(int temp_local)
+{
+ int idx;
+
+ idx = tcg_temp_new_internal(TCG_TYPE_I32, temp_local);
+ return MAKE_TCGV_I32(idx);
+}
+
+TCGv_i64 tcg_temp_new_internal_i64(int temp_local)
+{
+ int idx;
+
+ idx = tcg_temp_new_internal(TCG_TYPE_I64, temp_local);
+ return MAKE_TCGV_I64(idx);
}
-void tcg_temp_free(TCGv arg)
+static inline void tcg_temp_free_internal(int idx)
{
TCGContext *s = &tcg_ctx;
TCGTemp *ts;
- int idx = GET_TCGV(arg);
int k;
assert(idx >= s->nb_globals && idx < s->nb_temps);
@@ -458,19 +478,44 @@ void tcg_temp_free(TCGv arg)
s->first_free_temp[k] = idx;
}
+void tcg_temp_free_i32(TCGv_i32 arg)
+{
+ tcg_temp_free_internal(GET_TCGV_I32(arg));
+}
+
+void tcg_temp_free_i64(TCGv_i64 arg)
+{
+ tcg_temp_free_internal(GET_TCGV_I64(arg));
+}
+
+TCGv_i32 tcg_const_i32(int32_t val)
+{
+ TCGv_i32 t0;
+ t0 = tcg_temp_new_i32();
+ tcg_gen_movi_i32(t0, val);
+ return t0;
+}
+
+TCGv_i64 tcg_const_i64(int64_t val)
+{
+ TCGv_i64 t0;
+ t0 = tcg_temp_new_i64();
+ tcg_gen_movi_i64(t0, val);
+ return t0;
+}
-TCGv tcg_const_i32(int32_t val)
+TCGv_i32 tcg_const_local_i32(int32_t val)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I32);
+ TCGv_i32 t0;
+ t0 = tcg_temp_local_new_i32();
tcg_gen_movi_i32(t0, val);
return t0;
}
-TCGv tcg_const_i64(int64_t val)
+TCGv_i64 tcg_const_local_i64(int64_t val)
{
- TCGv t0;
- t0 = tcg_temp_new(TCG_TYPE_I64);
+ TCGv_i64 t0;
+ t0 = tcg_temp_local_new_i64();
tcg_gen_movi_i64(t0, val);
return t0;
}
@@ -494,150 +539,129 @@ void tcg_register_helper(void *func, const char *name)
s->nb_helpers++;
}
-static inline TCGType tcg_get_base_type(TCGContext *s, TCGv arg)
-{
- return s->temps[GET_TCGV(arg)].base_type;
-}
-
-static void tcg_gen_call_internal(TCGContext *s, TCGv func,
- unsigned int flags,
- unsigned int nb_rets, const TCGv *rets,
- unsigned int nb_params, const TCGv *params)
-{
- int i;
- *gen_opc_ptr++ = INDEX_op_call;
- *gen_opparam_ptr++ = (nb_rets << 16) | (nb_params + 1);
- for(i = 0; i < nb_rets; i++) {
- *gen_opparam_ptr++ = GET_TCGV(rets[i]);
- }
- for(i = 0; i < nb_params; i++) {
- *gen_opparam_ptr++ = GET_TCGV(params[i]);
- }
- *gen_opparam_ptr++ = GET_TCGV(func);
-
- *gen_opparam_ptr++ = flags;
- /* total parameters, needed to go backward in the instruction stream */
- *gen_opparam_ptr++ = 1 + nb_rets + nb_params + 3;
-}
-
-
-#if TCG_TARGET_REG_BITS < 64
/* Note: we convert the 64 bit args to 32 bit and do some alignment
and endian swap. Maybe it would be better to do the alignment
and endian swap in tcg_reg_alloc_call(). */
-void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
- unsigned int nb_rets, const TCGv *rets,
- unsigned int nb_params, const TCGv *args1)
+void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
+ int sizemask, TCGArg ret, int nargs, TCGArg *args)
{
- TCGv ret, *args2, rets_2[2], arg;
- int j, i, call_type;
-
- if (nb_rets == 1) {
- ret = rets[0];
- if (tcg_get_base_type(s, ret) == TCG_TYPE_I64) {
- nb_rets = 2;
+ int call_type;
+ int i;
+ int real_args;
+ int nb_rets;
+ TCGArg *nparam;
+ *gen_opc_ptr++ = INDEX_op_call;
+ nparam = gen_opparam_ptr++;
+ call_type = (flags & TCG_CALL_TYPE_MASK);
+ if (ret != TCG_CALL_DUMMY_ARG) {
+#if TCG_TARGET_REG_BITS < 64
+ if (sizemask & 1) {
#ifdef TCG_TARGET_WORDS_BIGENDIAN
- rets_2[0] = TCGV_HIGH(ret);
- rets_2[1] = ret;
+ *gen_opparam_ptr++ = ret + 1;
+ *gen_opparam_ptr++ = ret;
#else
- rets_2[0] = ret;
- rets_2[1] = TCGV_HIGH(ret);
+ *gen_opparam_ptr++ = ret;
+ *gen_opparam_ptr++ = ret + 1;
#endif
- rets = rets_2;
+ nb_rets = 2;
+ } else
+#endif
+ {
+ *gen_opparam_ptr++ = ret;
+ nb_rets = 1;
}
+ } else {
+ nb_rets = 0;
}
- args2 = alloca((nb_params * 3) * sizeof(TCGv));
- j = 0;
- call_type = (flags & TCG_CALL_TYPE_MASK);
- for(i = 0; i < nb_params; i++) {
- arg = args1[i];
- if (tcg_get_base_type(s, arg) == TCG_TYPE_I64) {
+ real_args = 0;
+ for (i = 0; i < nargs; i++) {
+#if TCG_TARGET_REG_BITS < 64
+ if (sizemask & (2 << i)) {
#ifdef TCG_TARGET_I386
/* REGPARM case: if the third parameter is 64 bit, it is
allocated on the stack */
- if (j == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
+ if (i == 2 && call_type == TCG_CALL_TYPE_REGPARM) {
call_type = TCG_CALL_TYPE_REGPARM_2;
flags = (flags & ~TCG_CALL_TYPE_MASK) | call_type;
}
- args2[j++] = arg;
- args2[j++] = TCGV_HIGH(arg);
-#else
+#endif
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
/* some targets want aligned 64 bit args */
- if (j & 1) {
- args2[j++] = TCG_CALL_DUMMY_ARG;
+ if (real_args & 1) {
+ *gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG;
+ real_args++;
}
#endif
#ifdef TCG_TARGET_WORDS_BIGENDIAN
- args2[j++] = TCGV_HIGH(arg);
- args2[j++] = arg;
+ *gen_opparam_ptr++ = args[i] + 1;
+ *gen_opparam_ptr++ = args[i];
#else
- args2[j++] = arg;
- args2[j++] = TCGV_HIGH(arg);
+ *gen_opparam_ptr++ = args[i];
+ *gen_opparam_ptr++ = args[i] + 1;
#endif
+ real_args += 2;
+ } else
#endif
- } else {
- args2[j++] = arg;
+ {
+ *gen_opparam_ptr++ = args[i];
+ real_args++;
}
}
- tcg_gen_call_internal(s, func, flags,
- nb_rets, rets, j, args2);
-}
-#else
-void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
- unsigned int nb_rets, const TCGv *rets,
- unsigned int nb_params, const TCGv *args1)
-{
- tcg_gen_call_internal(s, func, flags,
- nb_rets, rets, nb_params, args1);
+ *gen_opparam_ptr++ = GET_TCGV_PTR(func);
+
+ *gen_opparam_ptr++ = flags;
+
+ *nparam = (nb_rets << 16) | (real_args + 1);
+
+ /* total parameters, needed to go backward in the instruction stream */
+ *gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
}
-#endif
#if TCG_TARGET_REG_BITS == 32
-void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
+void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
int c, int right, int arith)
{
if (c == 0) {
- tcg_gen_mov_i32(ret, arg1);
+ tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
} else if (c >= 32) {
c -= 32;
if (right) {
if (arith) {
- tcg_gen_sari_i32(ret, TCGV_HIGH(arg1), c);
+ tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
} else {
- tcg_gen_shri_i32(ret, TCGV_HIGH(arg1), c);
+ tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
} else {
- tcg_gen_shli_i32(TCGV_HIGH(ret), arg1, c);
- tcg_gen_movi_i32(ret, 0);
+ tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
+ tcg_gen_movi_i32(TCGV_LOW(ret), 0);
}
} else {
- TCGv t0, t1;
+ TCGv_i32 t0, t1;
- t0 = tcg_temp_new(TCG_TYPE_I32);
- t1 = tcg_temp_new(TCG_TYPE_I32);
+ t0 = tcg_temp_new_i32();
+ t1 = tcg_temp_new_i32();
if (right) {
tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
if (arith)
tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
- else
+ else
tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
- tcg_gen_shri_i32(ret, arg1, c);
- tcg_gen_or_i32(ret, ret, t0);
+ tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
+ tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
} else {
- tcg_gen_shri_i32(t0, arg1, 32 - c);
+ tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
/* Note: ret can be the same as arg1, so we use t1 */
- tcg_gen_shli_i32(t1, arg1, c);
+ tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
- tcg_gen_mov_i32(ret, t1);
+ tcg_gen_mov_i32(TCGV_LOW(ret), t1);
}
- tcg_temp_free(t0);
- tcg_temp_free(t1);
+ tcg_temp_free_i32(t0);
+ tcg_temp_free_i32(t1);
}
}
#endif
@@ -682,9 +706,14 @@ static char *tcg_get_arg_str_idx(TCGContext *s, char *buf, int buf_size,
return buf;
}
-char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg)
+char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg)
+{
+ return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I32(arg));
+}
+
+char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg)
{
- return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV(arg));
+ return tcg_get_arg_str_idx(s, buf, buf_size, GET_TCGV_I64(arg));
}
static int helper_cmp(const void *p1, const void *p2)
@@ -822,7 +851,7 @@ void tcg_dump_ops(TCGContext *s, FILE *outfile)
val = args[1];
th = tcg_find_helper(s, val);
if (th) {
- fprintf(outfile, th->name);
+ fprintf(outfile, "%s", th->name);
} else {
if (c == INDEX_op_movi_i32)
fprintf(outfile, "0x%x", (uint32_t)val);
@@ -1095,9 +1124,11 @@ static void tcg_liveness_analysis(TCGContext *s)
dead_temps[arg] = 1;
}
- /* globals are live (they may be used by the call) */
- memset(dead_temps, 0, s->nb_globals);
-
+ if (!(call_flags & TCG_CALL_CONST)) {
+ /* globals are live (they may be used by the call) */
+ memset(dead_temps, 0, s->nb_globals);
+ }
+
/* input args are live */
dead_iargs = 0;
for(i = 0; i < nb_iargs; i++) {
@@ -1135,57 +1166,50 @@ static void tcg_liveness_analysis(TCGContext *s)
break;
/* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
default:
- if (op > INDEX_op_end) {
- args -= def->nb_args;
- nb_iargs = def->nb_iargs;
- nb_oargs = def->nb_oargs;
+ args -= def->nb_args;
+ nb_iargs = def->nb_iargs;
+ nb_oargs = def->nb_oargs;
- /* Test if the operation can be removed because all
- its outputs are dead. We assume that nb_oargs == 0
- implies side effects */
- if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
- for(i = 0; i < nb_oargs; i++) {
- arg = args[i];
- if (!dead_temps[arg])
- goto do_not_remove;
- }
- tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
+ /* Test if the operation can be removed because all
+ its outputs are dead. We assume that nb_oargs == 0
+ implies side effects */
+ if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
+ for(i = 0; i < nb_oargs; i++) {
+ arg = args[i];
+ if (!dead_temps[arg])
+ goto do_not_remove;
+ }
+ tcg_set_nop(s, gen_opc_buf + op_index, args, def->nb_args);
#ifdef CONFIG_PROFILER
- s->del_op_count++;
+ s->del_op_count++;
#endif
- } else {
- do_not_remove:
+ } else {
+ do_not_remove:
- /* output args are dead */
- for(i = 0; i < nb_oargs; i++) {
- arg = args[i];
- dead_temps[arg] = 1;
- }
-
- /* if end of basic block, update */
- if (def->flags & TCG_OPF_BB_END) {
- tcg_la_bb_end(s, dead_temps);
- } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
- /* globals are live */
- memset(dead_temps, 0, s->nb_globals);
- }
-
- /* input args are live */
- dead_iargs = 0;
- for(i = 0; i < nb_iargs; i++) {
- arg = args[i + nb_oargs];
- if (dead_temps[arg]) {
- dead_iargs |= (1 << i);
- }
- dead_temps[arg] = 0;
+ /* output args are dead */
+ for(i = 0; i < nb_oargs; i++) {
+ arg = args[i];
+ dead_temps[arg] = 1;
+ }
+
+ /* if end of basic block, update */
+ if (def->flags & TCG_OPF_BB_END) {
+ tcg_la_bb_end(s, dead_temps);
+ } else if (def->flags & TCG_OPF_CALL_CLOBBER) {
+ /* globals are live */
+ memset(dead_temps, 0, s->nb_globals);
+ }
+
+ /* input args are live */
+ dead_iargs = 0;
+ for(i = 0; i < nb_iargs; i++) {
+ arg = args[i + nb_oargs];
+ if (dead_temps[arg]) {
+ dead_iargs |= (1 << i);
}
- s->op_dead_iargs[op_index] = dead_iargs;
+ dead_temps[arg] = 0;
}
- } else {
- /* legacy dyngen operations */
- args -= def->nb_args;
- /* mark end of basic block */
- tcg_la_bb_end(s, dead_temps);
+ s->op_dead_iargs[op_index] = dead_iargs;
}
break;
}
@@ -1801,7 +1825,9 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
/* store globals and free associated registers (we assume the call
can modify any global. */
- save_globals(s, allocated_regs);
+ if (!(flags & TCG_CALL_CONST)) {
+ save_globals(s, allocated_regs);
+ }
tcg_out_op(s, opc, &func_arg, &const_func_arg);
@@ -1834,20 +1860,15 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
#ifdef CONFIG_PROFILER
-static int64_t dyngen_table_op_count[NB_OPS];
+static int64_t tcg_table_op_count[NB_OPS];
void dump_op_count(void)
{
int i;
FILE *f;
- f = fopen("/tmp/op1.log", "w");
- for(i = 0; i < INDEX_op_end; i++) {
- fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
- }
- fclose(f);
- f = fopen("/tmp/op2.log", "w");
+ f = fopen("/tmp/op.log", "w");
for(i = INDEX_op_end; i < NB_OPS; i++) {
- fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, dyngen_table_op_count[i]);
+ fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, tcg_table_op_count[i]);
}
fclose(f);
}
@@ -1863,10 +1884,10 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
const TCGArg *args;
#ifdef DEBUG_DISAS
- if (unlikely(loglevel & CPU_LOG_TB_OP)) {
- fprintf(logfile, "OP:\n");
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ qemu_log("OP:\n");
tcg_dump_ops(s, logfile);
- fprintf(logfile, "\n");
+ qemu_log("\n");
}
#endif
@@ -1879,10 +1900,10 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
#endif
#ifdef DEBUG_DISAS
- if (unlikely(loglevel & CPU_LOG_TB_OP_OPT)) {
- fprintf(logfile, "OP after la:\n");
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT))) {
+ qemu_log("OP after la:\n");
tcg_dump_ops(s, logfile);
- fprintf(logfile, "\n");
+ qemu_log("\n");
}
#endif
@@ -1897,7 +1918,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
for(;;) {
opc = gen_opc_buf[op_index];
#ifdef CONFIG_PROFILER
- dyngen_table_op_count[opc]++;
+ tcg_table_op_count[opc]++;
#endif
def = &tcg_op_defs[opc];
#if 0
@@ -1952,22 +1973,6 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
goto next;
case INDEX_op_end:
goto the_end;
-
-#ifdef CONFIG_DYNGEN_OP
- case 0 ... INDEX_op_end - 1:
- /* legacy dyngen ops */
-#ifdef CONFIG_PROFILER
- s->old_op_count++;
-#endif
- tcg_reg_alloc_bb_end(s, s->reserved_regs);
- if (search_pc >= 0) {
- s->code_ptr += def->copy_size;
- args += def->nb_args;
- } else {
- args = dyngen_op(s, opc, args);
- }
- goto next;
-#endif
default:
/* Note: in order to speed up the code, it would be much
faster to have specialized register allocator functions for
@@ -1990,7 +1995,7 @@ static inline int tcg_gen_code_common(TCGContext *s, uint8_t *gen_code_buf,
return -1;
}
-int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
+int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf)
{
#ifdef CONFIG_PROFILER
{
@@ -2018,7 +2023,7 @@ int dyngen_code(TCGContext *s, uint8_t *gen_code_buf)
offset bytes from the start of the TB. The contents of gen_code_buf must
not be changed, though writing the same values is ok.
Return -1 if not found. */
-int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
+int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset)
{
return tcg_gen_code_common(s, gen_code_buf, offset);
}
@@ -2039,8 +2044,6 @@ void tcg_dump_info(FILE *f,
s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
- cpu_fprintf(f, "old ops/total ops %0.1f%%\n",
- s->op_count ? (double)s->old_op_count / s->op_count * 100.0 : 0);
cpu_fprintf(f, "deleted ops/TB %0.2f\n",
s->tb_count ?
(double)s->del_op_count / s->tb_count : 0);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index bc5b902..ad0bd14 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu-common.h"
#include "tcg-target.h"
#if TCG_TARGET_REG_BITS == 32
@@ -114,37 +115,61 @@ typedef tcg_target_ulong TCGArg;
expecially on targets with braindamaged ABIs (e.g. i386).
We use plain int by default to avoid this runtime overhead.
Users of tcg_gen_* don't need to know about any of this, and should
- treat TCGv as an opaque type. */
+ treat TCGv as an opaque type.
+ In additon we do typechecking for different types of variables. TCGv_i32
+ and TCGv_i64 are 32/64-bit variables respectively. TCGv and TCGv_ptr
+ are aliases for target_ulong and host pointer sized values respectively.
+ */
-//#define DEBUG_TCGV 1
+#ifdef DEBUG_TCG
+#define DEBUG_TCGV 1
+#endif
#ifdef DEBUG_TCGV
typedef struct
{
- int n;
-} TCGv;
+ int i32;
+} TCGv_i32;
-#define MAKE_TCGV(i) __extension__ \
- ({ TCGv make_tcgv_tmp = {i}; make_tcgv_tmp;})
-#define GET_TCGV(t) ((t).n)
+typedef struct
+{
+ int i64;
+} TCGv_i64;
+
+#define MAKE_TCGV_I32(i) __extension__ \
+ ({ TCGv_i32 make_tcgv_tmp = {i}; make_tcgv_tmp;})
+#define MAKE_TCGV_I64(i) __extension__ \
+ ({ TCGv_i64 make_tcgv_tmp = {i}; make_tcgv_tmp;})
+#define GET_TCGV_I32(t) ((t).i32)
+#define GET_TCGV_I64(t) ((t).i64)
#if TCG_TARGET_REG_BITS == 32
-#define TCGV_HIGH(t) MAKE_TCGV(GET_TCGV(t) + 1)
+#define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t))
+#define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1)
#endif
#else /* !DEBUG_TCGV */
-typedef int TCGv;
-#define MAKE_TCGV(x) (x)
-#define GET_TCGV(t) (t)
+typedef int TCGv_i32;
+typedef int TCGv_i64;
+#define MAKE_TCGV_I32(x) (x)
+#define MAKE_TCGV_I64(x) (x)
+#define GET_TCGV_I32(t) (t)
+#define GET_TCGV_I64(t) (t)
+
#if TCG_TARGET_REG_BITS == 32
+#define TCGV_LOW(t) (t)
#define TCGV_HIGH(t) ((t) + 1)
#endif
#endif /* DEBUG_TCGV */
+#define TCGV_EQUAL_I32(a, b) (GET_TCGV_I32(a) == GET_TCGV_I32(b))
+#define TCGV_EQUAL_I64(a, b) (GET_TCGV_I64(a) == GET_TCGV_I64(b))
+
/* Dummy definition to avoid compiler warnings. */
-#define TCGV_UNUSED(x) x = MAKE_TCGV(-1)
+#define TCGV_UNUSED_I32(x) x = MAKE_TCGV_I32(-1)
+#define TCGV_UNUSED_I64(x) x = MAKE_TCGV_I64(-1)
/* call flags */
#define TCG_CALL_TYPE_MASK 0x000f
@@ -152,13 +177,17 @@ typedef int TCGv;
#define TCG_CALL_TYPE_REGPARM_1 0x0001 /* i386 style regparm call (1 reg) */
#define TCG_CALL_TYPE_REGPARM_2 0x0002 /* i386 style regparm call (2 regs) */
#define TCG_CALL_TYPE_REGPARM 0x0003 /* i386 style regparm call (3 regs) */
-/* A pure function only reads its arguments and globals variables and
- cannot raise exceptions. Hence a call to a pure function can be
+/* A pure function only reads its arguments and TCG global variables
+ and cannot raise exceptions. Hence a call to a pure function can be
safely suppressed if the return value is not used. */
#define TCG_CALL_PURE 0x0010
+/* A const function only reads its arguments and does not use TCG
+ global variables. Hence a call to such a function does not
+ save TCG global variables back to their canonical location. */
+#define TCG_CALL_CONST 0x0020
/* used to align parameters */
-#define TCG_CALL_DUMMY_TCGV MAKE_TCGV(-1)
+#define TCG_CALL_DUMMY_TCGV MAKE_TCGV_I32(-1)
#define TCG_CALL_DUMMY_ARG ((TCGArg)(-1))
typedef enum {
@@ -254,7 +283,6 @@ struct TCGContext {
int op_count_max; /* max insn per TB */
int64_t temp_count;
int temp_count_max;
- int64_t old_op_count;
int64_t del_op_count;
int64_t code_in_len;
int64_t code_out_len;
@@ -296,27 +324,42 @@ static inline void *tcg_malloc(int size)
void tcg_context_init(TCGContext *s);
void tcg_func_start(TCGContext *s);
-int dyngen_code(TCGContext *s, uint8_t *gen_code_buf);
-int dyngen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset);
+int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf);
+int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset);
void tcg_set_frame(TCGContext *s, int reg,
tcg_target_long start, tcg_target_long size);
-TCGv tcg_global_reg_new(TCGType type, int reg, const char *name);
-TCGv tcg_global_reg2_new_hack(TCGType type, int reg1, int reg2,
- const char *name);
-TCGv tcg_global_mem_new(TCGType type, int reg, tcg_target_long offset,
- const char *name);
-TCGv tcg_temp_new_internal(TCGType type, int temp_local);
-static inline TCGv tcg_temp_new(TCGType type)
+
+TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name);
+TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset,
+ const char *name);
+TCGv_i32 tcg_temp_new_internal_i32(int temp_local);
+static inline TCGv_i32 tcg_temp_new_i32(void)
+{
+ return tcg_temp_new_internal_i32(0);
+}
+static inline TCGv_i32 tcg_temp_local_new_i32(void)
{
- return tcg_temp_new_internal(type, 0);
+ return tcg_temp_new_internal_i32(1);
}
-static inline TCGv tcg_temp_local_new(TCGType type)
+void tcg_temp_free_i32(TCGv_i32 arg);
+char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg);
+
+TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name);
+TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset,
+ const char *name);
+TCGv_i64 tcg_temp_new_internal_i64(int temp_local);
+static inline TCGv_i64 tcg_temp_new_i64(void)
{
- return tcg_temp_new_internal(type, 1);
+ return tcg_temp_new_internal_i64(0);
}
-void tcg_temp_free(TCGv arg);
-char *tcg_get_arg_str(TCGContext *s, char *buf, int buf_size, TCGv arg);
+static inline TCGv_i64 tcg_temp_local_new_i64(void)
+{
+ return tcg_temp_new_internal_i64(1);
+}
+void tcg_temp_free_i64(TCGv_i64 arg);
+char *tcg_get_arg_str_i64(TCGContext *s, char *buf, int buf_size, TCGv_i64 arg);
+
void tcg_dump_info(FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
@@ -357,8 +400,6 @@ typedef struct TCGTargetOpDef {
const char *args_ct_str[TCG_MAX_OP_ARGS];
} TCGTargetOpDef;
-extern TCGOpDef tcg_op_defs[];
-
void tcg_target_init(TCGContext *s);
void tcg_target_qemu_prologue(TCGContext *s);
@@ -370,39 +411,50 @@ do {\
void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
-void tcg_gen_call(TCGContext *s, TCGv func, unsigned int flags,
- unsigned int nb_rets, const TCGv *rets,
- unsigned int nb_params, const TCGv *args1);
-void tcg_gen_shifti_i64(TCGv ret, TCGv arg1,
- int c, int right, int arith);
-
-/* only used for debugging purposes */
-void tcg_register_helper(void *func, const char *name);
-#define TCG_HELPER(func) tcg_register_helper(func, #func)
-const char *tcg_helper_get_name(TCGContext *s, void *func);
-void tcg_dump_ops(TCGContext *s, FILE *outfile);
-
-void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf);
-TCGv tcg_const_i32(int32_t val);
-TCGv tcg_const_i64(int64_t val);
-
#if TCG_TARGET_REG_BITS == 32
#define tcg_const_ptr tcg_const_i32
#define tcg_add_ptr tcg_add_i32
#define tcg_sub_ptr tcg_sub_i32
+#define TCGv_ptr TCGv_i32
+#define GET_TCGV_PTR GET_TCGV_I32
+#define tcg_global_reg_new_ptr tcg_global_reg_new_i32
+#define tcg_global_mem_new_ptr tcg_global_mem_new_i32
+#define tcg_temp_new_ptr tcg_temp_new_i32
+#define tcg_temp_free_ptr tcg_temp_free_i32
#else
#define tcg_const_ptr tcg_const_i64
#define tcg_add_ptr tcg_add_i64
#define tcg_sub_ptr tcg_sub_i64
+#define TCGv_ptr TCGv_i64
+#define GET_TCGV_PTR GET_TCGV_I64
+#define tcg_global_reg_new_ptr tcg_global_reg_new_i64
+#define tcg_global_mem_new_ptr tcg_global_mem_new_i64
+#define tcg_temp_new_ptr tcg_temp_new_i64
+#define tcg_temp_free_ptr tcg_temp_free_i64
#endif
+void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
+ int sizemask, TCGArg ret, int nargs, TCGArg *args);
+
+void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
+ int c, int right, int arith);
+
+/* only used for debugging purposes */
+void tcg_register_helper(void *func, const char *name);
+const char *tcg_helper_get_name(TCGContext *s, void *func);
+void tcg_dump_ops(TCGContext *s, FILE *outfile);
+
+void dump_ops(const uint16_t *opc_buf, const TCGArg *opparam_buf);
+TCGv_i32 tcg_const_i32(int32_t val);
+TCGv_i64 tcg_const_i64(int64_t val);
+TCGv_i32 tcg_const_local_i32(int32_t val);
+TCGv_i64 tcg_const_local_i64(int64_t val);
+
void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type,
int label_index, long addend);
const TCGArg *tcg_gen_code_op(TCGContext *s, int opc, const TCGArg *args1,
unsigned int dead_iargs);
-const TCGArg *dyngen_op(TCGContext *s, int opc, const TCGArg *opparam_ptr);
-
/* tcg-runtime.c */
int64_t tcg_helper_shl_i64(int64_t arg1, int64_t arg2);
int64_t tcg_helper_shr_i64(int64_t arg1, int64_t arg2);
@@ -413,7 +465,7 @@ uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2);
uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2);
extern uint8_t code_gen_prologue[];
-#if defined(__powerpc__) && !defined(__powerpc64__)
+#if defined(_ARCH_PPC) && !defined(_ARCH_PPC64)
#define tcg_qemu_tb_exec(tb_ptr) \
((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr)
#else
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
index 304a0c3..5378e85 100644
--- a/tcg/x86_64/tcg-target.c
+++ b/tcg/x86_64/tcg-target.c
@@ -21,7 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%rax",
"%rcx",
"%rdx",
@@ -39,27 +41,27 @@ const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
"%r14",
"%r15",
};
+#endif
-int tcg_target_reg_alloc_order[] = {
- TCG_REG_RDI,
- TCG_REG_RSI,
- TCG_REG_RDX,
- TCG_REG_RCX,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_RAX,
- TCG_REG_R10,
- TCG_REG_R11,
-
+static const int tcg_target_reg_alloc_order[] = {
TCG_REG_RBP,
TCG_REG_RBX,
TCG_REG_R12,
TCG_REG_R13,
TCG_REG_R14,
TCG_REG_R15,
+ TCG_REG_R10,
+ TCG_REG_R11,
+ TCG_REG_R9,
+ TCG_REG_R8,
+ TCG_REG_RCX,
+ TCG_REG_RDX,
+ TCG_REG_RSI,
+ TCG_REG_RDI,
+ TCG_REG_RAX,
};
-const int tcg_target_call_iarg_regs[6] = {
+static const int tcg_target_call_iarg_regs[6] = {
TCG_REG_RDI,
TCG_REG_RSI,
TCG_REG_RDX,
@@ -68,7 +70,7 @@ const int tcg_target_call_iarg_regs[6] = {
TCG_REG_R9,
};
-const int tcg_target_call_oarg_regs[2] = {
+static const int tcg_target_call_oarg_regs[2] = {
TCG_REG_RAX,
TCG_REG_RDX
};
@@ -191,6 +193,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ARITH_XOR 6
#define ARITH_CMP 7
+#define SHIFT_ROL 0
+#define SHIFT_ROR 1
#define SHIFT_SHL 4
#define SHIFT_SHR 5
#define SHIFT_SAR 7
@@ -240,7 +244,7 @@ static inline void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
}
if (opc & P_EXT)
tcg_out8(s, 0x0f);
- tcg_out8(s, opc);
+ tcg_out8(s, opc & 0xff);
}
static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
@@ -572,7 +576,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
break;
case 0:
+ /* movzbq */
+ tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
+ break;
case 1:
+ /* movzwq */
+ tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
+ break;
case 2:
default:
/* movl */
@@ -1040,7 +1050,13 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
case INDEX_op_sar_i32:
c = SHIFT_SAR;
goto gen_shift32;
-
+ case INDEX_op_rotl_i32:
+ c = SHIFT_ROL;
+ goto gen_shift32;
+ case INDEX_op_rotr_i32:
+ c = SHIFT_ROR;
+ goto gen_shift32;
+
case INDEX_op_shl_i64:
c = SHIFT_SHL;
gen_shift64:
@@ -1061,7 +1077,13 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
case INDEX_op_sar_i64:
c = SHIFT_SAR;
goto gen_shift64;
-
+ case INDEX_op_rotl_i64:
+ c = SHIFT_ROL;
+ goto gen_shift64;
+ case INDEX_op_rotr_i64:
+ c = SHIFT_ROR;
+ goto gen_shift64;
+
case INDEX_op_brcond_i32:
tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
args[3], 0);
@@ -1071,10 +1093,17 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
args[3], P_REXW);
break;
- case INDEX_op_bswap_i32:
+ case INDEX_op_bswap16_i32:
+ case INDEX_op_bswap16_i64:
+ tcg_out8(s, 0x66);
+ tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
+ tcg_out8(s, 8);
+ break;
+ case INDEX_op_bswap32_i32:
+ case INDEX_op_bswap32_i64:
tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
break;
- case INDEX_op_bswap_i64:
+ case INDEX_op_bswap64_i64:
tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
break;
@@ -1085,6 +1114,13 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
break;
+ case INDEX_op_not_i32:
+ tcg_out_modrm(s, 0xf7, 2, args[0]);
+ break;
+ case INDEX_op_not_i64:
+ tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
+ break;
+
case INDEX_op_ext8s_i32:
tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]);
break;
@@ -1221,6 +1257,8 @@ static const TCGTargetOpDef x86_64_op_defs[] = {
{ INDEX_op_shl_i32, { "r", "0", "ci" } },
{ INDEX_op_shr_i32, { "r", "0", "ci" } },
{ INDEX_op_sar_i32, { "r", "0", "ci" } },
+ { INDEX_op_rotl_i32, { "r", "0", "ci" } },
+ { INDEX_op_rotr_i32, { "r", "0", "ci" } },
{ INDEX_op_brcond_i32, { "r", "ri" } },
@@ -1250,15 +1288,23 @@ static const TCGTargetOpDef x86_64_op_defs[] = {
{ INDEX_op_shl_i64, { "r", "0", "ci" } },
{ INDEX_op_shr_i64, { "r", "0", "ci" } },
{ INDEX_op_sar_i64, { "r", "0", "ci" } },
+ { INDEX_op_rotl_i64, { "r", "0", "ci" } },
+ { INDEX_op_rotr_i64, { "r", "0", "ci" } },
{ INDEX_op_brcond_i64, { "r", "re" } },
- { INDEX_op_bswap_i32, { "r", "0" } },
- { INDEX_op_bswap_i64, { "r", "0" } },
+ { INDEX_op_bswap16_i32, { "r", "0" } },
+ { INDEX_op_bswap16_i64, { "r", "0" } },
+ { INDEX_op_bswap32_i32, { "r", "0" } },
+ { INDEX_op_bswap32_i64, { "r", "0" } },
+ { INDEX_op_bswap64_i64, { "r", "0" } },
{ INDEX_op_neg_i32, { "r", "0" } },
{ INDEX_op_neg_i64, { "r", "0" } },
+ { INDEX_op_not_i32, { "r", "0" } },
+ { INDEX_op_not_i64, { "r", "0" } },
+
{ INDEX_op_ext8s_i32, { "r", "r"} },
{ INDEX_op_ext16s_i32, { "r", "r"} },
{ INDEX_op_ext8s_i64, { "r", "r"} },
diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h
index 9a0cca0..8cb05c6 100644
--- a/tcg/x86_64/tcg-target.h
+++ b/tcg/x86_64/tcg-target.h
@@ -56,21 +56,27 @@ enum {
#define TCG_TARGET_CALL_STACK_OFFSET 0
/* optional instructions */
-#define TCG_TARGET_HAS_bswap_i32
-#define TCG_TARGET_HAS_bswap_i64
+#define TCG_TARGET_HAS_bswap16_i32
+#define TCG_TARGET_HAS_bswap16_i64
+#define TCG_TARGET_HAS_bswap32_i32
+#define TCG_TARGET_HAS_bswap32_i64
+#define TCG_TARGET_HAS_bswap64_i64
#define TCG_TARGET_HAS_neg_i32
#define TCG_TARGET_HAS_neg_i64
+#define TCG_TARGET_HAS_not_i32
+#define TCG_TARGET_HAS_not_i64
#define TCG_TARGET_HAS_ext8s_i32
#define TCG_TARGET_HAS_ext16s_i32
#define TCG_TARGET_HAS_ext8s_i64
#define TCG_TARGET_HAS_ext16s_i64
#define TCG_TARGET_HAS_ext32s_i64
+#define TCG_TARGET_HAS_rot_i32
+#define TCG_TARGET_HAS_rot_i64
/* Note: must be synced with dyngen-exec.h */
#define TCG_AREG0 TCG_REG_R14
#define TCG_AREG1 TCG_REG_R15
#define TCG_AREG2 TCG_REG_R12
-#define TCG_AREG3 TCG_REG_R13
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{