Message ID | 1491959850-30756-6-git-send-email-cota@braap.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 12/04/2017 09:17, Emilio G. Cota wrote: > This will be used by TCG targets to implement a fast path > for indirect branches. > > I only have implemented and tested this on an i386 host, so > make this opcode optional and mark it as not implemented by > other TCG backends. Please don't forget to document this in tcg/README. Thanks, Paolo
On 04/11/2017 06:17 PM, Emilio G. Cota wrote: > This will be used by TCG targets to implement a fast path > for indirect branches. > > I only have implemented and tested this on an i386 host, so > make this opcode optional and mark it as not implemented by > other TCG backends. I don't think this is quite the right abstraction. In particular, if we can always return a valid address from the helper, we can eliminate a conditional branch. I think this should work as follows: (1) tb_ret_addr gets moved into TCGContext so that it's available for other code to see. (2) Have a generic helper void *HELPER(lookup_tb_ptr)(CPUArchState *env, target_ulong addr) { TranslationBlock *tb = tb_from_jmp_cache(env, addr); return tb ? tb->tc_ptr : tcg_ctx.tb_ret_addr; } (3) Emit TCG opcodes like call t0,lookup_tb_ptr,env,addr jmp_tb t0 (4) Emit code for jmp_tb like mov %rax,%rdx // save target into new register xor %eax,%eax // set return value a-la exit_tb jmp *%edx // branch to tb or epilogue. (5) There needs to be a convenience function in tcg/tcg-op.c. If the host does not support jmp_tb, we should just generate exit_tb like we do now. There should be no ifdefs inside target/*. r~
On Sat, Apr 15, 2017 at 04:40:35 -0700, Richard Henderson wrote: > On 04/11/2017 06:17 PM, Emilio G. Cota wrote: > >This will be used by TCG targets to implement a fast path > >for indirect branches. > > > >I only have implemented and tested this on an i386 host, so > >make this opcode optional and mark it as not implemented by > >other TCG backends. > > I don't think this is quite the right abstraction. In particular, if we can > always return a valid address from the helper, we can eliminate a > conditional branch. > > I think this should work as follows: (snip) Yes that's much better. In fact in the cover letter I forgot to mention that the code by the paper authors does something similar to avoid the branch. I went with the design with a branch because (1) I wasn't sure that exporting tb_ret_addr would get your approval and (2) my knowledge of TCG backend code is shamefully poor. Will work on a v2. Thanks for the feedback! Emilio
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 1a5ea23..ed2fb84 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -77,6 +77,7 @@ typedef enum { #define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extrh_i64_i32 0 +#define TCG_TARGET_HAS_jr 0 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rem_i64 1 diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 09a19c6..1c9f0a2 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -123,6 +123,7 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_div_i32 use_idiv_instructions #define TCG_TARGET_HAS_rem_i32 0 +#define TCG_TARGET_HAS_jr 0 enum { TCG_AREG0 = TCG_REG_R6, diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index 4275787..ebbddb3 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -107,6 +107,7 @@ extern bool have_popcnt; #define TCG_TARGET_HAS_muls2_i32 1 #define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_jr 1 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_extrl_i64_i32 0 diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index 5918008..53baf71 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -1909,6 +1909,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_br: tcg_out_jxx(s, JCC_JMP, arg_label(a0), 0); break; + case INDEX_op_jr: + tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, a0); + break; OP_32_64(ld8u): /* Note that we can ignore REXW for the zero-extend to 64-bit. */ tcg_out_modrm_offset(s, OPC_MOVZBL, a0, a1, a2); @@ -2277,6 +2280,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) { + static const TCGTargetOpDef ri = { .args_ct_str = { "ri" } }; static const TCGTargetOpDef ri_r = { .args_ct_str = { "ri", "r" } }; static const TCGTargetOpDef re_r = { .args_ct_str = { "re", "r" } }; static const TCGTargetOpDef qi_r = { .args_ct_str = { "qi", "r" } }; @@ -2324,6 +2328,9 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) case INDEX_op_st_i64: return &re_r; + case INDEX_op_jr: + return &ri; + case INDEX_op_add_i32: case INDEX_op_add_i64: return &r_r_re; diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 42aea03..a2760ba 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -173,6 +173,7 @@ typedef enum { #define TCG_TARGET_HAS_mulsh_i64 0 #define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extrh_i64_i32 0 +#define TCG_TARGET_HAS_jr 0 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16) #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16) diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index f46d64a..d06e495 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -130,6 +130,7 @@ extern bool use_mips32r2_instructions; #define TCG_TARGET_HAS_muluh_i32 1 #define TCG_TARGET_HAS_mulsh_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1 +#define TCG_TARGET_HAS_jr 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_add2_i32 0 diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index abd8b3d..461bb0c 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -82,6 +82,7 @@ extern bool have_isa_3_00; #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muluh_i32 1 #define TCG_TARGET_HAS_mulsh_i32 1 +#define TCG_TARGET_HAS_jr 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_add2_i32 0 diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index cbdd2a6..b35c7b1 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -92,6 +92,7 @@ extern uint64_t s390_facilities; #define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_extrl_i64_i32 0 #define TCG_TARGET_HAS_extrh_i64_i32 0 +#define TCG_TARGET_HAS_jr 0 #define TCG_TARGET_HAS_div2_i64 1 #define TCG_TARGET_HAS_rot_i64 1 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index b8b74f9..3d6f872 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -123,6 +123,7 @@ extern bool use_vis3_instructions; #define TCG_TARGET_HAS_muls2_i32 1 #define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_jr 0 #define TCG_TARGET_HAS_extrl_i64_i32 1 #define TCG_TARGET_HAS_extrh_i64_i32 1 diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index c68e300..1924633 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -261,6 +261,12 @@ static inline void tcg_gen_br(TCGLabel *l) tcg_gen_op1(&tcg_ctx, INDEX_op_br, label_arg(l)); } +/* jump to a host address contained in a register */ +static inline void tcg_gen_jr(TCGv_ptr arg) +{ + tcg_gen_op1i(INDEX_op_jr, GET_TCGV_PTR(arg)); +} + void tcg_gen_mb(TCGBar); /* Helper calls. */ diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index f06f894..1e869af 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -34,6 +34,7 @@ DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) DEF(call, 0, 0, 3, TCG_OPF_CALL_CLOBBER | TCG_OPF_NOT_PRESENT) DEF(br, 0, 0, 1, TCG_OPF_BB_END) +DEF(jr, 0, 1, 0, TCG_OPF_BB_END) #define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0) #if TCG_TARGET_REG_BITS == 32 diff --git a/tcg/tcg.c b/tcg/tcg.c index cb898f1..a7e7842 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1139,6 +1139,7 @@ void tcg_dump_ops(TCGContext *s) switch (c) { case INDEX_op_set_label: case INDEX_op_br: + case INDEX_op_jr: case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: case INDEX_op_brcond2_i32: diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 838bf3a..63d1a57 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -85,6 +85,7 @@ #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_jr 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_extrl_i64_i32 0
This will be used by TCG targets to implement a fast path for indirect branches. I only have implemented and tested this on an i386 host, so make this opcode optional and mark it as not implemented by other TCG backends. Signed-off-by: Emilio G. Cota <cota@braap.org> --- tcg/aarch64/tcg-target.h | 1 + tcg/arm/tcg-target.h | 1 + tcg/i386/tcg-target.h | 1 + tcg/i386/tcg-target.inc.c | 7 +++++++ tcg/ia64/tcg-target.h | 1 + tcg/mips/tcg-target.h | 1 + tcg/ppc/tcg-target.h | 1 + tcg/s390/tcg-target.h | 1 + tcg/sparc/tcg-target.h | 1 + tcg/tcg-op.h | 6 ++++++ tcg/tcg-opc.h | 1 + tcg/tcg.c | 1 + tcg/tci/tcg-target.h | 1 + 13 files changed, 24 insertions(+)