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...@intel.com> * config/i386/i386.md (*zero_extendsidi2_x32): New. * config/i386/predicates.md (x86_64_symbolic_immediate_operand): Likewise. 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") -- 1.7.6.5