diff mbox

[10/10] addr32: Add *zero_extendsidi2_x32.

Message ID 20120302211454.GB2559@intel.com
State New
Headers show

Commit Message

H.J. Lu March 2, 2012, 9:14 p.m. UTC
Hi,

This is the last patch for Pmode == SImod in x32. In x32, the return value
of the symbol address must be zero-extended to DImode, This patch adds
*zero_extendsidi2_x32 to load the address of a symbol in SImode and
zero-extend it to DImode. It works for x32 since the address size is 32bit.
OK for trunk?

Thanks.


H.J.
---
2012-03-02  H.J. Lu  <hongjiu.lu@intel.com>

	* config/i386/i386.md (*zero_extendsidi2_x32): New.
	* config/i386/predicates.md (x86_64_symbolic_immediate_operand):
	Likewise.
diff mbox

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 1595491..d008815 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3407,6 +3407,17 @@ 
    (set_attr "prefix_0f" "0,*,*,*,*,*")
    (set_attr "mode" "SI,DI,DI,DI,TI,TI")])
 
+(define_insn "*zero_extendsidi2_x32"
+  [(set (match_operand:DI 0 "register_operand"  "=r")
+	(zero_extend:DI
+	  (match_operand:SI 1 "x86_64_symbolic_immediate_operand" "")))]
+  "TARGET_X32"
+  "mov\t{%1, %k0|%k0, %1}"
+  [(set_attr "type" "imovx")
+   (set_attr "prefix" "orig")
+   (set_attr "prefix_0f" "0")
+   (set_attr "mode" "SI")])
+
 (define_split
   [(set (match_operand:DI 0 "memory_operand" "")
      	(zero_extend:DI (match_dup 0)))]
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 32f73da..21cf3bb 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -333,6 +333,53 @@ 
   return false;
 })
 
+;; Return true if OP is either a symbol reference or a sum of a symbol
+;; reference and a constant in x86-64 small mode, which can be stored
+;; in the zero extended immediate field.
+(define_predicate "x86_64_symbolic_immediate_operand"
+  (match_code "symbol_ref,const")
+{
+  /* Only small model is allowed.  */
+  if (ix86_cmodel != CM_SMALL)
+    return false;
+
+  switch (GET_CODE (op))
+    {
+    case SYMBOL_REF:
+      /* TLS symbols are not constant.  */
+      if (SYMBOL_REF_TLS_MODEL (op))
+	return false;
+      return true;
+
+    case CONST:
+      op = XEXP (op, 0);
+      if (GET_CODE (op) == PLUS)
+	{
+	  rtx op1 = XEXP (op, 0);
+	  rtx op2 = XEXP (op, 1);
+
+	  switch (GET_CODE (op1))
+	    {
+	    case SYMBOL_REF:
+	      /* TLS symbols are not constant.  */
+	      if (SYMBOL_REF_TLS_MODEL (op1))
+		return false;
+	      if (CONST_INT_P (op2))
+		return true;
+	      break;
+
+	    default:
+	      return false;
+	    }
+	}
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+  return false;
+})
+
 ;; Return true if OP is general operand representable on x86_64.
 (define_predicate "x86_64_general_operand"
   (if_then_else (match_test "TARGET_64BIT")