diff --git a/MAINTAINERS b/MAINTAINERS index 780f4807259ef8faf3dcd2a596cdc889e1e56687..93ad19d90efc3612b78cb1028d54a02426f2bd3b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -781,6 +781,7 @@ Tiny Code Generator (TCG) ------------------------- Common code M: qemu-devel@nongnu.org +M: Richard Henderson S: Maintained F: tcg/ diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 97e4a5baa7c6a21fb317d95df16ea2ab310c4bd1..51e50920b2cd6051196e2d36224aeb1552f67eab 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -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 diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 6be736b75e084c9a2fe16359470c3c6edbcf6d66..6c4854dbb0370603dc49df4a33c99f00a204ac8c 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -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 - -#if defined(USE_ARMV6_INSTRUCTIONS) || \ - defined(__ARM_ARCH_5T__) || \ - defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_5TEJ__) -#define USE_ARMV5_INSTRUCTIONS -#endif +static int arm_arch = __ARM_ARCH; -#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 #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)); +} diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 3be41cce3c16801f44531a0c83ebf0d2e49548c6..5cd9d6a6797244b52e3dceb7f07492b909cadb75 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -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 diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 656e73621a75bdaddaf57380db5db464d4e46dc4..68f77ba4ddbaa073e8946c6b0ea9fb23ca334341 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -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 */ diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index ebd53d9e3620bdcee65a5540694e238be77fdbf7..25467bdd43ed4a41de9736d06f3a169ee397eae4 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -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 diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 9e95477ef4c1b4e3df8612b96b5005605c630c09..87eeab3d301bf3d17214cc3e588e67a08ac82071 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -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; diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index e3d72ea52f130cbed0288c9ad3f2745e50a351fe..f32d5199cb0b1a504f95f202cfb9a4c229ddbc72 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -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 diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 6155327a9ab4ac83045dad3b8f19e2ec85c2ff18..a438950bc1c1d76c3184e05195ad233a36c1b9ab 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -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 diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 29ca934e66ef344b72b93272702479af0dea1a2c..453ab6b580954ccde713dfdd620b249dc036fb89 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -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" } }, diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 17a6bb367a4498bc68e3e135866ce5af31a9c4c0..b42d97cc2474119b022f507ab7c07c6c82993f56 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -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 diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 606b73defcfe4a347d7a42459050e66c9e511cb0..0678de20459096865324a449fb6269d9c46f54ac 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -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" } }, diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index cb77634714c2dcd51f6fb36525fe8e93c12335a8..48fc6e2e547219d0be7c9ec770fc4c3847d03a0e 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -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 diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 025af9b379906817fc2f500b102a69dc29587439..5bfd29c3b41935f53808f38f8b835abe2eca974c 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -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) diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index b5217bef25e641557144cf6abd5c7618372121b4..dab52d717683d686db3ebaf23c31652326f455d2 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -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 diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 94f6043786bbbb9b0fd2cfa721393ea6d13eda50..364964d8d4d2e0fd90e478fda90b65e3d3618d91 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -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); diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 4246e9c1fa6296c8f5e9ffac45e4593310c0a7e8..a8af5b96a4f349aa7eb4c232b8030bc8471785ab 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -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) diff --git a/tcg/tcg.c b/tcg/tcg.c index 1d8099cca8126ca93aac3d5f0c63ee03ee2d031c..dac8224024da514177b3b4027092280ae75e4696 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -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. diff --git a/tcg/tcg.h b/tcg/tcg.h index df375cf31e4c246df11695bf5b7bced94b4b2e8d..f3f988969454c394e0eb19e6b28c34447850c627 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -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, }; diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 0395bbb8e42e26b363fb04e3d1baf5e52b934731..d7fc14eb17b461a329aaafc081043c4092eacfdc 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -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