Merge remote-tracking branch 'rth/tcg-next' into staging

# By Richard Henderson
# Via Richard Henderson
* rth/tcg-next:
  tcg-arm: Implement tcg_register_jit
  tcg-i386: Use QEMU_BUILD_BUG_ON instead of assert for frame size
  tcg: Move the CIE and FDE header definitions to common code
  tcg: Fix high_pc fields in .debug_info
  tcg-arm: Use AT_PLATFORM to detect the host ISA
  tcg-arm: Simplify logic in detecting the ARM ISA in use
  tcg-arm: Rename use_armv5_instructions to use_armvt5_instructions
  tcg-arm: Make use of conditional availability of opcodes for divide
  tcg: Simplify logic using TCG_OPF_NOT_PRESENT
  tcg: Allow non-constant control macros
  tcg-ppc64: Don't implement rem
  tcg-ppc: Don't implement rem
  tcg-arm: Don't implement rem
  tcg: Split rem requirement from div requirement
  tcg: Add myself to general TCG maintainership

Message-id: 1373379515-28596-1-git-send-email-rth@twiddle.net
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
master
Anthony Liguori 2013-07-10 10:53:55 -05:00
commit 6272d17c42
20 changed files with 248 additions and 218 deletions

View File

@ -781,6 +781,7 @@ Tiny Code Generator (TCG)
-------------------------
Common code
M: qemu-devel@nongnu.org
M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: tcg/

View File

@ -40,6 +40,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
#define TCG_TARGET_HAS_ext8u_i32 1
@ -62,6 +63,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1

View File

@ -22,50 +22,43 @@
* THE SOFTWARE.
*/
#if defined(__ARM_ARCH_7__) || \
defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7EM__) || \
defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_7R__)
#define USE_ARMV7_INSTRUCTIONS
/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
#ifndef __ARM_ARCH
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
# define __ARM_ARCH 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
|| defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
|| defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH 5
# else
# define __ARM_ARCH 4
# endif
#endif
#if defined(USE_ARMV7_INSTRUCTIONS) || \
defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || \
defined(__ARM_ARCH_6T2__) || \
defined(__ARM_ARCH_6Z__) || \
defined(__ARM_ARCH_6ZK__)
#define USE_ARMV6_INSTRUCTIONS
#endif
static int arm_arch = __ARM_ARCH;
#if defined(USE_ARMV6_INSTRUCTIONS) || \
defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5TE__) || \
defined(__ARM_ARCH_5TEJ__)
#define USE_ARMV5_INSTRUCTIONS
#endif
#ifdef USE_ARMV5_INSTRUCTIONS
static const int use_armv5_instructions = 1;
#if defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
# define use_armv5t_instructions 1
#else
static const int use_armv5_instructions = 0;
# define use_armv5t_instructions use_armv6_instructions
#endif
#undef USE_ARMV5_INSTRUCTIONS
#ifdef USE_ARMV6_INSTRUCTIONS
static const int use_armv6_instructions = 1;
#else
static const int use_armv6_instructions = 0;
#endif
#undef USE_ARMV6_INSTRUCTIONS
#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
#ifdef USE_ARMV7_INSTRUCTIONS
static const int use_armv7_instructions = 1;
#else
static const int use_armv7_instructions = 0;
#ifndef use_idiv_instructions
bool use_idiv_instructions;
#endif
#ifdef CONFIG_GETAUXVAL
# include <sys/auxv.h>
#endif
#undef USE_ARMV7_INSTRUCTIONS
#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@ -1023,7 +1016,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
if (addr & 1) {
/* Use BLX if the target is in Thumb mode */
if (!use_armv5_instructions) {
if (!use_armv5t_instructions) {
tcg_abort();
}
tcg_out_blx_imm(s, val);
@ -1042,7 +1035,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr)
static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
{
if (use_armv5_instructions) {
if (use_armv5t_instructions) {
tcg_out_blx(s, cond, arg);
} else {
tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
@ -1926,18 +1919,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_divu_i32:
tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
break;
case INDEX_op_rem_i32:
tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
SHIFT_IMM_LSL(0));
break;
case INDEX_op_remu_i32:
tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
SHIFT_IMM_LSL(0));
break;
default:
tcg_abort();
@ -2041,18 +2022,31 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
#if TCG_TARGET_HAS_div_i32
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_rem_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
{ INDEX_op_remu_i32, { "r", "r", "r" } },
#endif
{ -1 },
};
static void tcg_target_init(TCGContext *s)
{
#if defined(CONFIG_GETAUXVAL)
/* Only probe for the platform and capabilities if we havn't already
determined maximum values at compile time. */
# if !defined(use_idiv_instructions)
{
unsigned long hwcap = getauxval(AT_HWCAP);
use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
}
# endif
if (__ARM_ARCH < 7) {
const char *pl = (const char *)getauxval(AT_PLATFORM);
if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
arm_arch = pl[1] - '0';
}
}
#endif /* GETAUXVAL */
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
(1 << TCG_REG_R0) |
@ -2094,23 +2088,31 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
tcg_out_movi32(s, COND_AL, ret, arg);
}
/* Compute frame size via macros, to share between tcg_target_qemu_prologue
and tcg_register_jit. */
#define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
#define FRAME_SIZE \
((PUSH_SIZE \
+ TCG_STATIC_CALL_ARGS_SIZE \
+ CPU_TEMP_BUF_NLONGS * sizeof(long) \
+ TCG_TARGET_STACK_ALIGN - 1) \
& -TCG_TARGET_STACK_ALIGN)
static void tcg_target_qemu_prologue(TCGContext *s)
{
int frame_size;
int stack_addend;
/* Calling convention requires us to save r4-r11 and lr. */
/* stmdb sp!, { r4 - r11, lr } */
tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
/* Allocate the local stack frame. */
frame_size = TCG_STATIC_CALL_ARGS_SIZE;
frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
/* We saved an odd number of registers above; keep an 8 aligned stack. */
frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
& -TCG_TARGET_STACK_ALIGN) + 4;
/* Reserve callee argument and tcg temp space. */
stack_addend = FRAME_SIZE - PUSH_SIZE;
tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
TCG_REG_CALL_STACK, frame_size, 1);
TCG_REG_CALL_STACK, stack_addend, 1);
tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
CPU_TEMP_BUF_NLONGS * sizeof(long));
@ -2121,8 +2123,58 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* Epilogue. We branch here via tb_ret_addr. */
tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
TCG_REG_CALL_STACK, frame_size, 1);
TCG_REG_CALL_STACK, stack_addend, 1);
/* ldmia sp!, { r4 - r11, pc } */
tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
}
typedef struct {
DebugFrameCIE cie;
DebugFrameFDEHeader fde;
uint8_t fde_def_cfa[4];
uint8_t fde_reg_ofs[18];
} DebugFrame;
#define ELF_HOST_MACHINE EM_ARM
/* We're expecting a 2 byte uleb128 encoded value. */
QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
static DebugFrame debug_frame = {
.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
.cie.id = -1,
.cie.version = 1,
.cie.code_align = 1,
.cie.data_align = 0x7c, /* sleb128 -4 */
.cie.return_column = 14,
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
12, 13, /* DW_CFA_def_cfa sp, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
.fde_reg_ofs = {
/* The following must match the stmdb in the prologue. */
0x8e, 1, /* DW_CFA_offset, lr, -4 */
0x8b, 2, /* DW_CFA_offset, r11, -8 */
0x8a, 3, /* DW_CFA_offset, r10, -12 */
0x89, 4, /* DW_CFA_offset, r9, -16 */
0x88, 5, /* DW_CFA_offset, r8, -20 */
0x87, 6, /* DW_CFA_offset, r7, -24 */
0x86, 7, /* DW_CFA_offset, r6, -28 */
0x85, 8, /* DW_CFA_offset, r5, -32 */
0x84, 9, /* DW_CFA_offset, r4, -36 */
}
};
void tcg_register_jit(void *buf, size_t buf_size)
{
debug_frame.fde.func_start = (tcg_target_long) buf;
debug_frame.fde.func_len = buf_size;
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}

View File

@ -49,6 +49,13 @@ typedef enum {
#define TCG_TARGET_NB_REGS 16
#ifdef __ARM_ARCH_EXT_IDIV__
#define use_idiv_instructions 1
#else
extern bool use_idiv_instructions;
#endif
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_R13
#define TCG_TARGET_STACK_ALIGN 8
@ -73,12 +80,8 @@ typedef enum {
#define TCG_TARGET_HAS_deposit_i32 1
#define TCG_TARGET_HAS_movcond_i32 1
#define TCG_TARGET_HAS_muls2_i32 1
#ifdef __ARM_ARCH_EXT_IDIV__
#define TCG_TARGET_HAS_div_i32 1
#else
#define TCG_TARGET_HAS_div_i32 0
#endif
#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
#define TCG_TARGET_HAS_rem_i32 0
extern bool tcg_target_deposit_valid(int ofs, int len);
#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid

View File

@ -1765,29 +1765,12 @@ static void tcg_target_init(TCGContext *s)
tcg_add_target_add_op_defs(hppa_op_defs);
}
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t id;
uint8_t version;
char augmentation[1];
uint8_t code_align;
uint8_t data_align;
uint8_t return_column;
} DebugFrameCIE;
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t cie_offset;
tcg_target_long func_start __attribute__((packed));
tcg_target_long func_len __attribute__((packed));
uint8_t def_cfa[4];
uint8_t ret_ofs[3];
uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
} DebugFrameFDE;
typedef struct {
DebugFrameCIE cie;
DebugFrameFDE fde;
DebugFrameFDEHeader fde;
uint8_t fde_def_cfa[4];
uint8_t fde_ret_ofs[3];
uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
} DebugFrame;
#define ELF_HOST_MACHINE EM_PARISC
@ -1806,16 +1789,18 @@ static DebugFrame debug_frame = {
.cie.data_align = 1,
.cie.return_column = 2,
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
.fde.def_cfa = {
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
0x12, 30, /* DW_CFA_def_cfa_sf sp, ... */
(-FRAME_SIZE & 0x7f) | 0x80, /* ... sleb128 -FRAME_SIZE */
(-FRAME_SIZE >> 7) & 0x7f
},
.fde.ret_ofs = {
.fde_ret_ofs = {
0x11, 2, (-20 / 4) & 0x7f /* DW_CFA_offset_extended_sf r2, 20 */
},
.fde.reg_ofs = {
.fde_reg_ofs = {
/* This must match the ordering in tcg_target_callee_save_regs. */
0x80 + 4, 0, /* DW_CFA_offset r4, 0 */
0x80 + 5, 4, /* DW_CFA_offset r5, 4 */

View File

@ -85,6 +85,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1

View File

@ -2311,30 +2311,16 @@ static void tcg_target_init(TCGContext *s)
tcg_add_target_add_op_defs(x86_op_defs);
}
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t id;
uint8_t version;
char augmentation[1];
uint8_t code_align;
uint8_t data_align;
uint8_t return_column;
} DebugFrameCIE;
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t cie_offset;
tcg_target_long func_start __attribute__((packed));
tcg_target_long func_len __attribute__((packed));
uint8_t def_cfa[4];
uint8_t reg_ofs[14];
} DebugFrameFDE;
typedef struct {
DebugFrameCIE cie;
DebugFrameFDE fde;
DebugFrameFDEHeader fde;
uint8_t fde_def_cfa[4];
uint8_t fde_reg_ofs[14];
} DebugFrame;
/* We're expecting a 2 byte uleb128 encoded value. */
QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
#if !defined(__ELF__)
/* Host machine without ELF. */
#elif TCG_TARGET_REG_BITS == 64
@ -2347,13 +2333,15 @@ static DebugFrame debug_frame = {
.cie.data_align = 0x78, /* sleb128 -8 */
.cie.return_column = 16,
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
.fde.def_cfa = {
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
12, 7, /* DW_CFA_def_cfa %rsp, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
.fde.reg_ofs = {
.fde_reg_ofs = {
0x90, 1, /* DW_CFA_offset, %rip, -8 */
/* The following ordering must match tcg_target_callee_save_regs. */
0x86, 2, /* DW_CFA_offset, %rbp, -16 */
@ -2374,13 +2362,15 @@ static DebugFrame debug_frame = {
.cie.data_align = 0x7c, /* sleb128 -4 */
.cie.return_column = 8,
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
.fde.def_cfa = {
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
12, 4, /* DW_CFA_def_cfa %esp, ... */
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
(FRAME_SIZE >> 7)
},
.fde.reg_ofs = {
.fde_reg_ofs = {
0x88, 1, /* DW_CFA_offset, %eip, -4 */
/* The following ordering must match tcg_target_callee_save_regs. */
0x85, 2, /* DW_CFA_offset, %ebp, -8 */
@ -2394,9 +2384,6 @@ static DebugFrame debug_frame = {
#if defined(ELF_HOST_MACHINE)
void tcg_register_jit(void *buf, size_t buf_size)
{
/* We're expecting a 2 byte uleb128 encoded value. */
assert(FRAME_SIZE >> 14 == 0);
debug_frame.fde.func_start = (tcg_target_long) buf;
debug_frame.fde.func_len = buf_size;

View File

@ -104,7 +104,9 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 0
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_andc_i32 1
#define TCG_TARGET_HAS_andc_i64 1
#define TCG_TARGET_HAS_bswap16_i32 1

View File

@ -79,6 +79,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_not_i32 1
#define TCG_TARGET_HAS_nor_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1

View File

@ -1671,18 +1671,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
break;
case INDEX_op_rem_i32:
tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_remu_i32:
tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_mulu2_i32:
if (args[0] == args[2] || args[0] == args[3]) {
tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
@ -1992,8 +1980,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i32, { "r", "r", "ri" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
{ INDEX_op_rem_i32, { "r", "r", "r" } },
{ INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
{ INDEX_op_sub_i32, { "r", "r", "ri" } },
{ INDEX_op_and_i32, { "r", "r", "ri" } },

View File

@ -78,6 +78,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1

View File

@ -1617,18 +1617,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
break;
case INDEX_op_rem_i32:
tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_remu_i32:
tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_shl_i32:
if (const_args[2]) {
tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]);
@ -1786,16 +1774,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_divu_i64:
tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2]));
break;
case INDEX_op_rem_i64:
tcg_out32 (s, DIVD | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_remu_i64:
tcg_out32 (s, DIVDU | TAB (0, args[1], args[2]));
tcg_out32 (s, MULLD | TAB (0, 0, args[2]));
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
break;
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld (s, args, 0);
@ -2064,8 +2042,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i32, { "r", "r", "rI" } },
{ INDEX_op_div_i32, { "r", "r", "r" } },
{ INDEX_op_divu_i32, { "r", "r", "r" } },
{ INDEX_op_rem_i32, { "r", "r", "r" } },
{ INDEX_op_remu_i32, { "r", "r", "r" } },
{ INDEX_op_sub_i32, { "r", "rI", "ri" } },
{ INDEX_op_and_i32, { "r", "r", "ri" } },
{ INDEX_op_or_i32, { "r", "r", "ri" } },
@ -2108,8 +2084,6 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_mul_i64, { "r", "r", "rI" } },
{ INDEX_op_div_i64, { "r", "r", "r" } },
{ INDEX_op_divu_i64, { "r", "r", "r" } },
{ INDEX_op_rem_i64, { "r", "r", "r" } },
{ INDEX_op_remu_i64, { "r", "r", "r" } },
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },

View File

@ -76,6 +76,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_rot_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
@ -96,6 +97,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1

View File

@ -1646,29 +1646,12 @@ static void tcg_target_init(TCGContext *s)
# define ELF_HOST_FLAGS EF_SPARC_32PLUS
#endif
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t id;
uint8_t version;
char augmentation[1];
uint8_t code_align;
uint8_t data_align;
uint8_t return_column;
} DebugFrameCIE;
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t cie_offset;
tcg_target_long func_start __attribute__((packed));
tcg_target_long func_len __attribute__((packed));
uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
uint8_t win_save;
uint8_t ret_save[3];
} DebugFrameFDE;
typedef struct {
DebugFrameCIE cie;
DebugFrameFDE fde;
DebugFrameFDEHeader fde;
uint8_t fde_def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
uint8_t fde_win_save;
uint8_t fde_ret_save[3];
} DebugFrame;
static DebugFrame debug_frame = {
@ -1679,8 +1662,10 @@ static DebugFrame debug_frame = {
.cie.data_align = -sizeof(void *) & 0x7f,
.cie.return_column = 15, /* o7 */
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
.fde.def_cfa = {
/* Total FDE size does not include the "len" member. */
.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
.fde_def_cfa = {
#if TCG_TARGET_REG_BITS == 64
12, 30, /* DW_CFA_def_cfa i6, 2047 */
(2047 & 0x7f) | 0x80, (2047 >> 7)
@ -1688,8 +1673,8 @@ static DebugFrame debug_frame = {
13, 30 /* DW_CFA_def_cfa_register i6 */
#endif
},
.fde.win_save = 0x2d, /* DW_CFA_GNU_window_save */
.fde.ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
.fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
.fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
};
void tcg_register_jit(void *buf, size_t buf_size)

View File

@ -86,6 +86,7 @@ typedef enum {
/* optional instructions */
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_rot_i32 0
#define TCG_TARGET_HAS_ext8s_i32 0
#define TCG_TARGET_HAS_ext16s_i32 0
@ -109,6 +110,7 @@ typedef enum {
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1
#define TCG_TARGET_HAS_rot_i64 0
#define TCG_TARGET_HAS_ext8s_i64 0
#define TCG_TARGET_HAS_ext16s_i64 0

View File

@ -731,8 +731,14 @@ static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
if (TCG_TARGET_HAS_div_i32) {
if (TCG_TARGET_HAS_rem_i32) {
tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2);
} else if (TCG_TARGET_HAS_div_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2);
tcg_gen_mul_i32(t0, t0, arg2);
tcg_gen_sub_i32(ret, arg1, t0);
tcg_temp_free_i32(t0);
} else if (TCG_TARGET_HAS_div2_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_sari_i32(t0, arg1, 31);
@ -769,8 +775,14 @@ static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
if (TCG_TARGET_HAS_div_i32) {
if (TCG_TARGET_HAS_rem_i32) {
tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2);
} else if (TCG_TARGET_HAS_div_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2);
tcg_gen_mul_i32(t0, t0, arg2);
tcg_gen_sub_i32(ret, arg1, t0);
tcg_temp_free_i32(t0);
} else if (TCG_TARGET_HAS_div2_i32) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_movi_i32(t0, 0);
@ -1361,8 +1373,14 @@ static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
if (TCG_TARGET_HAS_div_i64) {
if (TCG_TARGET_HAS_rem_i64) {
tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2);
} else if (TCG_TARGET_HAS_div_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2);
tcg_gen_mul_i64(t0, t0, arg2);
tcg_gen_sub_i64(ret, arg1, t0);
tcg_temp_free_i64(t0);
} else if (TCG_TARGET_HAS_div2_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_sari_i64(t0, arg1, 63);
@ -1399,8 +1417,14 @@ static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
{
if (TCG_TARGET_HAS_div_i64) {
if (TCG_TARGET_HAS_rem_i64) {
tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2);
} else if (TCG_TARGET_HAS_div_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2);
tcg_gen_mul_i64(t0, t0, arg2);
tcg_gen_sub_i64(ret, arg1, t0);
tcg_temp_free_i64(t0);
} else if (TCG_TARGET_HAS_div2_i64) {
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_movi_i64(t0, 0);

View File

@ -27,20 +27,24 @@
*/
/* predefined ops */
DEF(end, 0, 0, 0, 0) /* must be kept first */
DEF(nop, 0, 0, 0, 0)
DEF(nop1, 0, 0, 1, 0)
DEF(nop2, 0, 0, 2, 0)
DEF(nop3, 0, 0, 3, 0)
DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */
DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT)
DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT)
DEF(discard, 1, 0, 0, 0)
/* variable number of parameters */
DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)
/* variable number of parameters */
DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END)
DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) /* variable number of parameters */
DEF(br, 0, 0, 1, TCG_OPF_BB_END)
#define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT)
#define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0)
#if TCG_TARGET_REG_BITS == 32
# define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT
#else
@ -66,8 +70,8 @@ DEF(sub_i32, 1, 2, 0, 0)
DEF(mul_i32, 1, 2, 0, 0)
DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32))
DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32))
DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32))
DEF(and_i32, 1, 2, 0, 0)
@ -126,8 +130,8 @@ DEF(sub_i64, 1, 2, 0, IMPL64)
DEF(mul_i64, 1, 2, 0, IMPL64)
DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64))
DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64))
DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64))
DEF(and_i64, 1, 2, 0, IMPL64)
@ -166,9 +170,9 @@ DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64))
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
DEF(debug_insn_start, 0, 0, 2, 0)
DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
#else
DEF(debug_insn_start, 0, 0, 1, 0)
DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
#endif
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)

View File

@ -68,6 +68,24 @@ static void tcg_target_qemu_prologue(TCGContext *s);
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
/* The CIE and FDE header definitions will be common to all hosts. */
typedef struct {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t id;
uint8_t version;
char augmentation[1];
uint8_t code_align;
uint8_t data_align;
uint8_t return_column;
} DebugFrameCIE;
typedef struct QEMU_PACKED {
uint32_t len __attribute__((aligned((sizeof(void *)))));
uint32_t cie_offset;
tcg_target_long func_start;
tcg_target_long func_len;
} DebugFrameFDEHeader;
static void tcg_register_jit_int(void *buf, size_t size,
void *debug_frame, size_t debug_frame_size)
__attribute__((unused));
@ -1160,9 +1178,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
i = 0;
for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) {
const TCGOpDef *def = &tcg_op_defs[op];
if (op < INDEX_op_call
|| op == INDEX_op_debug_insn_start
|| (def->flags & TCG_OPF_NOT_PRESENT)) {
if (def->flags & TCG_OPF_NOT_PRESENT) {
/* Wrong entry in op definitions? */
if (def->used) {
fprintf(stderr, "Invalid op definition for %s\n", def->name);
@ -2659,9 +2675,9 @@ static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
img->sym[1].st_size = buf_size;
img->di.cu_low_pc = buf;
img->di.cu_high_pc = buf_size;
img->di.cu_high_pc = buf + buf_size;
img->di.fn_low_pc = buf;
img->di.fn_high_pc = buf_size;
img->di.fn_high_pc = buf + buf_size;
#ifdef DEBUG_JIT
/* Enable this block to be able to debug the ELF image file creation.

View File

@ -60,6 +60,7 @@ typedef uint64_t TCGRegSet;
#if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_div2_i64 0
#define TCG_TARGET_HAS_rot_i64 0
#define TCG_TARGET_HAS_ext8s_i64 0
@ -102,11 +103,13 @@ typedef uint64_t TCGRegSet;
#define TCG_TARGET_HAS_div2_i32 0
#elif defined(TCG_TARGET_HAS_div2_i32)
#define TCG_TARGET_HAS_div_i32 0
#define TCG_TARGET_HAS_rem_i32 0
#endif
#if defined(TCG_TARGET_HAS_div_i64)
#define TCG_TARGET_HAS_div2_i64 0
#elif defined(TCG_TARGET_HAS_div2_i64)
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#endif
typedef enum TCGOpcode {
@ -593,7 +596,8 @@ enum {
TCG_OPF_SIDE_EFFECTS = 0x04,
/* Instruction operands are 64-bits (otherwise 32-bits). */
TCG_OPF_64BIT = 0x08,
/* Instruction is optional and not implemented by the host. */
/* Instruction is optional and not implemented by the host, or insn
is generic and should not be implemened by the host. */
TCG_OPF_NOT_PRESENT = 0x10,
};

View File

@ -59,9 +59,8 @@
#define TCG_TARGET_HAS_bswap16_i32 1
#define TCG_TARGET_HAS_bswap32_i32 1
/* Not more than one of the next two defines must be 1. */
#define TCG_TARGET_HAS_div_i32 1
#define TCG_TARGET_HAS_div2_i32 0
#define TCG_TARGET_HAS_rem_i32 1
#define TCG_TARGET_HAS_ext8s_i32 1
#define TCG_TARGET_HAS_ext16s_i32 1
#define TCG_TARGET_HAS_ext8u_i32 1
@ -83,9 +82,8 @@
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
#define TCG_TARGET_HAS_deposit_i64 1
/* Not more than one of the next two defines must be 1. */
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_div2_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_ext8s_i64 1
#define TCG_TARGET_HAS_ext16s_i64 1
#define TCG_TARGET_HAS_ext32s_i64 1