diff mbox

[05/10] tcg: add jr opcode

Message ID 1491959850-30756-6-git-send-email-cota@braap.org (mailing list archive)
State New, archived
Headers show

Commit Message

Emilio Cota April 12, 2017, 1:17 a.m. UTC
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(+)

Comments

Paolo Bonzini April 13, 2017, 5:09 a.m. UTC | #1
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
Richard Henderson April 15, 2017, 11:40 a.m. UTC | #2
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~
Emilio Cota April 16, 2017, 6:28 p.m. UTC | #3
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 mbox

Patch

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