Patchwork tcg/i386: allow constants in load/store ops

login
register
mail settings
Submitter Aurelien Jarno
Date Sept. 10, 2012, 11:56 a.m.
Message ID <1347278184-18693-1-git-send-email-aurelien@aurel32.net>
Download mbox | patch
Permalink /patch/182858/
State New
Headers show

Comments

Aurelien Jarno - Sept. 10, 2012, 11:56 a.m.
On x86, it is possible to move a constant value to memory. Add code to
handle a constant argument to load/store ops.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
 tcg/i386/tcg-target.c |   50 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 13 deletions(-)
Richard Henderson - Sept. 10, 2012, 1:40 p.m.
On Mon, 2012-09-10 at 13:56 +0200, Aurelien Jarno wrote:
> On x86, it is possible to move a constant value to memory. Add code to
> handle a constant argument to load/store ops.
> 
> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> 

While useful, you'll find that most constants that want storing to
memory are not generated with store opcodes, but directly via
tcg_out_st.  As happens for all register spilling, and helper calls.

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~
Aurelien Jarno - Sept. 10, 2012, 1:57 p.m.
On Mon, Sep 10, 2012 at 06:40:09AM -0700, Richard Henderson wrote:
> On Mon, 2012-09-10 at 13:56 +0200, Aurelien Jarno wrote:
> > On x86, it is possible to move a constant value to memory. Add code to
> > handle a constant argument to load/store ops.
> > 
> > Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> 
> 
> While useful, you'll find that most constants that want storing to
> memory are not generated with store opcodes, but directly via
> tcg_out_st.  As happens for all register spilling, and helper calls.

It actually depends on the target. Some of them are not using that at
all, some of them are using that a lot.

Ideally we would need to also do that directly from TCG when storing
back registers to their canonical location, but we have to find a nice
clean to do it.

> Reviewed-by: Richard Henderson <rth@twiddle.net>
> 
> 
> r~
> 
>

Patch

diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index da17bba..c9e9b3a 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -265,6 +265,7 @@  static inline int tcg_target_const_match(tcg_target_long val,
 #define OPC_MOVB_EvGv	(0x88)		/* stores, more or less */
 #define OPC_MOVL_EvGv	(0x89)		/* stores, more or less */
 #define OPC_MOVL_GvEv	(0x8b)		/* loads, more or less */
+#define OPC_MOVB_EvIz   (0xc6)
 #define OPC_MOVL_EvIz	(0xc7)
 #define OPC_MOVL_Iv     (0xb8)
 #define OPC_MOVSBL	(0xbe | P_EXT)
@@ -1573,18 +1574,35 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     OP_32_64(st8):
-        tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
-                             args[0], args[1], args[2]);
+        if (const_args[0]) {
+            tcg_out_modrm_offset(s, OPC_MOVB_EvIz,
+                                 0, args[1], args[2]);
+            tcg_out8(s, args[0]);
+        } else {
+            tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
+                                 args[0], args[1], args[2]);
+        }
         break;
     OP_32_64(st16):
-        tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
-                             args[0], args[1], args[2]);
+        if (const_args[0]) {
+            tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_DATA16,
+                                 0, args[1], args[2]);
+            tcg_out16(s, args[0]);
+        } else {
+            tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+                                 args[0], args[1], args[2]);
+        }
         break;
 #if TCG_TARGET_REG_BITS == 64
     case INDEX_op_st32_i64:
 #endif
     case INDEX_op_st_i32:
-        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
+        if (const_args[0]) {
+            tcg_out_modrm_offset(s, OPC_MOVL_EvIz, 0, args[1], args[2]);
+            tcg_out32(s, args[0]);
+        } else {
+            tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
+        }
         break;
 
     OP_32_64(add):
@@ -1788,7 +1806,13 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
         break;
     case INDEX_op_st_i64:
-        tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+        if (const_args[0]) {
+            tcg_out_modrm_offset(s, OPC_MOVL_EvIz | P_REXW,
+                                 0, args[1], args[2]);
+            tcg_out32(s, args[0]);
+        } else {
+            tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+        }
         break;
     case INDEX_op_qemu_ld32s:
         tcg_out_qemu_ld(s, args, 2 | 4);
@@ -1850,9 +1874,9 @@  static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_ld16u_i32, { "r", "r" } },
     { INDEX_op_ld16s_i32, { "r", "r" } },
     { INDEX_op_ld_i32, { "r", "r" } },
-    { INDEX_op_st8_i32, { "q", "r" } },
-    { INDEX_op_st16_i32, { "r", "r" } },
-    { INDEX_op_st_i32, { "r", "r" } },
+    { INDEX_op_st8_i32, { "qi", "r" } },
+    { INDEX_op_st16_i32, { "ri", "r" } },
+    { INDEX_op_st_i32, { "ri", "r" } },
 
     { INDEX_op_add_i32, { "r", "r", "ri" } },
     { INDEX_op_sub_i32, { "r", "0", "ri" } },
@@ -1903,10 +1927,10 @@  static const TCGTargetOpDef x86_op_defs[] = {
     { INDEX_op_ld32u_i64, { "r", "r" } },
     { INDEX_op_ld32s_i64, { "r", "r" } },
     { INDEX_op_ld_i64, { "r", "r" } },
-    { INDEX_op_st8_i64, { "r", "r" } },
-    { INDEX_op_st16_i64, { "r", "r" } },
-    { INDEX_op_st32_i64, { "r", "r" } },
-    { INDEX_op_st_i64, { "r", "r" } },
+    { INDEX_op_st8_i64, { "ri", "r" } },
+    { INDEX_op_st16_i64, { "ri", "r" } },
+    { INDEX_op_st32_i64, { "ri", "r" } },
+    { INDEX_op_st_i64, { "re", "r" } },
 
     { INDEX_op_add_i64, { "r", "0", "re" } },
     { INDEX_op_mul_i64, { "r", "0", "re" } },