aboutsummaryrefslogtreecommitdiff
path: root/tcg
diff options
context:
space:
mode:
Diffstat (limited to 'tcg')
-rw-r--r--tcg/README10
-rw-r--r--tcg/arm/tcg-target.c69
-rw-r--r--tcg/ia64/tcg-target.c2
-rw-r--r--tcg/mips/tcg-target.c2
4 files changed, 49 insertions, 34 deletions
diff --git a/tcg/README b/tcg/README
index 68d27ffa6d..a18a87ffcd 100644
--- a/tcg/README
+++ b/tcg/README
@@ -75,11 +75,11 @@ destroyed, but local temporaries and globals are preserved.
* Helpers:
Using the tcg_gen_helper_x_y it is possible to call any function
-taking i32, i64 or pointer types. By default, before calling an helper,
+taking i32, i64 or pointer types. By default, before calling a helper,
all globals are stored at their canonical location and it is assumed
-that the function can modify them. This can be overriden by the
+that the function can modify them. This can be overridden by the
TCG_CALL_CONST function modifier. By default, the helper is allowed to
-modify the CPU state or raise an exception. This can be overriden by
+modify the CPU state or raise an exception. This can be overridden by
the TCG_CALL_PURE function modifier, in which case the call to the
function is removed if the return value is not used.
@@ -364,7 +364,7 @@ formed from two 32-bit arguments. The result is a 32-bit value.
********* QEMU specific operations
-* tb_exit t0
+* exit_tb t0
Exit the current TB and return the value t0 (word type).
@@ -488,7 +488,7 @@ register.
the speed of the translation.
- Don't hesitate to use helpers for complicated or seldom used target
- intructions. There is little performance advantage in using TCG to
+ instructions. There is little performance advantage in using TCG to
implement target instructions taking more than about twenty TCG
instructions.
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index a3af5b222e..1eb5605f8c 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -113,12 +113,25 @@ static const int tcg_target_call_oarg_regs[2] = {
TCG_REG_R0, TCG_REG_R1
};
+static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
+{
+ *(uint32_t *) code_ptr = target;
+}
+
+static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
+{
+ uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
+
+ *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
+ | (offset & 0xffffff);
+}
+
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend)
{
switch (type) {
case R_ARM_ABS32:
- *(uint32_t *) code_ptr = value;
+ reloc_abs32(code_ptr, value);
break;
case R_ARM_CALL:
@@ -127,8 +140,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_abort();
case R_ARM_PC24:
- *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & 0xff000000) |
- (((value - ((tcg_target_long) code_ptr + 8)) >> 2) & 0xffffff);
+ reloc_pc24(code_ptr, value);
break;
}
}
@@ -394,35 +406,38 @@ static inline void tcg_out_dat_imm(TCGContext *s,
}
static inline void tcg_out_movi32(TCGContext *s,
- int cond, int rd, int32_t arg)
+ int cond, int rd, uint32_t arg)
{
/* TODO: This is very suboptimal, we can easily have a constant
* pool somewhere after all the instructions. */
-
- if (arg < 0 && arg > -0x100)
- return tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
-
- if (use_armv7_instructions) {
+ if ((int)arg < 0 && (int)arg >= -0x100) {
+ tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
+ } else if (use_armv7_instructions) {
/* use movw/movt */
/* movw */
tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
| ((arg << 4) & 0x000f0000) | (arg & 0xfff));
- if (arg & 0xffff0000)
+ if (arg & 0xffff0000) {
/* movt */
tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
| ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
- } else {
- tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
- if (arg & 0x0000ff00)
- tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
- ((arg >> 8) & 0xff) | 0xc00);
- if (arg & 0x00ff0000)
- tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
- ((arg >> 16) & 0xff) | 0x800);
- if (arg & 0xff000000)
- tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
- ((arg >> 24) & 0xff) | 0x400);
}
+ } else {
+ int opc = ARITH_MOV;
+ int rn = 0;
+
+ do {
+ int i, rot;
+
+ i = ctz32(arg) & ~1;
+ rot = ((32 - i) << 7) & 0xf00;
+ tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
+ arg &= ~(0xff << i);
+
+ opc = ARITH_ORR;
+ rn = rd;
+ } while (arg);
+ }
}
static inline void tcg_out_mul32(TCGContext *s,
@@ -1031,7 +1046,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
}
label_ptr = (void *) s->code_ptr;
- tcg_out_b(s, COND_EQ, 8);
+ tcg_out_b_noaddr(s, COND_EQ);
/* TODO: move this code to where the constants pool will be */
if (addr_reg != TCG_REG_R0) {
@@ -1076,7 +1091,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
break;
}
- *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
+ reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
uint32_t offset = GUEST_BASE;
@@ -1236,7 +1251,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
- tcg_out_st32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
+ tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
} else {
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
@@ -1245,7 +1260,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
}
label_ptr = (void *) s->code_ptr;
- tcg_out_b(s, COND_EQ, 8);
+ tcg_out_b_noaddr(s, COND_EQ);
/* TODO: move this code to where the constants pool will be */
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
@@ -1317,7 +1332,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
if (opc == 3)
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
- *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
+ reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
uint32_t offset = GUEST_BASE;
@@ -1399,7 +1414,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
/* Direct jump method */
#if defined(USE_DIRECT_JUMP)
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
- tcg_out_b(s, COND_AL, 8);
+ tcg_out_b_noaddr(s, COND_AL);
#else
tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 3ddf434571..e2e44f7d76 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -1329,7 +1329,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg)
static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
{
- tcg_out_bundle(s, mII,
+ tcg_out_bundle(s, miI,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb));
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 2af7a2e818..4e92a50e6f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -352,7 +352,7 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
{
/* We need to keep the offset unchanged for retranslation */
- uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
+ uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
}