mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
- Remove retranslation remenents
- Return success from patch_reloc - Preserve 32-bit values as zero-extended on x86_64 - Make bswap during memory ops as optional - Cleanup xxhash - Revert constant pooling for tcg/sparc/ -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJcFxchAAoJEGTfOOivfiFfBUcIALmEeTTRkDtY8rCX0Thegd6g O9roAEHvSu2BS3Zd3EwA+mu5OxcL8WeZY2LYBodFlCCsl/yQ09Lv7QmxrGtX7WNx VF96BftTxYFGVC3Xc6+Q16/dSYM4qcWLuDxAE9BAh47m9NvTjPq+9ntEJMlalIDh My8ANyGByBZeUeBXJuNReJcsGP5eUmNyuaM+aOlMjcVJeFAtvFacwkKpJdLPDM53 feDEiKhRWCkZq1ll4yFtuVTc+dQeYfLnPk8bkJcv7UAJnYIveXZk/eJcs5/vYjCx 8aePb9PwjbYrgXJgbo8mgVhgLBmakObQa8lJvlc3IZfIMp8OK/6au3TDXDSQAts= =4Kdn -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20181216' into staging - Remove retranslation remenents - Return success from patch_reloc - Preserve 32-bit values as zero-extended on x86_64 - Make bswap during memory ops as optional - Cleanup xxhash - Revert constant pooling for tcg/sparc/ # gpg: Signature made Mon 17 Dec 2018 03:25:21 GMT # gpg: using RSA key 64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-tcg-20181216: (33 commits) xxhash: match output against the original xxhash32 include: move exec/tb-hash-xx.h to qemu/xxhash.h exec: introduce qemu_xxhash{2,4,5,6,7} qht-bench: document -p flag tcg: Drop nargs from tcg_op_insert_{before,after} tcg/mips: Improve the add2/sub2 command to use TCG_TARGET_REG_BITS tcg: Add TCG_TARGET_HAS_MEMORY_BSWAP tcg/optimize: Optimize bswap tcg: Clean up generic bswap64 tcg: Clean up generic bswap32 tcg/i386: Add setup_guest_base_seg for FreeBSD tcg/i386: Precompute all guest_base parameters tcg/i386: Assume 32-bit values are zero-extended tcg/i386: Implement INDEX_op_extr{lh}_i64_i32 for 32-bit guests tcg/i386: Propagate is64 to tcg_out_qemu_ld_slow_path tcg/i386: Propagate is64 to tcg_out_qemu_ld_direct tcg/s390x: Return false on failure from patch_reloc tcg/ppc: Return false on failure from patch_reloc tcg/arm: Return false on failure from patch_reloc tcg/aarch64: Return false on failure from patch_reloc ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f163448536
@ -20,7 +20,7 @@
|
||||
#ifndef EXEC_TB_HASH_H
|
||||
#define EXEC_TB_HASH_H
|
||||
|
||||
#include "exec/tb-hash-xx.h"
|
||||
#include "qemu/xxhash.h"
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
|
||||
@ -61,7 +61,7 @@ static inline
|
||||
uint32_t tb_hash_func(tb_page_addr_t phys_pc, target_ulong pc, uint32_t flags,
|
||||
uint32_t cf_mask, uint32_t trace_vcpu_dstate)
|
||||
{
|
||||
return tb_hash_func7(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate);
|
||||
return qemu_xxhash7(phys_pc, pc, flags, cf_mask, trace_vcpu_dstate);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -31,8 +31,8 @@
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
#ifndef EXEC_TB_HASH_XX_H
|
||||
#define EXEC_TB_HASH_XX_H
|
||||
#ifndef QEMU_XXHASH_H
|
||||
#define QEMU_XXHASH_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
@ -42,23 +42,23 @@
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
#define TB_HASH_XX_SEED 1
|
||||
#define QEMU_XXHASH_SEED 1
|
||||
|
||||
/*
|
||||
* xxhash32, customized for input variables that are not guaranteed to be
|
||||
* contiguous in memory.
|
||||
*/
|
||||
static inline uint32_t
|
||||
tb_hash_func7(uint64_t a0, uint64_t b0, uint32_t e, uint32_t f, uint32_t g)
|
||||
qemu_xxhash7(uint64_t ab, uint64_t cd, uint32_t e, uint32_t f, uint32_t g)
|
||||
{
|
||||
uint32_t v1 = TB_HASH_XX_SEED + PRIME32_1 + PRIME32_2;
|
||||
uint32_t v2 = TB_HASH_XX_SEED + PRIME32_2;
|
||||
uint32_t v3 = TB_HASH_XX_SEED + 0;
|
||||
uint32_t v4 = TB_HASH_XX_SEED - PRIME32_1;
|
||||
uint32_t a = a0 >> 32;
|
||||
uint32_t b = a0;
|
||||
uint32_t c = b0 >> 32;
|
||||
uint32_t d = b0;
|
||||
uint32_t v1 = QEMU_XXHASH_SEED + PRIME32_1 + PRIME32_2;
|
||||
uint32_t v2 = QEMU_XXHASH_SEED + PRIME32_2;
|
||||
uint32_t v3 = QEMU_XXHASH_SEED + 0;
|
||||
uint32_t v4 = QEMU_XXHASH_SEED - PRIME32_1;
|
||||
uint32_t a = ab;
|
||||
uint32_t b = ab >> 32;
|
||||
uint32_t c = cd;
|
||||
uint32_t d = cd >> 32;
|
||||
uint32_t h32;
|
||||
|
||||
v1 += a * PRIME32_2;
|
||||
@ -98,4 +98,25 @@ tb_hash_func7(uint64_t a0, uint64_t b0, uint32_t e, uint32_t f, uint32_t g)
|
||||
return h32;
|
||||
}
|
||||
|
||||
#endif /* EXEC_TB_HASH_XX_H */
|
||||
static inline uint32_t qemu_xxhash2(uint64_t ab)
|
||||
{
|
||||
return qemu_xxhash7(ab, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t qemu_xxhash4(uint64_t ab, uint64_t cd)
|
||||
{
|
||||
return qemu_xxhash7(ab, cd, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t qemu_xxhash5(uint64_t ab, uint64_t cd, uint32_t e)
|
||||
{
|
||||
return qemu_xxhash7(ab, cd, e, 0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t qemu_xxhash6(uint64_t ab, uint64_t cd, uint32_t e,
|
||||
uint32_t f)
|
||||
{
|
||||
return qemu_xxhash7(ab, cd, e, f, 0);
|
||||
}
|
||||
|
||||
#endif /* QEMU_XXHASH_H */
|
@ -137,6 +137,7 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mul_vec 1
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
|
@ -78,48 +78,40 @@ static const int tcg_target_call_oarg_regs[1] = {
|
||||
#define TCG_REG_GUEST_BASE TCG_REG_X28
|
||||
#endif
|
||||
|
||||
static inline void reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
static inline bool reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = target - code_ptr;
|
||||
tcg_debug_assert(offset == sextract64(offset, 0, 26));
|
||||
/* read instruction, mask away previous PC_REL26 parameter contents,
|
||||
set the proper offset, then write back the instruction. */
|
||||
*code_ptr = deposit32(*code_ptr, 0, 26, offset);
|
||||
if (offset == sextract64(offset, 0, 26)) {
|
||||
/* read instruction, mask away previous PC_REL26 parameter contents,
|
||||
set the proper offset, then write back the instruction. */
|
||||
*code_ptr = deposit32(*code_ptr, 0, 26, offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void reloc_pc26_atomic(tcg_insn_unit *code_ptr,
|
||||
tcg_insn_unit *target)
|
||||
static inline bool reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = target - code_ptr;
|
||||
tcg_insn_unit insn;
|
||||
tcg_debug_assert(offset == sextract64(offset, 0, 26));
|
||||
/* read instruction, mask away previous PC_REL26 parameter contents,
|
||||
set the proper offset, then write back the instruction. */
|
||||
insn = atomic_read(code_ptr);
|
||||
atomic_set(code_ptr, deposit32(insn, 0, 26, offset));
|
||||
if (offset == sextract64(offset, 0, 19)) {
|
||||
*code_ptr = deposit32(*code_ptr, 5, 19, offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = target - code_ptr;
|
||||
tcg_debug_assert(offset == sextract64(offset, 0, 19));
|
||||
*code_ptr = deposit32(*code_ptr, 5, 19, offset);
|
||||
}
|
||||
|
||||
static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static inline bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
tcg_debug_assert(addend == 0);
|
||||
switch (type) {
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_CALL26:
|
||||
reloc_pc26(code_ptr, (tcg_insn_unit *)value);
|
||||
break;
|
||||
return reloc_pc26(code_ptr, (tcg_insn_unit *)value);
|
||||
case R_AARCH64_CONDBR19:
|
||||
reloc_pc19(code_ptr, (tcg_insn_unit *)value);
|
||||
break;
|
||||
return reloc_pc19(code_ptr, (tcg_insn_unit *)value);
|
||||
default:
|
||||
tcg_abort();
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1141,23 +1133,6 @@ static inline void tcg_out_goto_long(TCGContext *s, tcg_insn_unit *target)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tcg_out_goto_noaddr(TCGContext *s)
|
||||
{
|
||||
/* We pay attention here to not modify the branch target by reading from
|
||||
the buffer. This ensure that caches and memory are kept coherent during
|
||||
retranslation. Mask away possible garbage in the high bits for the
|
||||
first translation, while keeping the offset bits for retranslation. */
|
||||
uint32_t old = tcg_in32(s);
|
||||
tcg_out_insn(s, 3206, B, old);
|
||||
}
|
||||
|
||||
static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
|
||||
{
|
||||
/* See comments in tcg_out_goto_noaddr. */
|
||||
uint32_t old = tcg_in32(s) >> 5;
|
||||
tcg_out_insn(s, 3202, B_C, c, old);
|
||||
}
|
||||
|
||||
static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
|
||||
{
|
||||
tcg_out_insn(s, 3207, BLR, reg);
|
||||
@ -1204,7 +1179,7 @@ static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
|
||||
{
|
||||
if (!l->has_value) {
|
||||
tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
|
||||
tcg_out_goto_noaddr(s);
|
||||
tcg_out_insn(s, 3206, B, 0);
|
||||
} else {
|
||||
tcg_out_goto(s, l->u.value_ptr);
|
||||
}
|
||||
@ -1415,7 +1390,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
TCGMemOp size = opc & MO_SIZE;
|
||||
|
||||
reloc_pc19(lb->label_ptr[0], s->code_ptr);
|
||||
bool ok = reloc_pc19(lb->label_ptr[0], s->code_ptr);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
|
||||
tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
|
||||
@ -1437,7 +1413,8 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
TCGMemOp size = opc & MO_SIZE;
|
||||
|
||||
reloc_pc19(lb->label_ptr[0], s->code_ptr);
|
||||
bool ok = reloc_pc19(lb->label_ptr[0], s->code_ptr);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
|
||||
tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
|
||||
@ -1535,7 +1512,7 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp opc,
|
||||
|
||||
/* If not equal, we jump to the slow path. */
|
||||
*label_ptr = s->code_ptr;
|
||||
tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
|
||||
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SOFTMMU */
|
||||
|
@ -131,6 +131,7 @@ enum {
|
||||
};
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
|
@ -187,27 +187,23 @@ static const uint8_t tcg_cond_to_arm_cond[] = {
|
||||
[TCG_COND_GTU] = COND_HI,
|
||||
};
|
||||
|
||||
static inline void reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
static inline bool reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
|
||||
*code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
|
||||
if (offset == sextract32(offset, 0, 24)) {
|
||||
*code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void reloc_pc24_atomic(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
|
||||
tcg_insn_unit insn = atomic_read(code_ptr);
|
||||
tcg_debug_assert(offset == sextract32(offset, 0, 24));
|
||||
atomic_set(code_ptr, deposit32(insn, 0, 24, offset));
|
||||
}
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
tcg_debug_assert(addend == 0);
|
||||
|
||||
if (type == R_ARM_PC24) {
|
||||
reloc_pc24(code_ptr, (tcg_insn_unit *)value);
|
||||
return reloc_pc24(code_ptr, (tcg_insn_unit *)value);
|
||||
} else if (type == R_ARM_PC13) {
|
||||
intptr_t diff = value - (uintptr_t)(code_ptr + 2);
|
||||
tcg_insn_unit insn = *code_ptr;
|
||||
@ -221,7 +217,11 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
} else {
|
||||
int rd = extract32(insn, 12, 4);
|
||||
int rt = rd == TCG_REG_PC ? TCG_REG_TMP : rd;
|
||||
assert(diff >= 0x1000 && diff < 0x100000);
|
||||
|
||||
if (diff < 0x1000 || diff >= 0x100000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* add rt, pc, #high */
|
||||
*code_ptr++ = ((insn & 0xf0000000) | (1 << 25) | ARITH_ADD
|
||||
| (TCG_REG_PC << 16) | (rt << 12)
|
||||
@ -237,6 +237,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define TCG_CT_CONST_ARM 0x100
|
||||
@ -374,22 +375,6 @@ static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
|
||||
(((offset - 8) >> 2) & 0x00ffffff));
|
||||
}
|
||||
|
||||
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
|
||||
{
|
||||
/* We pay attention here to not modify the branch target by masking
|
||||
the corresponding bytes. This ensure that caches and memory are
|
||||
kept coherent during retranslation. */
|
||||
tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0a));
|
||||
}
|
||||
|
||||
static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
|
||||
{
|
||||
/* We pay attention here to not modify the branch target by masking
|
||||
the corresponding bytes. This ensure that caches and memory are
|
||||
kept coherent during retranslation. */
|
||||
tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0b));
|
||||
}
|
||||
|
||||
static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
|
||||
{
|
||||
tcg_out32(s, (cond << 28) | 0x0b000000 |
|
||||
@ -1090,7 +1075,7 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, TCGLabel *l)
|
||||
tcg_out_goto(s, cond, l->u.value_ptr);
|
||||
} else {
|
||||
tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, l, 0);
|
||||
tcg_out_b_noaddr(s, cond);
|
||||
tcg_out_b(s, cond, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1395,7 +1380,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
void *func;
|
||||
|
||||
reloc_pc24(lb->label_ptr[0], s->code_ptr);
|
||||
bool ok = reloc_pc24(lb->label_ptr[0], s->code_ptr);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
@ -1455,7 +1441,8 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOpIdx oi = lb->oi;
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
|
||||
reloc_pc24(lb->label_ptr[0], s->code_ptr);
|
||||
bool ok = reloc_pc24(lb->label_ptr[0], s->code_ptr);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
argreg = TCG_REG_R0;
|
||||
argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
|
||||
@ -1636,7 +1623,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||
/* This a conditional BL only to load a pointer within this opcode into LR
|
||||
for the slow path. We will not be using the value for a tail call. */
|
||||
label_ptr = s->code_ptr;
|
||||
tcg_out_bl_noaddr(s, COND_NE);
|
||||
tcg_out_bl(s, COND_NE, 0);
|
||||
|
||||
tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
|
||||
|
||||
@ -1768,7 +1755,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||
|
||||
/* The conditional call must come last, as we're going to return here. */
|
||||
label_ptr = s->code_ptr;
|
||||
tcg_out_bl_noaddr(s, COND_NE);
|
||||
tcg_out_bl(s, COND_NE, 0);
|
||||
|
||||
add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
|
||||
s->code_ptr, label_ptr);
|
||||
|
@ -84,10 +84,12 @@ typedef enum {
|
||||
TCG_REG_RBP = TCG_REG_EBP,
|
||||
TCG_REG_RSI = TCG_REG_ESI,
|
||||
TCG_REG_RDI = TCG_REG_EDI,
|
||||
|
||||
TCG_AREG0 = TCG_REG_EBP,
|
||||
TCG_REG_CALL_STACK = TCG_REG_ESP
|
||||
} TCGReg;
|
||||
|
||||
/* used for function call generation */
|
||||
#define TCG_REG_CALL_STACK TCG_REG_ESP
|
||||
#define TCG_TARGET_STACK_ALIGN 16
|
||||
#if defined(_WIN64)
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 32
|
||||
@ -133,8 +135,9 @@ extern bool have_avx2;
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
/* Keep target addresses zero-extended in a register. */
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 (TARGET_LONG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 (TARGET_LONG_BITS == 32)
|
||||
#define TCG_TARGET_HAS_div2_i64 1
|
||||
#define TCG_TARGET_HAS_rot_i64 1
|
||||
#define TCG_TARGET_HAS_ext8s_i64 1
|
||||
@ -194,12 +197,6 @@ extern bool have_avx2;
|
||||
#define TCG_TARGET_extract_i64_valid(ofs, len) \
|
||||
(((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32)
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
# define TCG_AREG0 TCG_REG_R14
|
||||
#else
|
||||
# define TCG_AREG0 TCG_REG_EBP
|
||||
#endif
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
}
|
||||
@ -223,6 +220,8 @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
|
||||
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
#endif
|
||||
|
@ -167,7 +167,7 @@ static bool have_lzcnt;
|
||||
|
||||
static tcg_insn_unit *tb_ret_addr;
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
value += addend;
|
||||
@ -175,7 +175,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
case R_386_PC32:
|
||||
value -= (uintptr_t)code_ptr;
|
||||
if (value != (int32_t)value) {
|
||||
tcg_abort();
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case R_386_32:
|
||||
@ -184,13 +184,14 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
case R_386_PC8:
|
||||
value -= (uintptr_t)code_ptr;
|
||||
if (value != (int8_t)value) {
|
||||
tcg_abort();
|
||||
return false;
|
||||
}
|
||||
tcg_patch8(code_ptr, value);
|
||||
break;
|
||||
default:
|
||||
tcg_abort();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
@ -308,13 +309,11 @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
#define P_EXT38 0x200 /* 0x0f 0x38 opcode prefix */
|
||||
#define P_DATA16 0x400 /* 0x66 opcode prefix */
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
# define P_ADDR32 0x800 /* 0x67 opcode prefix */
|
||||
# define P_REXW 0x1000 /* Set REX.W = 1 */
|
||||
# define P_REXB_R 0x2000 /* REG field as byte register */
|
||||
# define P_REXB_RM 0x4000 /* R/M field as byte register */
|
||||
# define P_GS 0x8000 /* gs segment override */
|
||||
#else
|
||||
# define P_ADDR32 0
|
||||
# define P_REXW 0
|
||||
# define P_REXB_R 0
|
||||
# define P_REXB_RM 0
|
||||
@ -527,9 +526,6 @@ static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
|
||||
tcg_debug_assert((opc & P_REXW) == 0);
|
||||
tcg_out8(s, 0x66);
|
||||
}
|
||||
if (opc & P_ADDR32) {
|
||||
tcg_out8(s, 0x67);
|
||||
}
|
||||
if (opc & P_SIMDF3) {
|
||||
tcg_out8(s, 0xf3);
|
||||
} else if (opc & P_SIMDF2) {
|
||||
@ -1658,11 +1654,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||
tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, 0);
|
||||
|
||||
/* Prepare for both the fast path add of the tlb addend, and the slow
|
||||
path function argument setup. There are two cases worth note:
|
||||
For 32-bit guest and x86_64 host, MOVL zero-extends the guest address
|
||||
before the fastpath ADDQ below. For 64-bit guest and x32 host, MOVQ
|
||||
copies the entire guest address for the slow path, while truncation
|
||||
for the 32-bit host happens with the fastpath ADDL below. */
|
||||
path function argument setup. */
|
||||
tcg_out_mov(s, ttype, r1, addrlo);
|
||||
|
||||
/* jne slow_path */
|
||||
@ -1691,7 +1683,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
|
||||
* Record the context of a call to the out of line helper code for the slow path
|
||||
* for a load or store, so that we can later generate the correct helper code
|
||||
*/
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
|
||||
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, bool is_64,
|
||||
TCGMemOpIdx oi,
|
||||
TCGReg datalo, TCGReg datahi,
|
||||
TCGReg addrlo, TCGReg addrhi,
|
||||
tcg_insn_unit *raddr,
|
||||
@ -1701,6 +1694,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
|
||||
|
||||
label->is_ld = is_ld;
|
||||
label->oi = oi;
|
||||
label->type = is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
||||
label->datalo_reg = datalo;
|
||||
label->datahi_reg = datahi;
|
||||
label->addrlo_reg = addrlo;
|
||||
@ -1721,6 +1715,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
TCGReg data_reg;
|
||||
tcg_insn_unit **label_ptr = &l->label_ptr[0];
|
||||
int rexw = (l->type == TCG_TYPE_I64 ? P_REXW : 0);
|
||||
|
||||
/* resolve label address */
|
||||
tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
|
||||
@ -1759,10 +1754,10 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||
data_reg = l->datalo_reg;
|
||||
switch (opc & MO_SSIZE) {
|
||||
case MO_SB:
|
||||
tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
|
||||
tcg_out_ext8s(s, data_reg, TCG_REG_EAX, rexw);
|
||||
break;
|
||||
case MO_SW:
|
||||
tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
|
||||
tcg_out_ext16s(s, data_reg, TCG_REG_EAX, rexw);
|
||||
break;
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
case MO_SL:
|
||||
@ -1862,30 +1857,49 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||
tcg_out_push(s, retaddr);
|
||||
tcg_out_jmp(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
|
||||
}
|
||||
#elif defined(__x86_64__) && defined(__linux__)
|
||||
# include <asm/prctl.h>
|
||||
# include <sys/prctl.h>
|
||||
|
||||
#elif TCG_TARGET_REG_BITS == 32
|
||||
# define x86_guest_base_seg 0
|
||||
# define x86_guest_base_index -1
|
||||
# define x86_guest_base_offset guest_base
|
||||
#else
|
||||
static int x86_guest_base_seg;
|
||||
static int x86_guest_base_index = -1;
|
||||
static int32_t x86_guest_base_offset;
|
||||
# if defined(__x86_64__) && defined(__linux__)
|
||||
# include <asm/prctl.h>
|
||||
# include <sys/prctl.h>
|
||||
int arch_prctl(int code, unsigned long addr);
|
||||
|
||||
static int guest_base_flags;
|
||||
static inline void setup_guest_base_seg(void)
|
||||
static inline int setup_guest_base_seg(void)
|
||||
{
|
||||
if (arch_prctl(ARCH_SET_GS, guest_base) == 0) {
|
||||
guest_base_flags = P_GS;
|
||||
return P_GS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
# define guest_base_flags 0
|
||||
static inline void setup_guest_base_seg(void) { }
|
||||
# elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
||||
# include <machine/sysarch.h>
|
||||
static inline int setup_guest_base_seg(void)
|
||||
{
|
||||
if (sysarch(AMD64_SET_GSBASE, &guest_base) == 0) {
|
||||
return P_GS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
# else
|
||||
static inline int setup_guest_base_seg(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
#endif /* SOFTMMU */
|
||||
|
||||
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
TCGReg base, int index, intptr_t ofs,
|
||||
int seg, TCGMemOp memop)
|
||||
int seg, bool is64, TCGMemOp memop)
|
||||
{
|
||||
const TCGMemOp real_bswap = memop & MO_BSWAP;
|
||||
TCGMemOp bswap = real_bswap;
|
||||
int rexw = is64 * P_REXW;
|
||||
int movop = OPC_MOVL_GvEv;
|
||||
|
||||
if (have_movbe && real_bswap) {
|
||||
@ -1899,7 +1913,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
base, index, 0, ofs);
|
||||
break;
|
||||
case MO_SB:
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVSBL + P_REXW + seg, datalo,
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVSBL + rexw + seg, datalo,
|
||||
base, index, 0, ofs);
|
||||
break;
|
||||
case MO_UW:
|
||||
@ -1919,9 +1933,9 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
base, index, 0, ofs);
|
||||
tcg_out_rolw_8(s, datalo);
|
||||
}
|
||||
tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
|
||||
tcg_out_modrm(s, OPC_MOVSWL + rexw, datalo, datalo);
|
||||
} else {
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + P_REXW + seg,
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + rexw + seg,
|
||||
datalo, base, index, 0, ofs);
|
||||
}
|
||||
break;
|
||||
@ -2009,49 +2023,21 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
|
||||
label_ptr, offsetof(CPUTLBEntry, addr_read));
|
||||
|
||||
/* TLB Hit. */
|
||||
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, opc);
|
||||
tcg_out_qemu_ld_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, is64, opc);
|
||||
|
||||
/* Record the current context of a load into ldst label */
|
||||
add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, true, is64, oi, datalo, datahi, addrlo, addrhi,
|
||||
s->code_ptr, label_ptr);
|
||||
#else
|
||||
{
|
||||
int32_t offset = guest_base;
|
||||
TCGReg base = addrlo;
|
||||
int index = -1;
|
||||
int seg = 0;
|
||||
|
||||
/* For a 32-bit guest, the high 32 bits may contain garbage.
|
||||
We can do this with the ADDR32 prefix if we're not using
|
||||
a guest base, or when using segmentation. Otherwise we
|
||||
need to zero-extend manually. */
|
||||
if (guest_base == 0 || guest_base_flags) {
|
||||
seg = guest_base_flags;
|
||||
offset = 0;
|
||||
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
|
||||
seg |= P_ADDR32;
|
||||
}
|
||||
} else if (TCG_TARGET_REG_BITS == 64) {
|
||||
if (TARGET_LONG_BITS == 32) {
|
||||
tcg_out_ext32u(s, TCG_REG_L0, base);
|
||||
base = TCG_REG_L0;
|
||||
}
|
||||
if (offset != guest_base) {
|
||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, guest_base);
|
||||
index = TCG_REG_L1;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
tcg_out_qemu_ld_direct(s, datalo, datahi,
|
||||
base, index, offset, seg, opc);
|
||||
}
|
||||
tcg_out_qemu_ld_direct(s, datalo, datahi, addrlo, x86_guest_base_index,
|
||||
x86_guest_base_offset, x86_guest_base_seg,
|
||||
is64, opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
TCGReg base, intptr_t ofs, int seg,
|
||||
TCGMemOp memop)
|
||||
TCGReg base, int index, intptr_t ofs,
|
||||
int seg, TCGMemOp memop)
|
||||
{
|
||||
/* ??? Ideally we wouldn't need a scratch register. For user-only,
|
||||
we could perform the bswap twice to restore the original value
|
||||
@ -2075,8 +2061,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
|
||||
datalo = scratch;
|
||||
}
|
||||
tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
|
||||
datalo, base, ofs);
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVB_EvGv + P_REXB_R + seg,
|
||||
datalo, base, index, 0, ofs);
|
||||
break;
|
||||
case MO_16:
|
||||
if (bswap) {
|
||||
@ -2084,7 +2070,8 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
tcg_out_rolw_8(s, scratch);
|
||||
datalo = scratch;
|
||||
}
|
||||
tcg_out_modrm_offset(s, movop + P_DATA16 + seg, datalo, base, ofs);
|
||||
tcg_out_modrm_sib_offset(s, movop + P_DATA16 + seg, datalo,
|
||||
base, index, 0, ofs);
|
||||
break;
|
||||
case MO_32:
|
||||
if (bswap) {
|
||||
@ -2092,7 +2079,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
tcg_out_bswap32(s, scratch);
|
||||
datalo = scratch;
|
||||
}
|
||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
||||
tcg_out_modrm_sib_offset(s, movop + seg, datalo, base, index, 0, ofs);
|
||||
break;
|
||||
case MO_64:
|
||||
if (TCG_TARGET_REG_BITS == 64) {
|
||||
@ -2101,22 +2088,27 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
||||
tcg_out_bswap64(s, scratch);
|
||||
datalo = scratch;
|
||||
}
|
||||
tcg_out_modrm_offset(s, movop + P_REXW + seg, datalo, base, ofs);
|
||||
tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo,
|
||||
base, index, 0, ofs);
|
||||
} else if (bswap) {
|
||||
tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
|
||||
tcg_out_bswap32(s, scratch);
|
||||
tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs);
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVL_EvGv + seg, scratch,
|
||||
base, index, 0, ofs);
|
||||
tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
|
||||
tcg_out_bswap32(s, scratch);
|
||||
tcg_out_modrm_offset(s, OPC_MOVL_EvGv + seg, scratch, base, ofs+4);
|
||||
tcg_out_modrm_sib_offset(s, OPC_MOVL_EvGv + seg, scratch,
|
||||
base, index, 0, ofs + 4);
|
||||
} else {
|
||||
if (real_bswap) {
|
||||
int t = datalo;
|
||||
datalo = datahi;
|
||||
datahi = t;
|
||||
}
|
||||
tcg_out_modrm_offset(s, movop + seg, datalo, base, ofs);
|
||||
tcg_out_modrm_offset(s, movop + seg, datahi, base, ofs+4);
|
||||
tcg_out_modrm_sib_offset(s, movop + seg, datalo,
|
||||
base, index, 0, ofs);
|
||||
tcg_out_modrm_sib_offset(s, movop + seg, datahi,
|
||||
base, index, 0, ofs + 4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -2149,44 +2141,14 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
|
||||
label_ptr, offsetof(CPUTLBEntry, addr_write));
|
||||
|
||||
/* TLB Hit. */
|
||||
tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, 0, 0, opc);
|
||||
tcg_out_qemu_st_direct(s, datalo, datahi, TCG_REG_L1, -1, 0, 0, opc);
|
||||
|
||||
/* Record the current context of a store into ldst label */
|
||||
add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
|
||||
add_qemu_ldst_label(s, false, is64, oi, datalo, datahi, addrlo, addrhi,
|
||||
s->code_ptr, label_ptr);
|
||||
#else
|
||||
{
|
||||
int32_t offset = guest_base;
|
||||
TCGReg base = addrlo;
|
||||
int seg = 0;
|
||||
|
||||
/* See comment in tcg_out_qemu_ld re zero-extension of addrlo. */
|
||||
if (guest_base == 0 || guest_base_flags) {
|
||||
seg = guest_base_flags;
|
||||
offset = 0;
|
||||
if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
|
||||
seg |= P_ADDR32;
|
||||
}
|
||||
} else if (TCG_TARGET_REG_BITS == 64) {
|
||||
/* ??? Note that we can't use the same SIB addressing scheme
|
||||
as for loads, since we require L0 free for bswap. */
|
||||
if (offset != guest_base) {
|
||||
if (TARGET_LONG_BITS == 32) {
|
||||
tcg_out_ext32u(s, TCG_REG_L0, base);
|
||||
base = TCG_REG_L0;
|
||||
}
|
||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_L1, guest_base);
|
||||
tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_L1, base);
|
||||
base = TCG_REG_L1;
|
||||
offset = 0;
|
||||
} else if (TARGET_LONG_BITS == 32) {
|
||||
tcg_out_ext32u(s, TCG_REG_L1, base);
|
||||
base = TCG_REG_L1;
|
||||
}
|
||||
}
|
||||
|
||||
tcg_out_qemu_st_direct(s, datalo, datahi, base, offset, seg, opc);
|
||||
}
|
||||
tcg_out_qemu_st_direct(s, datalo, datahi, addrlo, x86_guest_base_index,
|
||||
x86_guest_base_offset, x86_guest_base_seg, opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2544,12 +2506,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||
break;
|
||||
case INDEX_op_extu_i32_i64:
|
||||
case INDEX_op_ext32u_i64:
|
||||
case INDEX_op_extrl_i64_i32:
|
||||
tcg_out_ext32u(s, a0, a1);
|
||||
break;
|
||||
case INDEX_op_ext_i32_i64:
|
||||
case INDEX_op_ext32s_i64:
|
||||
tcg_out_ext32s(s, a0, a1);
|
||||
break;
|
||||
case INDEX_op_extrh_i64_i32:
|
||||
tcg_out_shifti(s, SHIFT_SHR + P_REXW, a0, 32);
|
||||
break;
|
||||
#endif
|
||||
|
||||
OP_32_64(deposit):
|
||||
@ -2913,6 +2879,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
|
||||
case INDEX_op_neg_i64:
|
||||
case INDEX_op_not_i32:
|
||||
case INDEX_op_not_i64:
|
||||
case INDEX_op_extrh_i64_i32:
|
||||
return &r_0;
|
||||
|
||||
case INDEX_op_ext8s_i32:
|
||||
@ -2928,6 +2895,7 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
|
||||
case INDEX_op_ext32u_i64:
|
||||
case INDEX_op_ext_i32_i64:
|
||||
case INDEX_op_extu_i32_i64:
|
||||
case INDEX_op_extrl_i64_i32:
|
||||
case INDEX_op_extract_i32:
|
||||
case INDEX_op_extract_i64:
|
||||
case INDEX_op_sextract_i32:
|
||||
@ -3427,6 +3395,21 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
(ARRAY_SIZE(tcg_target_callee_save_regs) + 2) * 4
|
||||
+ stack_addend);
|
||||
#else
|
||||
# if !defined(CONFIG_SOFTMMU) && TCG_TARGET_REG_BITS == 64
|
||||
if (guest_base) {
|
||||
int seg = setup_guest_base_seg();
|
||||
if (seg != 0) {
|
||||
x86_guest_base_seg = seg;
|
||||
} else if (guest_base == (int32_t)guest_base) {
|
||||
x86_guest_base_offset = guest_base;
|
||||
} else {
|
||||
/* Choose R12 because, as a base, it requires a SIB byte. */
|
||||
x86_guest_base_index = TCG_REG_R12;
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, x86_guest_base_index);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
||||
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
|
||||
/* jmp *tb. */
|
||||
@ -3452,13 +3435,6 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
tcg_out_pop(s, tcg_target_callee_save_regs[i]);
|
||||
}
|
||||
tcg_out_opc(s, OPC_RET, 0, 0, 0);
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
/* Try to set up a segment register to point to guest_base. */
|
||||
if (guest_base) {
|
||||
setup_guest_base_seg();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
|
||||
|
@ -203,6 +203,7 @@ extern bool use_mips32r2_instructions;
|
||||
#endif
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
|
@ -168,12 +168,13 @@ static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
*pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
|
||||
}
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
tcg_debug_assert(type == R_MIPS_PC16);
|
||||
tcg_debug_assert(addend == 0);
|
||||
reloc_pc16(code_ptr, (tcg_insn_unit *)value);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define TCG_CT_CONST_ZERO 0x100
|
||||
@ -483,12 +484,7 @@ static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
|
||||
static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
|
||||
TCGReg rt, TCGReg rs)
|
||||
{
|
||||
/* We pay attention here to not modify the branch target by reading
|
||||
the existing value and using it again. This ensure that caches and
|
||||
memory are kept coherent during retranslation. */
|
||||
uint16_t offset = (uint16_t)*s->code_ptr;
|
||||
|
||||
tcg_out_opc_imm(s, opc, rt, rs, offset);
|
||||
tcg_out_opc_imm(s, opc, rt, rs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -796,7 +792,7 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
|
||||
tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
|
||||
tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
|
||||
} else if (rl == al && rl == bl) {
|
||||
tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
|
||||
tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, TCG_TARGET_REG_BITS - 1);
|
||||
tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
|
||||
} else {
|
||||
tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
|
||||
|
@ -353,6 +353,15 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
|
||||
CASE_OP_32_64(ext16u):
|
||||
return (uint16_t)x;
|
||||
|
||||
CASE_OP_32_64(bswap16):
|
||||
return bswap16(x);
|
||||
|
||||
CASE_OP_32_64(bswap32):
|
||||
return bswap32(x);
|
||||
|
||||
case INDEX_op_bswap64_i64:
|
||||
return bswap64(x);
|
||||
|
||||
case INDEX_op_ext_i32_i64:
|
||||
case INDEX_op_ext32s_i64:
|
||||
return (int32_t)x;
|
||||
@ -1105,6 +1114,9 @@ void tcg_optimize(TCGContext *s)
|
||||
CASE_OP_32_64(ext16s):
|
||||
CASE_OP_32_64(ext16u):
|
||||
CASE_OP_32_64(ctpop):
|
||||
CASE_OP_32_64(bswap16):
|
||||
CASE_OP_32_64(bswap32):
|
||||
case INDEX_op_bswap64_i64:
|
||||
case INDEX_op_ext32s_i64:
|
||||
case INDEX_op_ext32u_i64:
|
||||
case INDEX_op_ext_i32_i64:
|
||||
@ -1249,7 +1261,7 @@ void tcg_optimize(TCGContext *s)
|
||||
uint64_t a = ((uint64_t)ah << 32) | al;
|
||||
uint64_t b = ((uint64_t)bh << 32) | bl;
|
||||
TCGArg rl, rh;
|
||||
TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
|
||||
TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32);
|
||||
|
||||
if (opc == INDEX_op_add2_i32) {
|
||||
a += b;
|
||||
@ -1271,7 +1283,7 @@ void tcg_optimize(TCGContext *s)
|
||||
uint32_t b = arg_info(op->args[3])->val;
|
||||
uint64_t r = (uint64_t)a * b;
|
||||
TCGArg rl, rh;
|
||||
TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
|
||||
TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32);
|
||||
|
||||
rl = op->args[0];
|
||||
rh = op->args[1];
|
||||
|
@ -128,6 +128,7 @@ void flush_icache_range(uintptr_t start, uintptr_t stop);
|
||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t);
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define TCG_TARGET_NEED_LDST_LABELS
|
||||
|
@ -193,9 +193,14 @@ static uint32_t reloc_pc24_val(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
return disp & 0x3fffffc;
|
||||
}
|
||||
|
||||
static void reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
static bool reloc_pc24(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
{
|
||||
*pc = (*pc & ~0x3fffffc) | reloc_pc24_val(pc, target);
|
||||
ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
|
||||
if (in_range_b(disp)) {
|
||||
*pc = (*pc & ~0x3fffffc) | (disp & 0x3fffffc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
@ -205,21 +210,14 @@ static uint16_t reloc_pc14_val(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
return disp & 0xfffc;
|
||||
}
|
||||
|
||||
static void reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
static bool reloc_pc14(tcg_insn_unit *pc, tcg_insn_unit *target)
|
||||
{
|
||||
*pc = (*pc & ~0xfffc) | reloc_pc14_val(pc, target);
|
||||
}
|
||||
|
||||
static inline void tcg_out_b_noaddr(TCGContext *s, int insn)
|
||||
{
|
||||
unsigned retrans = *s->code_ptr & 0x3fffffc;
|
||||
tcg_out32(s, insn | retrans);
|
||||
}
|
||||
|
||||
static inline void tcg_out_bc_noaddr(TCGContext *s, int insn)
|
||||
{
|
||||
unsigned retrans = *s->code_ptr & 0xfffc;
|
||||
tcg_out32(s, insn | retrans);
|
||||
ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
|
||||
if (disp == (int16_t) disp) {
|
||||
*pc = (*pc & ~0xfffc) | (disp & 0xfffc);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* parse target specific constraints */
|
||||
@ -525,7 +523,7 @@ static const uint32_t tcg_to_isel[] = {
|
||||
[TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
|
||||
};
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
tcg_insn_unit *target;
|
||||
@ -536,11 +534,9 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
|
||||
switch (type) {
|
||||
case R_PPC_REL14:
|
||||
reloc_pc14(code_ptr, target);
|
||||
break;
|
||||
return reloc_pc14(code_ptr, target);
|
||||
case R_PPC_REL24:
|
||||
reloc_pc24(code_ptr, target);
|
||||
break;
|
||||
return reloc_pc24(code_ptr, target);
|
||||
case R_PPC_ADDR16:
|
||||
/* We are abusing this relocation type. This points to a pair
|
||||
of insns, addis + load. If the displacement is small, we
|
||||
@ -552,7 +548,9 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
} else {
|
||||
int16_t lo = value;
|
||||
int hi = value - lo;
|
||||
assert(hi + lo == value);
|
||||
if (hi + lo != value) {
|
||||
return false;
|
||||
}
|
||||
code_ptr[0] = deposit32(code_ptr[0], 0, 16, hi >> 16);
|
||||
code_ptr[1] = deposit32(code_ptr[1], 0, 16, lo);
|
||||
}
|
||||
@ -560,6 +558,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
|
||||
@ -1179,11 +1178,11 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
|
||||
static void tcg_out_bc(TCGContext *s, int bc, TCGLabel *l)
|
||||
{
|
||||
if (l->has_value) {
|
||||
tcg_out32(s, bc | reloc_pc14_val(s->code_ptr, l->u.value_ptr));
|
||||
bc |= reloc_pc14_val(s->code_ptr, l->u.value_ptr);
|
||||
} else {
|
||||
tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, l, 0);
|
||||
tcg_out_bc_noaddr(s, bc);
|
||||
}
|
||||
tcg_out32(s, bc);
|
||||
}
|
||||
|
||||
static void tcg_out_brcond(TCGContext *s, TCGCond cond,
|
||||
@ -1649,7 +1648,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
TCGReg hi, lo, arg = TCG_REG_R3;
|
||||
|
||||
reloc_pc14(lb->label_ptr[0], s->code_ptr);
|
||||
**lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
|
||||
|
||||
@ -1694,7 +1693,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOp s_bits = opc & MO_SIZE;
|
||||
TCGReg hi, lo, arg = TCG_REG_R3;
|
||||
|
||||
reloc_pc14(lb->label_ptr[0], s->code_ptr);
|
||||
**lb->label_ptr |= reloc_pc14_val(*lb->label_ptr, s->code_ptr);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
|
||||
|
||||
@ -1771,7 +1770,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
|
||||
|
||||
/* Load a pointer into the current opcode w/conditional branch-link. */
|
||||
label_ptr = s->code_ptr;
|
||||
tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
|
||||
tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
|
||||
|
||||
rbase = TCG_REG_R3;
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
@ -1846,7 +1845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
|
||||
|
||||
/* Load a pointer into the current opcode w/conditional branch-link. */
|
||||
label_ptr = s->code_ptr;
|
||||
tcg_out_bc_noaddr(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
|
||||
tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
|
||||
|
||||
rbase = TCG_REG_R3;
|
||||
#else /* !CONFIG_SOFTMMU */
|
||||
@ -2044,13 +2043,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
|
||||
case INDEX_op_br:
|
||||
{
|
||||
TCGLabel *l = arg_label(args[0]);
|
||||
uint32_t insn = B;
|
||||
|
||||
if (l->has_value) {
|
||||
tcg_out_b(s, 0, l->u.value_ptr);
|
||||
insn |= reloc_pc24_val(s->code_ptr, l->u.value_ptr);
|
||||
} else {
|
||||
tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, l, 0);
|
||||
tcg_out_b_noaddr(s, B);
|
||||
}
|
||||
tcg_out32(s, insn);
|
||||
}
|
||||
break;
|
||||
case INDEX_op_ld8u_i32:
|
||||
|
@ -135,6 +135,7 @@ extern uint64_t s390_facilities;
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 160
|
||||
|
||||
#define TCG_TARGET_EXTEND_ARGS 1
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
|
||||
|
||||
|
@ -366,7 +366,7 @@ static void * const qemu_st_helpers[16] = {
|
||||
static tcg_insn_unit *tb_ret_addr;
|
||||
uint64_t s390_facilities;
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
intptr_t pcrel2;
|
||||
@ -377,22 +377,29 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
|
||||
switch (type) {
|
||||
case R_390_PC16DBL:
|
||||
assert(pcrel2 == (int16_t)pcrel2);
|
||||
tcg_patch16(code_ptr, pcrel2);
|
||||
if (pcrel2 == (int16_t)pcrel2) {
|
||||
tcg_patch16(code_ptr, pcrel2);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case R_390_PC32DBL:
|
||||
assert(pcrel2 == (int32_t)pcrel2);
|
||||
tcg_patch32(code_ptr, pcrel2);
|
||||
if (pcrel2 == (int32_t)pcrel2) {
|
||||
tcg_patch32(code_ptr, pcrel2);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case R_390_20:
|
||||
assert(value == sextract64(value, 0, 20));
|
||||
old = *(uint32_t *)code_ptr & 0xf00000ff;
|
||||
old |= ((value & 0xfff) << 16) | ((value & 0xff000) >> 4);
|
||||
tcg_patch32(code_ptr, old);
|
||||
if (value == sextract64(value, 0, 20)) {
|
||||
old = *(uint32_t *)code_ptr & 0xf00000ff;
|
||||
old |= ((value & 0xfff) << 16) | ((value & 0xff000) >> 4);
|
||||
tcg_patch32(code_ptr, old);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* parse target specific constraints */
|
||||
@ -1329,13 +1336,12 @@ static void tgen_branch(TCGContext *s, int cc, TCGLabel *l)
|
||||
static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
|
||||
TCGReg r1, TCGReg r2, TCGLabel *l)
|
||||
{
|
||||
intptr_t off;
|
||||
intptr_t off = 0;
|
||||
|
||||
if (l->has_value) {
|
||||
off = l->u.value_ptr - s->code_ptr;
|
||||
tcg_debug_assert(off == (int16_t)off);
|
||||
} else {
|
||||
/* We need to keep the offset unchanged for retranslation. */
|
||||
off = s->code_ptr[1];
|
||||
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
|
||||
}
|
||||
|
||||
@ -1347,13 +1353,12 @@ static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
|
||||
static void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc,
|
||||
TCGReg r1, int i2, TCGLabel *l)
|
||||
{
|
||||
tcg_target_long off;
|
||||
tcg_target_long off = 0;
|
||||
|
||||
if (l->has_value) {
|
||||
off = l->u.value_ptr - s->code_ptr;
|
||||
tcg_debug_assert(off == (int16_t)off);
|
||||
} else {
|
||||
/* We need to keep the offset unchanged for retranslation. */
|
||||
off = s->code_ptr[1];
|
||||
tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
|
||||
}
|
||||
|
||||
@ -1618,7 +1623,9 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOpIdx oi = lb->oi;
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
|
||||
patch_reloc(lb->label_ptr[0], R_390_PC16DBL, (intptr_t)s->code_ptr, 2);
|
||||
bool ok = patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
|
||||
(intptr_t)s->code_ptr, 2);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_AREG0);
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
@ -1639,7 +1646,9 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||
TCGMemOpIdx oi = lb->oi;
|
||||
TCGMemOp opc = get_memop(oi);
|
||||
|
||||
patch_reloc(lb->label_ptr[0], R_390_PC16DBL, (intptr_t)s->code_ptr, 2);
|
||||
bool ok = patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
|
||||
(intptr_t)s->code_ptr, 2);
|
||||
tcg_debug_assert(ok);
|
||||
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_AREG0);
|
||||
if (TARGET_LONG_BITS == 64) {
|
||||
@ -1696,7 +1705,6 @@ static void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
|
||||
|
||||
base_reg = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 1);
|
||||
|
||||
/* We need to keep the offset unchanged for retranslation. */
|
||||
tcg_out16(s, RI_BRC | (S390_CC_NE << 4));
|
||||
label_ptr = s->code_ptr;
|
||||
s->code_ptr += 1;
|
||||
@ -1724,7 +1732,6 @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
|
||||
|
||||
base_reg = tcg_out_tlb_read(s, addr_reg, opc, mem_index, 0);
|
||||
|
||||
/* We need to keep the offset unchanged for retranslation. */
|
||||
tcg_out16(s, RI_BRC | (S390_CC_NE << 4));
|
||||
label_ptr = s->code_ptr;
|
||||
s->code_ptr += 1;
|
||||
|
@ -164,6 +164,7 @@ extern bool use_vis3_instructions;
|
||||
#define TCG_AREG0 TCG_REG_I0
|
||||
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
{
|
||||
|
@ -291,7 +291,7 @@ static inline int check_fit_i32(int32_t val, unsigned int bits)
|
||||
# define check_fit_ptr check_fit_i32
|
||||
#endif
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
uint32_t insn = *code_ptr;
|
||||
@ -311,29 +311,12 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
insn &= ~INSN_OFF19(-1);
|
||||
insn |= INSN_OFF19(pcrel);
|
||||
break;
|
||||
case R_SPARC_13:
|
||||
/* Note that we're abusing this reloc type for our own needs. */
|
||||
if (!check_fit_ptr(value, 13)) {
|
||||
int adj = (value > 0 ? 0xff8 : -0x1000);
|
||||
value -= adj;
|
||||
assert(check_fit_ptr(value, 13));
|
||||
*code_ptr++ = (ARITH_ADD | INSN_RD(TCG_REG_T2)
|
||||
| INSN_RS1(TCG_REG_TB) | INSN_IMM13(adj));
|
||||
insn ^= INSN_RS1(TCG_REG_TB) ^ INSN_RS1(TCG_REG_T2);
|
||||
}
|
||||
insn &= ~INSN_IMM13(-1);
|
||||
insn |= INSN_IMM13(value);
|
||||
break;
|
||||
case R_SPARC_32:
|
||||
/* Note that we're abusing this reloc type for our own needs. */
|
||||
code_ptr[0] = deposit32(code_ptr[0], 0, 22, value >> 10);
|
||||
code_ptr[1] = deposit32(code_ptr[1], 0, 10, value);
|
||||
return;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
*code_ptr = insn;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* parse target specific constraints */
|
||||
@ -459,6 +442,15 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
|
||||
return;
|
||||
}
|
||||
|
||||
/* A 13-bit constant relative to the TB. */
|
||||
if (!in_prologue && USE_REG_TB) {
|
||||
test = arg - (uintptr_t)s->code_gen_ptr;
|
||||
if (check_fit_ptr(test, 13)) {
|
||||
tcg_out_arithi(s, ret, TCG_REG_TB, test, ARITH_ADD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
|
||||
if (type == TCG_TYPE_I32 || arg == (uint32_t)arg) {
|
||||
tcg_out_sethi(s, ret, arg);
|
||||
@ -488,26 +480,6 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_prologue) {
|
||||
if (USE_REG_TB) {
|
||||
intptr_t diff = arg - (uintptr_t)s->code_gen_ptr;
|
||||
if (check_fit_ptr(diff, 13)) {
|
||||
tcg_out_arithi(s, ret, TCG_REG_TB, diff, ARITH_ADD);
|
||||
} else {
|
||||
new_pool_label(s, arg, R_SPARC_13, s->code_ptr,
|
||||
-(intptr_t)s->code_gen_ptr);
|
||||
tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(TCG_REG_TB));
|
||||
/* May be used to extend the 13-bit range in patch_reloc. */
|
||||
tcg_out32(s, NOP);
|
||||
}
|
||||
} else {
|
||||
new_pool_label(s, arg, R_SPARC_32, s->code_ptr, 0);
|
||||
tcg_out_sethi(s, ret, 0);
|
||||
tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) | INSN_IMM13(0));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* A 64-bit constant decomposed into 2 32-bit pieces. */
|
||||
if (check_fit_i32(lo, 13)) {
|
||||
hi = (arg - lo) >> 32;
|
||||
@ -639,13 +611,11 @@ static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19)
|
||||
|
||||
static void tcg_out_bpcc(TCGContext *s, int scond, int flags, TCGLabel *l)
|
||||
{
|
||||
int off19;
|
||||
int off19 = 0;
|
||||
|
||||
if (l->has_value) {
|
||||
off19 = INSN_OFF19(tcg_pcrel_diff(s, l->u.value_ptr));
|
||||
} else {
|
||||
/* Make sure to preserve destinations during retranslation. */
|
||||
off19 = *s->code_ptr & INSN_OFF19(-1);
|
||||
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, l, 0);
|
||||
}
|
||||
tcg_out_bpcc0(s, scond, flags, off19);
|
||||
@ -685,13 +655,11 @@ static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
|
||||
{
|
||||
/* For 64-bit signed comparisons vs zero, we can avoid the compare. */
|
||||
if (arg2 == 0 && !is_unsigned_cond(cond)) {
|
||||
int off16;
|
||||
int off16 = 0;
|
||||
|
||||
if (l->has_value) {
|
||||
off16 = INSN_OFF16(tcg_pcrel_diff(s, l->u.value_ptr));
|
||||
} else {
|
||||
/* Make sure to preserve destinations during retranslation. */
|
||||
off16 = *s->code_ptr & INSN_OFF16(-1);
|
||||
tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, l, 0);
|
||||
}
|
||||
tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
|
||||
|
215
tcg/tcg-op.c
215
tcg/tcg-op.c
@ -1012,24 +1012,24 @@ void tcg_gen_bswap32_i32(TCGv_i32 ret, TCGv_i32 arg)
|
||||
if (TCG_TARGET_HAS_bswap32_i32) {
|
||||
tcg_gen_op2_i32(INDEX_op_bswap32_i32, ret, arg);
|
||||
} else {
|
||||
TCGv_i32 t0, t1;
|
||||
t0 = tcg_temp_new_i32();
|
||||
t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_const_i32(0x00ff00ff);
|
||||
|
||||
tcg_gen_shli_i32(t0, arg, 24);
|
||||
/* arg = abcd */
|
||||
tcg_gen_shri_i32(t0, arg, 8); /* t0 = .abc */
|
||||
tcg_gen_and_i32(t1, arg, t2); /* t1 = .b.d */
|
||||
tcg_gen_and_i32(t0, t0, t2); /* t0 = .a.c */
|
||||
tcg_gen_shli_i32(t1, t1, 8); /* t1 = b.d. */
|
||||
tcg_gen_or_i32(ret, t0, t1); /* ret = badc */
|
||||
|
||||
tcg_gen_andi_i32(t1, arg, 0x0000ff00);
|
||||
tcg_gen_shli_i32(t1, t1, 8);
|
||||
tcg_gen_or_i32(t0, t0, t1);
|
||||
tcg_gen_shri_i32(t0, ret, 16); /* t0 = ..ba */
|
||||
tcg_gen_shli_i32(t1, ret, 16); /* t1 = dc.. */
|
||||
tcg_gen_or_i32(ret, t0, t1); /* ret = dcba */
|
||||
|
||||
tcg_gen_shri_i32(t1, arg, 8);
|
||||
tcg_gen_andi_i32(t1, t1, 0x0000ff00);
|
||||
tcg_gen_or_i32(t0, t0, t1);
|
||||
|
||||
tcg_gen_shri_i32(t1, arg, 24);
|
||||
tcg_gen_or_i32(ret, t0, t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1638,25 +1638,25 @@ void tcg_gen_bswap32_i64(TCGv_i64 ret, TCGv_i64 arg)
|
||||
} else if (TCG_TARGET_HAS_bswap32_i64) {
|
||||
tcg_gen_op2_i64(INDEX_op_bswap32_i64, ret, arg);
|
||||
} else {
|
||||
TCGv_i64 t0, t1;
|
||||
t0 = tcg_temp_new_i64();
|
||||
t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_const_i64(0x00ff00ff);
|
||||
|
||||
tcg_gen_shli_i64(t0, arg, 24);
|
||||
tcg_gen_ext32u_i64(t0, t0);
|
||||
/* arg = ....abcd */
|
||||
tcg_gen_shri_i64(t0, arg, 8); /* t0 = .....abc */
|
||||
tcg_gen_and_i64(t1, arg, t2); /* t1 = .....b.d */
|
||||
tcg_gen_and_i64(t0, t0, t2); /* t0 = .....a.c */
|
||||
tcg_gen_shli_i64(t1, t1, 8); /* t1 = ....b.d. */
|
||||
tcg_gen_or_i64(ret, t0, t1); /* ret = ....badc */
|
||||
|
||||
tcg_gen_andi_i64(t1, arg, 0x0000ff00);
|
||||
tcg_gen_shli_i64(t1, t1, 8);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
tcg_gen_shli_i64(t1, ret, 48); /* t1 = dc...... */
|
||||
tcg_gen_shri_i64(t0, ret, 16); /* t0 = ......ba */
|
||||
tcg_gen_shri_i64(t1, t1, 32); /* t1 = ....dc.. */
|
||||
tcg_gen_or_i64(ret, t0, t1); /* ret = ....dcba */
|
||||
|
||||
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);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1678,37 +1678,30 @@ void tcg_gen_bswap64_i64(TCGv_i64 ret, TCGv_i64 arg)
|
||||
} else {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_shli_i64(t0, arg, 56);
|
||||
/* arg = abcdefgh */
|
||||
tcg_gen_movi_i64(t2, 0x00ff00ff00ff00ffull);
|
||||
tcg_gen_shri_i64(t0, arg, 8); /* t0 = .abcdefg */
|
||||
tcg_gen_and_i64(t1, arg, t2); /* t1 = .b.d.f.h */
|
||||
tcg_gen_and_i64(t0, t0, t2); /* t0 = .a.c.e.g */
|
||||
tcg_gen_shli_i64(t1, t1, 8); /* t1 = b.d.f.h. */
|
||||
tcg_gen_or_i64(ret, t0, t1); /* ret = badcfehg */
|
||||
|
||||
tcg_gen_andi_i64(t1, arg, 0x0000ff00);
|
||||
tcg_gen_shli_i64(t1, t1, 40);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
tcg_gen_movi_i64(t2, 0x0000ffff0000ffffull);
|
||||
tcg_gen_shri_i64(t0, ret, 16); /* t0 = ..badcfe */
|
||||
tcg_gen_and_i64(t1, ret, t2); /* t1 = ..dc..hg */
|
||||
tcg_gen_and_i64(t0, t0, t2); /* t0 = ..ba..fe */
|
||||
tcg_gen_shli_i64(t1, t1, 16); /* t1 = dc..hg.. */
|
||||
tcg_gen_or_i64(ret, t0, t1); /* ret = dcbahgfe */
|
||||
|
||||
tcg_gen_andi_i64(t1, arg, 0x00ff0000);
|
||||
tcg_gen_shli_i64(t1, t1, 24);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
tcg_gen_shri_i64(t0, ret, 32); /* t0 = ....dcba */
|
||||
tcg_gen_shli_i64(t1, ret, 32); /* t1 = hgfe.... */
|
||||
tcg_gen_or_i64(ret, t0, t1); /* ret = hgfedcba */
|
||||
|
||||
tcg_gen_andi_i64(t1, arg, 0xff000000);
|
||||
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, 0xff000000);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
|
||||
tcg_gen_shri_i64(t1, arg, 24);
|
||||
tcg_gen_andi_i64(t1, t1, 0x00ff0000);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
|
||||
tcg_gen_shri_i64(t1, arg, 40);
|
||||
tcg_gen_andi_i64(t1, t1, 0x0000ff00);
|
||||
tcg_gen_or_i64(t0, t0, t1);
|
||||
|
||||
tcg_gen_shri_i64(t1, arg, 56);
|
||||
tcg_gen_or_i64(ret, t0, t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2701,25 +2694,78 @@ static void tcg_gen_req_mo(TCGBar type)
|
||||
|
||||
void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
|
||||
{
|
||||
TCGMemOp orig_memop;
|
||||
|
||||
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
|
||||
memop = tcg_canonicalize_memop(memop, 0, 0);
|
||||
trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
|
||||
addr, trace_mem_get_info(memop, 0));
|
||||
|
||||
orig_memop = memop;
|
||||
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
|
||||
memop &= ~MO_BSWAP;
|
||||
/* The bswap primitive requires zero-extended input. */
|
||||
if ((memop & MO_SSIZE) == MO_SW) {
|
||||
memop &= ~MO_SIGN;
|
||||
}
|
||||
}
|
||||
|
||||
gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
|
||||
|
||||
if ((orig_memop ^ memop) & MO_BSWAP) {
|
||||
switch (orig_memop & MO_SIZE) {
|
||||
case MO_16:
|
||||
tcg_gen_bswap16_i32(val, val);
|
||||
if (orig_memop & MO_SIGN) {
|
||||
tcg_gen_ext16s_i32(val, val);
|
||||
}
|
||||
break;
|
||||
case MO_32:
|
||||
tcg_gen_bswap32_i32(val, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
|
||||
{
|
||||
TCGv_i32 swap = NULL;
|
||||
|
||||
tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
|
||||
memop = tcg_canonicalize_memop(memop, 0, 1);
|
||||
trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
|
||||
addr, trace_mem_get_info(memop, 1));
|
||||
|
||||
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
|
||||
swap = tcg_temp_new_i32();
|
||||
switch (memop & MO_SIZE) {
|
||||
case MO_16:
|
||||
tcg_gen_ext16u_i32(swap, val);
|
||||
tcg_gen_bswap16_i32(swap, swap);
|
||||
break;
|
||||
case MO_32:
|
||||
tcg_gen_bswap32_i32(swap, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
val = swap;
|
||||
memop &= ~MO_BSWAP;
|
||||
}
|
||||
|
||||
gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
|
||||
|
||||
if (swap) {
|
||||
tcg_temp_free_i32(swap);
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
|
||||
{
|
||||
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
|
||||
TCGMemOp orig_memop;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
|
||||
tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
|
||||
if (memop & MO_SIGN) {
|
||||
@ -2730,24 +2776,85 @@ void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
|
||||
return;
|
||||
}
|
||||
|
||||
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
|
||||
memop = tcg_canonicalize_memop(memop, 1, 0);
|
||||
trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
|
||||
addr, trace_mem_get_info(memop, 0));
|
||||
|
||||
orig_memop = memop;
|
||||
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
|
||||
memop &= ~MO_BSWAP;
|
||||
/* The bswap primitive requires zero-extended input. */
|
||||
if ((memop & MO_SIGN) && (memop & MO_SIZE) < MO_64) {
|
||||
memop &= ~MO_SIGN;
|
||||
}
|
||||
}
|
||||
|
||||
gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
|
||||
|
||||
if ((orig_memop ^ memop) & MO_BSWAP) {
|
||||
switch (orig_memop & MO_SIZE) {
|
||||
case MO_16:
|
||||
tcg_gen_bswap16_i64(val, val);
|
||||
if (orig_memop & MO_SIGN) {
|
||||
tcg_gen_ext16s_i64(val, val);
|
||||
}
|
||||
break;
|
||||
case MO_32:
|
||||
tcg_gen_bswap32_i64(val, val);
|
||||
if (orig_memop & MO_SIGN) {
|
||||
tcg_gen_ext32s_i64(val, val);
|
||||
}
|
||||
break;
|
||||
case MO_64:
|
||||
tcg_gen_bswap64_i64(val, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
|
||||
{
|
||||
tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
|
||||
TCGv_i64 swap = NULL;
|
||||
|
||||
if (TCG_TARGET_REG_BITS == 32 && (memop & MO_SIZE) < MO_64) {
|
||||
tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
|
||||
return;
|
||||
}
|
||||
|
||||
tcg_gen_req_mo(TCG_MO_LD_ST | TCG_MO_ST_ST);
|
||||
memop = tcg_canonicalize_memop(memop, 1, 1);
|
||||
trace_guest_mem_before_tcg(tcg_ctx->cpu, cpu_env,
|
||||
addr, trace_mem_get_info(memop, 1));
|
||||
|
||||
if (!TCG_TARGET_HAS_MEMORY_BSWAP && (memop & MO_BSWAP)) {
|
||||
swap = tcg_temp_new_i64();
|
||||
switch (memop & MO_SIZE) {
|
||||
case MO_16:
|
||||
tcg_gen_ext16u_i64(swap, val);
|
||||
tcg_gen_bswap16_i64(swap, swap);
|
||||
break;
|
||||
case MO_32:
|
||||
tcg_gen_ext32u_i64(swap, val);
|
||||
tcg_gen_bswap32_i64(swap, swap);
|
||||
break;
|
||||
case MO_64:
|
||||
tcg_gen_bswap64_i64(swap, val);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
val = swap;
|
||||
memop &= ~MO_BSWAP;
|
||||
}
|
||||
|
||||
gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
|
||||
|
||||
if (swap) {
|
||||
tcg_temp_free_i64(swap);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcg_gen_ext_i32(TCGv_i32 ret, TCGv_i32 val, TCGMemOp opc)
|
||||
|
18
tcg/tcg.c
18
tcg/tcg.c
@ -66,7 +66,7 @@
|
||||
static void tcg_target_init(TCGContext *s);
|
||||
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
|
||||
static void tcg_target_qemu_prologue(TCGContext *s);
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend);
|
||||
|
||||
/* The CIE and FDE header definitions will be common to all hosts. */
|
||||
@ -268,7 +268,8 @@ static void tcg_out_reloc(TCGContext *s, tcg_insn_unit *code_ptr, int type,
|
||||
/* FIXME: This may break relocations on RISC targets that
|
||||
modify instruction fields in place. The caller may not have
|
||||
written the initial value. */
|
||||
patch_reloc(code_ptr, type, l->u.value, addend);
|
||||
bool ok = patch_reloc(code_ptr, type, l->u.value, addend);
|
||||
tcg_debug_assert(ok);
|
||||
} else {
|
||||
/* add a new relocation entry */
|
||||
r = tcg_malloc(sizeof(TCGRelocation));
|
||||
@ -288,7 +289,8 @@ static void tcg_out_label(TCGContext *s, TCGLabel *l, tcg_insn_unit *ptr)
|
||||
tcg_debug_assert(!l->has_value);
|
||||
|
||||
for (r = l->u.first_reloc; r != NULL; r = r->next) {
|
||||
patch_reloc(r->ptr, r->type, value, r->addend);
|
||||
bool ok = patch_reloc(r->ptr, r->type, value, r->addend);
|
||||
tcg_debug_assert(ok);
|
||||
}
|
||||
|
||||
l->has_value = 1;
|
||||
@ -2203,16 +2205,14 @@ TCGOp *tcg_emit_op(TCGOpcode opc)
|
||||
return op;
|
||||
}
|
||||
|
||||
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op,
|
||||
TCGOpcode opc, int nargs)
|
||||
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op, TCGOpcode opc)
|
||||
{
|
||||
TCGOp *new_op = tcg_op_alloc(opc);
|
||||
QTAILQ_INSERT_BEFORE(old_op, new_op, link);
|
||||
return new_op;
|
||||
}
|
||||
|
||||
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
|
||||
TCGOpcode opc, int nargs)
|
||||
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op, TCGOpcode opc)
|
||||
{
|
||||
TCGOp *new_op = tcg_op_alloc(opc);
|
||||
QTAILQ_INSERT_AFTER(&s->ops, old_op, new_op, link);
|
||||
@ -2550,7 +2550,7 @@ static bool liveness_pass_2(TCGContext *s)
|
||||
TCGOpcode lopc = (arg_ts->type == TCG_TYPE_I32
|
||||
? INDEX_op_ld_i32
|
||||
: INDEX_op_ld_i64);
|
||||
TCGOp *lop = tcg_op_insert_before(s, op, lopc, 3);
|
||||
TCGOp *lop = tcg_op_insert_before(s, op, lopc);
|
||||
|
||||
lop->args[0] = temp_arg(dir_ts);
|
||||
lop->args[1] = temp_arg(arg_ts->mem_base);
|
||||
@ -2619,7 +2619,7 @@ static bool liveness_pass_2(TCGContext *s)
|
||||
TCGOpcode sopc = (arg_ts->type == TCG_TYPE_I32
|
||||
? INDEX_op_st_i32
|
||||
: INDEX_op_st_i64);
|
||||
TCGOp *sop = tcg_op_insert_after(s, op, sopc, 3);
|
||||
TCGOp *sop = tcg_op_insert_after(s, op, sopc);
|
||||
|
||||
sop->args[0] = temp_arg(dir_ts);
|
||||
sop->args[1] = temp_arg(arg_ts->mem_base);
|
||||
|
@ -1071,8 +1071,8 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
|
||||
|
||||
TCGOp *tcg_emit_op(TCGOpcode opc);
|
||||
void tcg_op_remove(TCGContext *s, TCGOp *op);
|
||||
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg);
|
||||
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg);
|
||||
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *op, TCGOpcode opc);
|
||||
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc);
|
||||
|
||||
void tcg_optimize(TCGContext *s);
|
||||
|
||||
|
@ -198,6 +198,8 @@ static inline void flush_icache_range(uintptr_t start, uintptr_t stop)
|
||||
We prefer consistency across hosts on this. */
|
||||
#define TCG_TARGET_DEFAULT_MO (0)
|
||||
|
||||
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
|
||||
|
||||
static inline void tb_target_set_jmp_target(uintptr_t tc_ptr,
|
||||
uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
|
@ -369,7 +369,7 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
intptr_t value, intptr_t addend)
|
||||
{
|
||||
/* tcg_out_reloc always uses the same type, addend. */
|
||||
@ -381,6 +381,7 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type,
|
||||
} else {
|
||||
tcg_patch64(code_ptr, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse target specific constraints. */
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/qht.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/tb-hash-xx.h"
|
||||
#include "qemu/xxhash.h"
|
||||
|
||||
struct thread_stats {
|
||||
size_t rd;
|
||||
@ -72,6 +72,7 @@ static const char commands_string[] =
|
||||
" -n = number of threads\n"
|
||||
"\n"
|
||||
" -o = offset at which keys start\n"
|
||||
" -p = precompute hashes\n"
|
||||
"\n"
|
||||
" -g = set -s,-k,-K,-l,-r to the same value\n"
|
||||
" -s = initial size hint\n"
|
||||
@ -104,7 +105,7 @@ static bool is_equal(const void *ap, const void *bp)
|
||||
|
||||
static uint32_t h(unsigned long v)
|
||||
{
|
||||
return tb_hash_func7(v, 0, 0, 0, 0);
|
||||
return qemu_xxhash2(v);
|
||||
}
|
||||
|
||||
static uint32_t hval(unsigned long v)
|
||||
|
14
util/qsp.c
14
util/qsp.c
@ -61,7 +61,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/qht.h"
|
||||
#include "qemu/rcu.h"
|
||||
#include "exec/tb-hash-xx.h"
|
||||
#include "qemu/xxhash.h"
|
||||
|
||||
enum QSPType {
|
||||
QSP_MUTEX,
|
||||
@ -135,13 +135,13 @@ QemuCondWaitFunc qemu_cond_wait_func = qemu_cond_wait_impl;
|
||||
* without it we still get a pretty unique hash.
|
||||
*/
|
||||
static inline
|
||||
uint32_t do_qsp_callsite_hash(const QSPCallSite *callsite, uint64_t a)
|
||||
uint32_t do_qsp_callsite_hash(const QSPCallSite *callsite, uint64_t ab)
|
||||
{
|
||||
uint64_t b = (uint64_t)(uintptr_t)callsite->obj;
|
||||
uint64_t cd = (uint64_t)(uintptr_t)callsite->obj;
|
||||
uint32_t e = callsite->line;
|
||||
uint32_t f = callsite->type;
|
||||
|
||||
return tb_hash_func7(a, b, e, f, 0);
|
||||
return qemu_xxhash6(ab, cd, e, f);
|
||||
}
|
||||
|
||||
static inline
|
||||
@ -169,11 +169,11 @@ static uint32_t qsp_entry_no_thread_hash(const QSPEntry *entry)
|
||||
static uint32_t qsp_entry_no_thread_obj_hash(const QSPEntry *entry)
|
||||
{
|
||||
const QSPCallSite *callsite = entry->callsite;
|
||||
uint64_t a = g_str_hash(callsite->file);
|
||||
uint64_t b = callsite->line;
|
||||
uint64_t ab = g_str_hash(callsite->file);
|
||||
uint64_t cd = callsite->line;
|
||||
uint32_t e = callsite->type;
|
||||
|
||||
return tb_hash_func7(a, b, e, 0, 0);
|
||||
return qemu_xxhash5(ab, cd, e);
|
||||
}
|
||||
|
||||
static bool qsp_callsite_cmp(const void *ap, const void *bp)
|
||||
|
Loading…
Reference in New Issue
Block a user