diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2b87045f22..90ab3876c38 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,17 @@ -Wed Mar 21 10:25:13 CET 2001 Jan Hubicka +Wed Mar 21 10:53:57 CET 2001 Jan Hubicka + + * i386.md (pushqi1): New. + * i386-protos.h (x86_64_general_operand, x86_64_szext_general_operand, + x86_64_nonmemory_operand, x86_64_szext_nonmemory_operand, + x86_64_immediate_operand, x86_64_immediate_operand, + x86_64_zext_immediate_operand): Declare. + * i386.c (x86_64_general_operand, x86_64_szext_general_operand, + x86_64_nonmemory_operand, x86_64_szext_nonmemory_operand, + x86_64_immediate_operand, x86_64_immediate_operand, + x86_64_zext_immediate_operand): define. + * i386.h (PREDICATE_CODES): Add new predicates. + +Wed Mar 21 10:25:13 CET 2001 Jan Hubicka * i386.md (pophi1, popqi1, pushqi1): Remove. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index e4639a34b61..aaa239491a3 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -43,6 +43,12 @@ extern int standard_80387_constant_p PARAMS ((rtx)); extern int standard_sse_constant_p PARAMS ((rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx)); +extern int x86_64_general_operand PARAMS ((rtx, enum machine_mode)); +extern int x86_64_szext_general_operand PARAMS ((rtx, enum machine_mode)); +extern int x86_64_nonmemory_operand PARAMS ((rtx, enum machine_mode)); +extern int x86_64_szext_nonmemory_operand PARAMS ((rtx, enum machine_mode)); +extern int x86_64_immediate_operand PARAMS ((rtx, enum machine_mode)); +extern int x86_64_zext_immediate_operand PARAMS ((rtx, enum machine_mode)); extern int const_int_1_operand PARAMS ((rtx, enum machine_mode)); extern int symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 20b7eca7eb5..91dee40cf96 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1127,6 +1127,101 @@ function_arg (cum, mode, type, named) } +/* Return nonzero if OP is general operand representable on x86_64. */ + +int +x86_64_general_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT) + return general_operand (op, mode); + if (nonimmediate_operand (op, mode)) + return 1; + return x86_64_sign_extended_value (op); +} + +/* Return nonzero if OP is general operand representable on x86_64 + as eighter sign extended or zero extended constant. */ + +int +x86_64_szext_general_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT) + return general_operand (op, mode); + if (nonimmediate_operand (op, mode)) + return 1; + return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op); +} + +/* Return nonzero if OP is nonmemory operand representable on x86_64. */ + +int +x86_64_nonmemory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT) + return nonmemory_operand (op, mode); + if (register_operand (op, mode)) + return 1; + return x86_64_sign_extended_value (op); +} + +/* Return nonzero if OP is nonmemory operand acceptable by movabs patterns. */ + +int +x86_64_movabs_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT || !flag_pic) + return nonmemory_operand (op, mode); + if (register_operand (op, mode) || x86_64_sign_extended_value (op)) + return 1; + if (CONSTANT_P (op) && !symbolic_reference_mentioned_p (op)) + return 1; + return 0; +} + +/* Return nonzero if OP is nonmemory operand representable on x86_64. */ + +int +x86_64_szext_nonmemory_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT) + return nonmemory_operand (op, mode); + if (register_operand (op, mode)) + return 1; + return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op); +} + +/* Return nonzero if OP is immediate operand representable on x86_64. */ + +int +x86_64_immediate_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + if (!TARGET_64BIT) + return immediate_operand (op, mode); + return x86_64_sign_extended_value (op); +} + +/* Return nonzero if OP is immediate operand representable on x86_64. */ + +int +x86_64_zext_immediate_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return x86_64_zero_extended_value (op); +} + /* Return nonzero if OP is (const_int 1), else return zero. */ int diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 02c6e2a03cc..697f2213fbe 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -3022,6 +3022,20 @@ do { long l; \ /* Define the codes that are matched by predicates in i386.c. */ #define PREDICATE_CODES \ + {"x86_64_immediate_operand", {CONST_INT, SUBREG, REG, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_nonmemory_operand", {CONST_INT, SUBREG, REG, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_movabs_operand", {CONST_INT, SUBREG, REG, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_szext_nonmemory_operand", {CONST_INT, SUBREG, REG, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_general_operand", {CONST_INT, SUBREG, REG, MEM, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_szext_general_operand", {CONST_INT, SUBREG, REG, MEM, \ + SYMBOL_REF, LABEL_REF, CONST}}, \ + {"x86_64_zext_immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, \ + SYMBOL_REF, LABEL_REF}}, \ {"const_int_1_operand", {CONST_INT}}, \ {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \ {"aligned_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 6eae78c567a..77392fe0e19 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1858,6 +1858,20 @@ "" "ix86_expand_move (QImode, operands); DONE;") +;; emit_push_insn when it calls move_by_pieces requires an insn to +;; "push a byte". But actually we use pushw, which has the effect +;; of rounding the amount pushed up to a halfword. + +(define_insn "*pushqi2" + [(set (match_operand:QI 0 "push_operand" "=X,X") + (match_operand:QI 1 "nonmemory_no_elim_operand" "n,r"))] + "!TARGET_64BIT" + "@ + push{w}\\t{|word ptr }%1 + push{w}\\t%w1" + [(set_attr "type" "push") + (set_attr "mode" "HI")]) + ;; Situation is quite tricky about when to choose full sized (SImode) move ;; over QImode moves. For Q_REG -> Q_REG move we use full size only for ;; partial register dependency machines (such as AMD Athlon), where QImode