From: matt Date: Wed, 1 Apr 2009 17:00:00 +0000 (+0000) Subject: 2009-04-01 Jan-Benedict Glaw X-Git-Tag: upstream/4.9.2~37221 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6718899ef176db1d50db752655c02eddd962d1af;p=platform%2Fupstream%2Flinaro-gcc.git 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/vax.c: Add #includes to silence warnings. Change #include order to silence two warnings. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/linux.h (TARGET_DEFAULT): Add the MASK_QMATH flag bit. (ASM_SPEC): Pass -k to the assembler for PIC code. 2009-04-01 Jan-Benedict Glaw * gcc/config.gcc: Add vax-*-linux* to the switch. * gcc/config/vax/linux.h: New file. (TARGET_VERSION, TARGET_OS_CPP_BUILTINS, TARGET_DEFAULT, CPP_SPEC, LINK_SPEC): Define. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/vax.c (vax_output_int_move, adjacent_operands_p): Use predicate macros instead of GET_CODE() == foo. * gcc/config/vax/vax.md (movsi_2, movstrictqi, and3, ashrsi3, ashlsi3, rotrsi3, ): Likewise. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/builtins.md (jbbssiqi, jbbssihi, jbbssisi, jbbcciqi, jbbccihi, jbbccisi): Remova trailing whitespace. * gcc/config/vax/constraints.md: Likewise. * gcc/config/vax/elf.h: (ASM_PREFERRED_EH_DATA_FORMAT): Likewise. * gcc/config/vax/openbsd1.h (OBSD_OLD_GAS): Likewise. * gcc/config/vax/predicates.md: Likewise. * gcc/config/vax/vax.c (print_operand_address, vax_output_int_move, vax_expand_addsub_di_operands, adjacent_operands_p): Likewise. * gcc/config/vax/vax.h: Likewise. * gcc/config/vax/vax.md (nonlocal_goto): Likewise. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/vax.c (vax_float_literal, vax_output_int_move) (indirectable_address_p, adjacent_operands_p): Add spaces around braces. * gcc/config/vax/vax-protos.h (adjacent_operands_p): Likewise. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/vax.c (legitimate_constant_address_p, legitimate_constant_p, indirectable_address_p, nonindexed_address_p, index_term_p, reg_plus_index_p, legitimate_address_p, vax_mode_dependent_address_p): Update comments to match functions modified by the recent int->bool conversion. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/builtins.md: Update copyright message. * gcc/config/vax/constraints.md: Likewise. * gcc/config/vax/netbsd-elf.h: Likewise. * gcc/config/vax/predicates.md: Likewise. * gcc/config/vax/vax-protos.h: Likewise. * gcc/config/vax/vax.c: Likewise. * gcc/config/vax/vax.h: Likewise. * gcc/config/vax/vax.md: Likewise. * gcc/config/vax/vax.opt: Likewise. 2009-04-01 Jan-Benedict Glaw * gcc/config/vax/builtins.md (ffssi2, ffssi2_internal, sync_lock_test_and_set, sync_lock_release): Fix indention. * gcc/config/vax/constraints.md (B, R): Likewise. * gcc/config/vax/predicates.md (external_memory_operand, nonimmediate_addsub_di_operand): Likewise. * gcc/config/vax/vax.c (vax_output_int_add): Likewise. * gcc/config/vax/vax.md (movsi, movsi_2, mov, call_value, untyped_call): Likewise. 2009-04-01 Matt Thomas * config/vax/predicates.md: New file. (symbolic_operand, local_symbolic_operand, external_symbolic_operand, external_const_operand, nonsymbolic_operand, external_memory_operand, indirect_memory_operand, indexed_memory_operand, illegal_blk_memory_operand, illegal_addsub_di_memory_operand, nonimmediate_addsub_di_operand, general_addsub_di_operand): New predicate. * config/vax/constraints.md: New file. (Z0, U06, U08, U16, CN6, S08, S16, I, J, K, L, M, N, O, G, Q, B, R, T): New constraint. * config/vax/builtins.md: New file. (ffssi2, ffssi2_internal, sync_lock_test_and_set, jbbssiqi, jbbssihi, jbbssisi, sync_lock_release, jbbcciqi, jbbccihi, jbbccisi): Define. * config/vax/vax.opt (mqmath): Add option. * config/vax/vax.md (isfx): Extend with DI. (VAXintQH, VAXintQHSD): Define. (tst, cmp, *bit, movmemhi1, truncsiqi2, truncsihi2, mulsidi3, add3, sub, mul3, div3, and, and_const_int, ior3, xor3, neg2, one_cmpl2, ashlsi3, lshrsi3, rotlsi3): Update constraints. (movdi): Update constraints and use vax_output_int_move(). (movsi, movsi_2, pushlclsymreg, pushextsymreg, movlclsymreg, movextsymreg, adddi3, adcdi3, subdi3, sbcdi3, pushextsym, movextsym, pushlclsym, movlclsym, movaddr, pushaddr, nonlocal_goto): New. (mov): Extend accepted operand types. (subdi3_old): Rename from subdi3, change update constraints and use a new implementation. * gcc/config/vax/vax.h (PCC_BITFIELD_TYPE_MATTERS): Add space. (FRAME_POINTER_CFA_OFFSET, IRA_COVER_CLASSES, CLASS_MAX_NREGS, MOVE_RATIO, CLEAR_RATIO): Define. (REG_CLASS_FROM_LETTER, CONST_OK_FOR_LETTER_P, CONST_DOUBLE_OK_FOR_LETTER_P, EXTRA_CONSTRAINT): Delete. (PRINT_OPERAND): Redefine using a function instead of inlined code. * gcc/config/vax/vax.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Define. (split_quadword_operands): Make static and really allow variable splitting. (print_operand_address): Update for PIC generation. (print_operand, vax_builtin_setjmp_frame_value, vax_output_int_subtract, indexable_address_p, fixup_mathdi_operand, vax_expand_addsub_di_operands, adjacent_operands_p): New. (vax_float_literal, legitimate_constant_p, indirectable_constant_address_p, index_term_p, reg_plus_index_p): Return bool instead of int. (vax_rtx_costs): Fix cost for CONST_INT, indent and use HOST_WIDE_INT where needed. (vax_output_int_move, vax_output_int_add): Extend to allow PIC generation. (vax_output_conditional_branch): Indent. (legitimate_constant_address_p, indirectable_constant_address_p, indirectable_address_p, nonindexed_address_p, legitimate_address_p, vax_mode_dependent_address_p): Return bool instead of int, update for PIC generation. * config/vax/vax-protos.h (legitimate_constant_address_p, legitimate_constant_p, legitimate_address_p, vax_mode_dependent_address_p): Change declaration to bool. (legitimate_pic_operand_p, adjacent_operands_p, print_operand, vax_expand_addsub_di_operands, vax_output_int_subtract, vax_output_movmemsi): Declare. (split_quadword_operands, vax_float_literal): Delete declaration. * config/vax/netbsd-elf.h (CC1_SPEC, CC1PLUS_SPEC) Define. * config/vax/elf.h (NO_EXTERNAL_INDIRECT_ADDRESS, VAX_CC1_AND_CC1PLUS_SPEC, ASM_PREFERRED_EH_DATA_FORMAT, ASM_OUTPUT_DWARF_PCREL): Define. (ASM_SPEC): Change definition to allow PIC generation. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145416 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f26fe7..d907434 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,144 @@ +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/vax.c: Add #includes to silence warnings. + Change #include order to silence two warnings. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/linux.h (TARGET_DEFAULT): Add the MASK_QMATH flag bit. + (ASM_SPEC): Pass -k to the assembler for PIC code. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config.gcc: Add vax-*-linux* to the switch. + * gcc/config/vax/linux.h: New file. (TARGET_VERSION, + TARGET_OS_CPP_BUILTINS, TARGET_DEFAULT, CPP_SPEC, LINK_SPEC): Define. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/vax.c (vax_output_int_move, adjacent_operands_p): + Use predicate macros instead of GET_CODE() == foo. + * gcc/config/vax/vax.md (movsi_2, movstrictqi, and3, ashrsi3, + ashlsi3, rotrsi3, ): Likewise. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/builtins.md (jbbssiqi, jbbssihi, jbbssisi, jbbcciqi, + jbbccihi, jbbccisi): Remova trailing whitespace. + * gcc/config/vax/constraints.md: Likewise. + * gcc/config/vax/elf.h: (ASM_PREFERRED_EH_DATA_FORMAT): Likewise. + * gcc/config/vax/openbsd1.h (OBSD_OLD_GAS): Likewise. + * gcc/config/vax/predicates.md: Likewise. + * gcc/config/vax/vax.c (print_operand_address, vax_output_int_move, + vax_expand_addsub_di_operands, adjacent_operands_p): Likewise. + * gcc/config/vax/vax.h: Likewise. + * gcc/config/vax/vax.md (nonlocal_goto): Likewise. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/vax.c (vax_float_literal, vax_output_int_move) + (indirectable_address_p, adjacent_operands_p): Add spaces around + braces. + * gcc/config/vax/vax-protos.h (adjacent_operands_p): Likewise. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/vax.c (legitimate_constant_address_p, + legitimate_constant_p, indirectable_address_p, nonindexed_address_p, + index_term_p, reg_plus_index_p, legitimate_address_p, + vax_mode_dependent_address_p): Update comments to match functions + modified by the recent int->bool conversion. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/builtins.md: Update copyright message. + * gcc/config/vax/constraints.md: Likewise. + * gcc/config/vax/netbsd-elf.h: Likewise. + * gcc/config/vax/predicates.md: Likewise. + * gcc/config/vax/vax-protos.h: Likewise. + * gcc/config/vax/vax.c: Likewise. + * gcc/config/vax/vax.h: Likewise. + * gcc/config/vax/vax.md: Likewise. + * gcc/config/vax/vax.opt: Likewise. + +2009-04-01 Jan-Benedict Glaw + + * gcc/config/vax/builtins.md (ffssi2, ffssi2_internal, + sync_lock_test_and_set, sync_lock_release): Fix indention. + * gcc/config/vax/constraints.md (B, R): Likewise. + * gcc/config/vax/predicates.md (external_memory_operand, + nonimmediate_addsub_di_operand): Likewise. + * gcc/config/vax/vax.c (vax_output_int_add): Likewise. + * gcc/config/vax/vax.md (movsi, movsi_2, mov, call_value, + untyped_call): Likewise. + +2009-04-01 Matt Thomas + + * config/vax/predicates.md: New file. (symbolic_operand, + local_symbolic_operand, external_symbolic_operand, + external_const_operand, nonsymbolic_operand, external_memory_operand, + indirect_memory_operand, indexed_memory_operand, + illegal_blk_memory_operand, illegal_addsub_di_memory_operand, + nonimmediate_addsub_di_operand, general_addsub_di_operand): New + predicate. + * config/vax/constraints.md: New file. (Z0, U06, U08, U16, CN6, S08, + S16, I, J, K, L, M, N, O, G, Q, B, R, T): New constraint. + * config/vax/builtins.md: New file. (ffssi2, ffssi2_internal, + sync_lock_test_and_set, jbbssiqi, jbbssihi, jbbssisi, + sync_lock_release, jbbcciqi, jbbccihi, jbbccisi): Define. + * config/vax/vax.opt (mqmath): Add option. + * config/vax/vax.md (isfx): Extend with DI. + (VAXintQH, VAXintQHSD): Define. + (tst, cmp, *bit, movmemhi1, truncsiqi2, truncsihi2, + mulsidi3, add3, sub, mul3, div3, and, + and_const_int, ior3, xor3, neg2, + one_cmpl2, ashlsi3, lshrsi3, rotlsi3): Update constraints. + (movdi): Update constraints and use vax_output_int_move(). + (movsi, movsi_2, pushlclsymreg, pushextsymreg, movlclsymreg, + movextsymreg, adddi3, adcdi3, subdi3, sbcdi3, pushextsym, movextsym, + pushlclsym, movlclsym, movaddr, pushaddr, + nonlocal_goto): New. + (mov): Extend accepted operand types. + (subdi3_old): Rename from subdi3, change update constraints and use + a new implementation. + * gcc/config/vax/vax.h (PCC_BITFIELD_TYPE_MATTERS): Add space. + (FRAME_POINTER_CFA_OFFSET, IRA_COVER_CLASSES, CLASS_MAX_NREGS, + MOVE_RATIO, CLEAR_RATIO): Define. + (REG_CLASS_FROM_LETTER, CONST_OK_FOR_LETTER_P, + CONST_DOUBLE_OK_FOR_LETTER_P, EXTRA_CONSTRAINT): Delete. + (PRINT_OPERAND): Redefine using a function instead of inlined code. + * gcc/config/vax/vax.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Define. + (split_quadword_operands): Make static and really allow variable + splitting. + (print_operand_address): Update for PIC generation. + (print_operand, vax_builtin_setjmp_frame_value, vax_output_int_subtract, + indexable_address_p, fixup_mathdi_operand, + vax_expand_addsub_di_operands, adjacent_operands_p): New. + (vax_float_literal, legitimate_constant_p, + indirectable_constant_address_p, index_term_p, + reg_plus_index_p): Return bool instead of int. + (vax_rtx_costs): Fix cost for CONST_INT, indent and use HOST_WIDE_INT + where needed. + (vax_output_int_move, vax_output_int_add): Extend to allow PIC + generation. + (vax_output_conditional_branch): Indent. + (legitimate_constant_address_p, indirectable_constant_address_p, + indirectable_address_p, nonindexed_address_p, legitimate_address_p, + vax_mode_dependent_address_p): Return bool instead of int, update for + PIC generation. + * config/vax/vax-protos.h (legitimate_constant_address_p, + legitimate_constant_p, legitimate_address_p, + vax_mode_dependent_address_p): Change declaration to bool. + (legitimate_pic_operand_p, adjacent_operands_p, print_operand, + vax_expand_addsub_di_operands, vax_output_int_subtract, + vax_output_movmemsi): Declare. + (split_quadword_operands, vax_float_literal): Delete declaration. + * config/vax/netbsd-elf.h (CC1_SPEC, CC1PLUS_SPEC) Define. + * config/vax/elf.h (NO_EXTERNAL_INDIRECT_ADDRESS, + VAX_CC1_AND_CC1PLUS_SPEC, ASM_PREFERRED_EH_DATA_FORMAT, + ASM_OUTPUT_DWARF_PCREL): Define. + (ASM_SPEC): Change definition to allow PIC generation. + 2009-04-01 Jakub Jelinek PR target/39226 diff --git a/gcc/config.gcc b/gcc/config.gcc index 5617065..cf8c91b 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2351,6 +2351,9 @@ v850-*-*) cxx_target_objs="v850-c.o" use_gcc_stdint=wrap ;; +vax-*-linux*) + tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h vax/elf.h vax/linux.h" + ;; vax-*-netbsdelf*) tm_file="${tm_file} elfos.h netbsd.h netbsd-elf.h vax/elf.h vax/netbsd-elf.h" ;; diff --git a/gcc/config/vax/builtins.md b/gcc/config/vax/builtins.md new file mode 100644 index 0000000..389526b --- /dev/null +++ b/gcc/config/vax/builtins.md @@ -0,0 +1,192 @@ +;; builtin definitions for DEC VAX. +;; Copyright (C) 2007, 2009 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free +;; Software Foundation; either version 3, or (at your option) any later +;; version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY; without even the implied warranty of MERCHANTABILITY or +;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +;; for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_constants + [ + (VUNSPEC_LOCK 100) ; sync lock and test + (VUNSPEC_UNLOCK 101) ; sync lock release + ] +) + +(define_expand "ffssi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (ffs:SI (match_operand:SI 1 "general_operand" "")))] + "" + " +{ + rtx label = gen_label_rtx (); + emit_insn (gen_ffssi2_internal (operands[0], operands[1])); + emit_jump_insn (gen_bne (label)); + emit_insn (gen_negsi2 (operands[0], const1_rtx)); + emit_label (label); + emit_insn (gen_addsi3 (operands[0], operands[0], const1_rtx)); + DONE; +}") + +(define_insn "ffssi2_internal" + [(set (match_operand:SI 0 "nonimmediate_operand" "=rQ") + (ffs:SI (match_operand:SI 1 "general_operand" "nrmT"))) + (set (cc0) (match_dup 0))] + "" + "ffs $0,$32,%1,%0") + +(define_expand "sync_lock_test_and_set" + [(set (match_operand:VAXint 0 "nonimmediate_operand" "=&g") + (unspec:VAXint [(match_operand:VAXint 1 "memory_operand" "+m") + (match_operand:VAXint 2 "const_int_operand" "n") + ] VUNSPEC_LOCK))] + "" + " +{ + rtx label; + + if (operands[2] != const1_rtx) + FAIL; + + label = gen_label_rtx (); + emit_move_insn (operands[0], const1_rtx); + emit_jump_insn (gen_jbbssi (operands[1], const0_rtx, label, operands[1])); + emit_move_insn (operands[0], const0_rtx); + emit_label (label); + DONE; +}") + +(define_insn "jbbssiqi" + [(parallel + [(set (pc) + (if_then_else + (ne (zero_extract:SI (match_operand:QI 0 "memory_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:QI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 1))])] + "" + "jbssi %1,%0,%l2") + +(define_insn "jbbssihi" + [(parallel + [(set (pc) + (if_then_else + (ne (zero_extract:SI (match_operand:HI 0 "memory_operand" "Q") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:HI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 1))])] + "" + "jbssi %1,%0,%l2") + +(define_insn "jbbssisi" + [(parallel + [(set (pc) + (if_then_else + (ne (zero_extract:SI (match_operand:SI 0 "memory_operand" "Q") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:SI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 1))])] + "" + "jbssi %1,%0,%l2") + + +(define_expand "sync_lock_release" + [(set (match_operand:VAXint 0 "memory_operand" "+m") + (unspec:VAXint [(match_operand:VAXint 1 "const_int_operand" "n") + ] VUNSPEC_UNLOCK))] + "" + " +{ + rtx label; + if (operands[1] != const0_rtx) + FAIL; +#if 1 + label = gen_label_rtx (); + emit_jump_insn (gen_jbbcci (operands[0], const0_rtx, label, operands[0])); + emit_label (label); +#else + emit_move_insn (operands[0], const0_rtx); +#endif + DONE; +}") + +(define_insn "jbbcciqi" + [(parallel + [(set (pc) + (if_then_else + (eq (zero_extract:SI (match_operand:QI 0 "memory_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:QI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 0))])] + "" + "jbcci %1,%0,%l2") + +(define_insn "jbbccihi" + [(parallel + [(set (pc) + (if_then_else + (eq (zero_extract:SI (match_operand:HI 0 "memory_operand" "Q") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:HI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 0))])] + "" + "jbcci %1,%0,%l2") + +(define_insn "jbbccisi" + [(parallel + [(set (pc) + (if_then_else + (eq (zero_extract:SI (match_operand:SI 0 "memory_operand" "Q") + (const_int 1) + (match_operand:SI 1 "general_operand" "nrm")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (zero_extract:SI (match_operand:SI 3 "memory_operand" "+0") + (const_int 1) + (match_dup 1)) + (const_int 0))])] + "" + "jbcci %1,%0,%l2") + diff --git a/gcc/config/vax/constraints.md b/gcc/config/vax/constraints.md new file mode 100644 index 0000000..e3266f6 --- /dev/null +++ b/gcc/config/vax/constraints.md @@ -0,0 +1,117 @@ +;; Constraints for the DEC VAX port. +;; Copyright (C) 2007, 2009 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free +;; Software Foundation; either version 3, or (at your option) any later +;; version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY; without even the implied warranty of MERCHANTABILITY or +;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +;; for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . */ + +(define_constraint "Z0" + "Match a CONST_INT of 0" + (and (match_code "const_int") + (match_test "ival == 0"))) + +(define_constraint "U06" + "unsigned 6 bit value (0..63)" + (and (match_code "const_int") + (match_test "0 <= ival && ival < 64"))) + +(define_constraint "U08" + "Unsigned 8 bit value" + (and (match_code "const_int") + (match_test "0 <= ival && ival < 256"))) + +(define_constraint "U16" + "Unsigned 16 bit value" + (and (match_code "const_int") + (match_test "0 <= ival && ival < 65536"))) + +(define_constraint "CN6" + "negative 6 bit value (-63..-1)" + (and (match_code "const_int") + (match_test "-63 <= ival && ival < 0"))) + +(define_constraint "S08" + "signed 8 bit value [old]" + (and (match_code "const_int") + (match_test "-128 <= ival && ival < 128"))) + +(define_constraint "S16" + "signed 16 bit value [old]" + (and (match_code "const_int") + (match_test "-32768 <= ival && ival < 32768"))) + +(define_constraint "I" + "Match a CONST_INT of 0 [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_Z0 (GEN_INT (ival))"))) + +(define_constraint "J" + "unsigned 6 bit value [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_U06 (GEN_INT (ival))"))) + +(define_constraint "K" + "signed 8 bit value [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_S08 (GEN_INT (ival))"))) + +(define_constraint "L" + "signed 16 bit value [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_S16 (GEN_INT (ival))"))) + +(define_constraint "M" + "Unsigned 8 bit value [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_U08 (GEN_INT (ival))"))) + +(define_constraint "N" + "Unsigned 16 bit value [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_U16 (GEN_INT (ival))"))) + +(define_constraint "O" + "Negative short literals (-63..-1) [old]" + (and (match_code "const_int") + (match_test "satisfies_constraint_CN6 (GEN_INT (ival))"))) + +/* Similar, but for floating constants, and defining letters G and H. */ + +(define_constraint "G" + "Match a floating-point zero" + (and (match_code "const_double") + (match_test "op == CONST0_RTX (DFmode) || op == CONST0_RTX (SFmode)"))) + +/* Optional extra constraints for this machine. */ + +(define_memory_constraint "Q" + "operand is a MEM that does not have a mode-dependent address." + (and (match_code "mem") + (match_test "!mode_dependent_address_p (XEXP (op, 0))"))) + +(define_memory_constraint "B" + "" + (and (match_operand:BLK 0 "memory_operand") + (not (match_operand:BLK 0 "illegal_blk_memory_operand" "")))) + +(define_memory_constraint "R" + "" + (and (match_operand:DI 0 "memory_operand") + (not (match_operand:DI 0 "illegal_addsub_di_memory_operand" "")))) + +(define_constraint "T" + "@internal satisfies CONSTANT_P and, if pic is enabled, is not a SYMBOL_REF, LABEL_REF, or CONST." + (ior (not (match_code "const,symbol_ref,label_ref")) + (match_test "!flag_pic"))) diff --git a/gcc/config/vax/elf.h b/gcc/config/vax/elf.h index 1efb1f0..c7b3d21 100644 --- a/gcc/config/vax/elf.h +++ b/gcc/config/vax/elf.h @@ -85,8 +85,29 @@ along with GCC; see the file COPYING3. If not see } \ while (0) +/* Don't allow *foo which foo is non-local */ +#define NO_EXTERNAL_INDIRECT_ADDRESS + +#undef VAX_CC1_AND_CC1PLUS_SPEC +#define VAX_CC1_AND_CC1PLUS_SPEC \ + "%{!fno-pic: \ + %{!fpic: \ + %{!fPIC:-fPIC}}}" + /* VAX ELF is always gas; override the generic VAX ASM_SPEC. */ #undef ASM_SPEC -#define ASM_SPEC "" - +#define ASM_SPEC "%{!fno-pic: %{!mno-asm-pic:-k}}" + +/* We want PCREL dwarf output. */ +#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ + ((GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4) + +/* Emit a PC-relative relocation. */ +#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \ + do { \ + fputs (integer_asm_op (SIZE, FALSE), FILE); \ + fprintf (FILE, "%%pcrel%d(", SIZE * 8); \ + assemble_name (FILE, LABEL); \ + fputc (')', FILE); \ + } while (0) diff --git a/gcc/config/vax/linux.h b/gcc/config/vax/linux.h new file mode 100644 index 0000000..af8ebe9 --- /dev/null +++ b/gcc/config/vax/linux.h @@ -0,0 +1,54 @@ +/* Definitions for VAX running Linux-based GNU systems with ELF format. + Copyright (C) 2007 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (VAX GNU/Linux with ELF)"); + +#define TARGET_OS_CPP_BUILTINS() \ + do \ + { \ + LINUX_TARGET_OS_CPP_BUILTINS(); \ + if (flag_pic) \ + { \ + builtin_define ("__PIC__"); \ + builtin_define ("__pic__"); \ + } \ + } \ + while (0) + +/* We use GAS, G-float double and want new DI patterns. */ +#undef TARGET_DEFAULT +#define TARGET_DEFAULT (MASK_QMATH | MASK_G_FLOAT) + +#undef CPP_SPEC +#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" + +#undef ASM_SPEC +#define ASM_SPEC "%{fpic|fPIC:-k}" + +#undef LINK_SPEC +#define LINK_SPEC \ + "%(endian_spec) \ + %{shared:-shared} \ + %{!shared: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \ + %{static:-static}}" diff --git a/gcc/config/vax/netbsd-elf.h b/gcc/config/vax/netbsd-elf.h index ed71b5a..6ba9249 100644 --- a/gcc/config/vax/netbsd-elf.h +++ b/gcc/config/vax/netbsd-elf.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for NetBSD/vax ELF systems. - Copyright (C) 2002, 2007 Free Software Foundation, Inc. + Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -30,10 +30,16 @@ along with GCC; see the file COPYING3. If not see #undef CPP_SPEC #define CPP_SPEC NETBSD_CPP_SPEC +#undef CC1_SPEC +#define CC1_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1_AND_CC1PLUS_SPEC + +#undef CC1PLUS_SPEC +#define CC1PLUS_SPEC NETBSD_CC1_AND_CC1PLUS_SPEC VAX_CC1_AND_CC1PLUS_SPEC + #define NETBSD_ENTRY_POINT "__start" #undef LINK_SPEC -#if 1 +#if 0 /* FIXME: We must link all executables statically until PIC support is added to the compiler. */ #define LINK_SPEC \ @@ -55,5 +61,4 @@ along with GCC; see the file COPYING3. If not see /* We use gas, not the UNIX assembler. */ #undef TARGET_DEFAULT -#define TARGET_DEFAULT 0 - +#define TARGET_DEFAULT MASK_QMATH diff --git a/gcc/config/vax/openbsd1.h b/gcc/config/vax/openbsd1.h index a1dd549..84b90e5 100644 --- a/gcc/config/vax/openbsd1.h +++ b/gcc/config/vax/openbsd1.h @@ -18,5 +18,5 @@ along with GCC; see the file COPYING3. If not see . */ /* Set up definitions before picking up the common openbsd.h file. */ -#define OBSD_OLD_GAS +#define OBSD_OLD_GAS #define OBSD_NO_DYNAMIC_LIBRARIES diff --git a/gcc/config/vax/predicates.md b/gcc/config/vax/predicates.md new file mode 100644 index 0000000..775ddcd --- /dev/null +++ b/gcc/config/vax/predicates.md @@ -0,0 +1,111 @@ +;; Predicate definitions for DEC VAX. +;; Copyright (C) 2007, 2009 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free +;; Software Foundation; either version 3, or (at your option) any later +;; version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY; without even the implied warranty of MERCHANTABILITY or +;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +;; for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +;; Special case of a symbolic operand that's used as a +;; operand. + +(define_predicate "symbolic_operand" + (match_code "const,symbol_ref,label_ref")) + +(define_predicate "local_symbolic_operand" + (match_code "const,symbol_ref,label_ref") +{ + if (GET_CODE (op) == LABEL_REF) + return 1; + if (GET_CODE (op) == SYMBOL_REF) + return !flag_pic || SYMBOL_REF_LOCAL_P (op); + if (GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF) + return 1; + return !flag_pic || SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0)); +}) + +(define_predicate "external_symbolic_operand" + (and (match_code "symbol_ref") + (not (match_operand 0 "local_symbolic_operand" "")))) + +(define_predicate "external_const_operand" + (and (match_code "const") + (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (op, 0), 0))"))) + +(define_predicate "nonsymbolic_operand" + (and (ior (match_test "!flag_pic") + (not (match_operand 0 "symbolic_operand"))) + (match_operand 0 "general_operand" ""))) + +(define_predicate "external_memory_operand" + (match_code "mem") +{ + rtx addr = XEXP (op, 0); + if (MEM_P (addr)) + addr = XEXP (addr, 0); + if (GET_CODE (addr) == PLUS) + addr = XEXP (addr, 1); + if (MEM_P (addr)) + addr = XEXP (addr, 0); + if (GET_CODE (addr) == PLUS) + addr = XEXP (addr, 1); + return external_symbolic_operand (addr, SImode) + || external_const_operand (addr, SImode); +}) + +(define_predicate "indirect_memory_operand" + (match_code "mem") +{ + op = XEXP (op, 0); + if (MEM_P (op)) + return 1; + if (GET_CODE (op) == PLUS) + op = XEXP (op, 1); + return MEM_P (op); +}) + +(define_predicate "indexed_memory_operand" + (match_code "mem") +{ + op = XEXP (op, 0); + return GET_CODE (op) != PRE_DEC && GET_CODE (op) != POST_INC + && mode_dependent_address_p (op); +}) + +(define_predicate "illegal_blk_memory_operand" + (and (match_code "mem") + (ior (and (match_test "flag_pic") + (match_operand 0 "external_memory_operand" "")) + (ior (match_operand 0 "indexed_memory_operand" "") + (ior (match_operand 0 "indirect_memory_operand" "") + (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")))))) + +(define_predicate "illegal_addsub_di_memory_operand" + (and (match_code "mem") + (ior (and (match_test "flag_pic") + (match_operand 0 "external_memory_operand" "")) + (ior (match_operand 0 "indexed_memory_operand" "") + (ior (match_operand 0 "indirect_memory_operand" "") + (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")))))) + +(define_predicate "nonimmediate_addsub_di_operand" + (and (match_code "subreg,reg,mem") + (and (match_operand:DI 0 "nonimmediate_operand" "") + (not (match_operand:DI 0 "illegal_addsub_di_memory_operand"))))) + +(define_predicate "general_addsub_di_operand" + (and (match_code "const_int,const_double,subreg,reg,mem") + (and (match_operand:DI 0 "general_operand" "") + (not (match_operand:DI 0 "illegal_addsub_di_memory_operand"))))) diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h index f466efa..9b43d4f 100644 --- a/gcc/config/vax/vax-protos.h +++ b/gcc/config/vax/vax-protos.h @@ -1,5 +1,5 @@ /* Definitions of target machine for GNU compiler. VAX version. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -19,20 +19,24 @@ along with GCC; see the file COPYING3. If not see extern void override_options (void); -extern int legitimate_constant_address_p (rtx); -extern int legitimate_constant_p (rtx); -extern int legitimate_address_p (enum machine_mode, rtx, int); -extern int vax_mode_dependent_address_p (rtx); +extern bool legitimate_constant_address_p (rtx); +extern bool legitimate_constant_p (rtx); +extern bool legitimate_pic_operand_p (rtx); +extern bool legitimate_address_p (enum machine_mode, rtx, bool); +extern bool vax_mode_dependent_address_p (rtx); #ifdef RTX_CODE +extern bool adjacent_operands_p (rtx, rtx, enum machine_mode); extern const char *rev_cond_name (rtx); -extern void split_quadword_operands (rtx *, rtx *, int); extern void print_operand_address (FILE *, rtx); -extern int vax_float_literal (rtx); +extern void print_operand (FILE *, rtx, int); extern void vax_notice_update_cc (rtx, rtx); +extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code); extern const char * vax_output_int_move (rtx, rtx *, enum machine_mode); extern const char * vax_output_int_add (rtx, rtx *, enum machine_mode); +extern const char * vax_output_int_subtract (rtx, rtx *, enum machine_mode); extern const char * vax_output_conditional_branch (enum rtx_code); +extern const char * vax_output_movmemsi (rtx, rtx *); #endif /* RTX_CODE */ #ifdef REAL_VALUE_TYPE diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c index eae2d19..e916969 100644 --- a/gcc/config/vax/vax.c +++ b/gcc/config/vax/vax.c @@ -1,6 +1,6 @@ /* Subroutines for insn-output.c for VAX. Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, - 2004, 2005, 2006, 2007, 2008 + 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" +#include "df.h" #include "tree.h" #include "regs.h" #include "hard-reg-set.h" @@ -39,6 +40,8 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "debug.h" #include "toplev.h" +#include "tm-preds.h" +#include "tm-constrs.h" #include "tm_p.h" #include "target.h" #include "target-def.h" @@ -52,6 +55,7 @@ static int vax_address_cost_1 (rtx); static int vax_address_cost (rtx, bool); static bool vax_rtx_costs (rtx, int, int, int *, bool); static rtx vax_struct_value_rtx (tree, int); +static rtx vax_builtin_setjmp_frame_value (void); /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -87,6 +91,9 @@ static rtx vax_struct_value_rtx (tree, int); #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX vax_struct_value_rtx +#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE +#define TARGET_BUILTIN_SETJMP_FRAME_VALUE vax_builtin_setjmp_frame_value + struct gcc_target targetm = TARGET_INITIALIZER; /* Set global variables as needed for the options enabled. */ @@ -167,27 +174,34 @@ vax_init_libfuncs (void) /* This is like nonimmediate_operand with a restriction on the type of MEM. */ -void -split_quadword_operands (rtx * operands, rtx * low, int n ATTRIBUTE_UNUSED) +static void +split_quadword_operands (rtx insn, enum rtx_code code, rtx * operands, + rtx * low, int n) { int i; - /* Split operands. */ - low[0] = low[1] = low[2] = 0; - for (i = 0; i < 3; i++) + for (i = 0; i < n; i++) + low[i] = 0; + + for (i = 0; i < n; i++) { - if (low[i]) - /* it's already been figured out */; - else if (MEM_P (operands[i]) - && (GET_CODE (XEXP (operands[i], 0)) == POST_INC)) + if (MEM_P (operands[i]) + && (GET_CODE (XEXP (operands[i], 0)) == PRE_DEC + || GET_CODE (XEXP (operands[i], 0)) == POST_INC)) { rtx addr = XEXP (operands[i], 0); operands[i] = low[i] = gen_rtx_MEM (SImode, addr); - if (which_alternative == 0 && i == 0) - { - addr = XEXP (operands[i], 0); - operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr); - } + } + else if (optimize_size && MEM_P (operands[i]) + && REG_P (XEXP (operands[i], 0)) + && (code != MINUS || operands[1] != const0_rtx) + && find_regno_note (insn, REG_DEAD, + REGNO (XEXP (operands[i], 0)))) + { + low[i] = gen_rtx_MEM (SImode, + gen_rtx_POST_INC (Pmode, + XEXP (operands[i], 0))); + operands[i] = gen_rtx_MEM (SImode, XEXP (operands[i], 0)); } else { @@ -200,6 +214,7 @@ split_quadword_operands (rtx * operands, rtx * low, int n ATTRIBUTE_UNUSED) void print_operand_address (FILE * file, rtx addr) { + rtx orig = addr; rtx reg1, breg, ireg; rtx offset; @@ -344,7 +359,11 @@ print_operand_address (FILE * file, rtx addr) /* If REG1 is nonzero, figure out if it is a base or index register. */ if (reg1) { - if (breg != 0 || (offset && MEM_P (offset))) + if (breg + || (flag_pic && GET_CODE (addr) == SYMBOL_REF) + || (offset + && (MEM_P (offset) + || (flag_pic && symbolic_operand (offset, SImode))))) { gcc_assert (!ireg); ireg = reg1; @@ -354,7 +373,36 @@ print_operand_address (FILE * file, rtx addr) } if (offset != 0) - output_address (offset); + { + if (flag_pic && symbolic_operand (offset, SImode)) + { + if (breg && ireg) + { + debug_rtx (orig); + output_operand_lossage ("symbol used with both base and indexed registers"); + } + +#ifdef NO_EXTERNAL_INDIRECT_ADDRESS + if (flag_pic > 1 && GET_CODE (offset) == CONST + && GET_CODE (XEXP (XEXP (offset, 0), 0)) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (offset, 0), 0))) + { + debug_rtx (orig); + output_operand_lossage ("symbol with offset used in PIC mode"); + } +#endif + + /* symbol(reg) isn't PIC, but symbol[reg] is. */ + if (breg) + { + ireg = breg; + breg = 0; + } + + } + + output_address (offset); + } if (breg != 0) fprintf (file, "(%s)", reg_names[REGNO (breg)]); @@ -372,6 +420,64 @@ print_operand_address (FILE * file, rtx addr) output_addr_const (file, addr); } } + +void +print_operand (FILE *file, rtx x, int code) +{ + if (code == '#') + fputc (ASM_DOUBLE_CHAR, file); + else if (code == '|') + fputs (REGISTER_PREFIX, file); + else if (code == 'C') + fputs (rev_cond_name (x), file); + else if (code == 'D' && CONST_INT_P (x) && INTVAL (x) < 0) + fprintf (file, "$" NEG_HWI_PRINT_HEX16, INTVAL (x)); + else if (code == 'P' && CONST_INT_P (x)) + fprintf (file, "$" HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + 1); + else if (code == 'N' && CONST_INT_P (x)) + fprintf (file, "$" HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (x)); + /* rotl instruction cannot deal with negative arguments. */ + else if (code == 'R' && CONST_INT_P (x)) + fprintf (file, "$" HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (x)); + else if (code == 'H' && CONST_INT_P (x)) + fprintf (file, "$%d", (int) (0xffff & ~ INTVAL (x))); + else if (code == 'h' && CONST_INT_P (x)) + fprintf (file, "$%d", (short) - INTVAL (x)); + else if (code == 'B' && CONST_INT_P (x)) + fprintf (file, "$%d", (int) (0xff & ~ INTVAL (x))); + else if (code == 'b' && CONST_INT_P (x)) + fprintf (file, "$%d", (int) (0xff & - INTVAL (x))); + else if (code == 'M' && CONST_INT_P (x)) + fprintf (file, "$%d", ~((1 << INTVAL (x)) - 1)); + else if (REG_P (x)) + fprintf (file, "%s", reg_names[REGNO (x)]); + else if (MEM_P (x)) + output_address (XEXP (x, 0)); + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) + { + char dstr[30]; + real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), + sizeof (dstr), 0, 1); + fprintf (file, "$0f%s", dstr); + } + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) + { + char dstr[30]; + real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), + sizeof (dstr), 0, 1); + fprintf (file, "$0%c%s", ASM_DOUBLE_CHAR, dstr); + } + else + { + if (flag_pic > 1 && symbolic_operand (x, SImode)) + { + debug_rtx (x); + output_operand_lossage ("symbol used as immediate operand"); + } + putc ('$', file); + output_addr_const (file, x); + } +} const char * rev_cond_name (rtx op) @@ -404,22 +510,22 @@ rev_cond_name (rtx op) } } -int -vax_float_literal(rtx c) +static bool +vax_float_literal (rtx c) { enum machine_mode mode; REAL_VALUE_TYPE r, s; int i; if (GET_CODE (c) != CONST_DOUBLE) - return 0; + return false; mode = GET_MODE (c); if (c == const_tiny_rtx[(int) mode][0] || c == const_tiny_rtx[(int) mode][1] || c == const_tiny_rtx[(int) mode][2]) - return 1; + return true; REAL_VALUE_FROM_CONST_DOUBLE (r, c); @@ -430,13 +536,13 @@ vax_float_literal(rtx c) REAL_VALUE_FROM_INT (s, x, 0, mode); if (REAL_VALUES_EQUAL (r, s)) - return 1; + return true; ok = exact_real_inverse (mode, &s); gcc_assert (ok); if (REAL_VALUES_EQUAL (r, s)) - return 1; + return true; } - return 0; + return false; } @@ -550,10 +656,13 @@ vax_rtx_costs (rtx x, int code, int outer_code, int *total, patterns will not match). */ case CONST_INT: if (INTVAL (x) == 0) - return true; + { + *total = 0; + return true; + } if (outer_code == AND) { - *total = ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2; + *total = ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2; return true; } if ((unsigned HOST_WIDE_INT) INTVAL (x) <= 077 @@ -577,7 +686,7 @@ vax_rtx_costs (rtx x, int code, int outer_code, int *total, if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) *total = vax_float_literal (x) ? 5 : 8; else - *total = ((CONST_DOUBLE_HIGH (x) == 0 + *total = ((CONST_DOUBLE_HIGH (x) == 0 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x) < 64) || (outer_code == PLUS && CONST_DOUBLE_HIGH (x) == -1 @@ -783,7 +892,7 @@ vax_rtx_costs (rtx x, int code, int outer_code, int *total, else { if (CONST_DOUBLE_HIGH (op) != 0 - || (unsigned)CONST_DOUBLE_LOW (op) > 63) + || (unsigned HOST_WIDE_INT)CONST_DOUBLE_LOW (op) > 63) *total += 2; } break; @@ -812,10 +921,10 @@ vax_rtx_costs (rtx x, int code, int outer_code, int *total, static void vax_output_mi_thunk (FILE * file, - tree thunk ATTRIBUTE_UNUSED, - HOST_WIDE_INT delta, - HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, - tree function) + tree thunk ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, + HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, + tree function) { fprintf (file, "\t.word 0x0ffc\n\taddl2 $" HOST_WIDE_INT_PRINT_DEC, delta); asm_fprintf (file, ",4(%Rap)\n"); @@ -831,6 +940,12 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM); } +static rtx +vax_builtin_setjmp_frame_value (void) +{ + return hard_frame_pointer_rtx; +} + /* Worker function for NOTICE_UPDATE_CC. */ void @@ -906,28 +1021,161 @@ const char * vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands, enum machine_mode mode) { + rtx hi[3], lo[3]; + const char *pattern_hi, *pattern_lo; + switch (mode) { + case DImode: + if (operands[1] == const0_rtx) + return "clrq %0"; + if (TARGET_QMATH && optimize_size + && (CONST_INT_P (operands[1]) + || GET_CODE (operands[1]) == CONST_DOUBLE)) + { + unsigned HOST_WIDE_INT hval, lval; + int n; + + if (GET_CODE (operands[1]) == CONST_DOUBLE) + { + gcc_assert (HOST_BITS_PER_WIDE_INT != 64); + + /* Make sure only the low 32 bits are valid. */ + lval = CONST_DOUBLE_LOW (operands[1]) & 0xffffffff; + hval = CONST_DOUBLE_HIGH (operands[1]) & 0xffffffff; + } + else + { + lval = INTVAL (operands[1]); + hval = 0; + } + + /* Here we see if we are trying to see if the 64bit value is really + a 6bit shifted some arbitrary amount. If so, we can use ashq to + shift it to the correct value saving 7 bytes (1 addr-mode-byte + + 8 bytes - 1 shift byte - 1 short literal byte. */ + if (lval != 0 + && (n = exact_log2 (lval & (- lval))) != -1 + && (lval >> n) < 64) + { + lval >>= n; + +#if HOST_BITS_PER_WIDE_INT == 32 + /* On 32bit platforms, if the 6bits didn't overflow into the + upper 32bit value that value better be 0. If we have + overflowed, make sure it wasn't too much. */ + if (hval != 0) + { + if (n <= 26 || hval >= ((unsigned)1 << (n - 26))) + n = 0; /* failure */ + else + lval |= hval << (32 - n); + } +#endif + /* If n is 0, then ashq is not the best way to emit this. */ + if (n > 0) + { + operands[1] = GEN_INT (lval); + operands[2] = GEN_INT (n); + return "ashq %2,%1,%0"; + } +#if HOST_BITS_PER_WIDE_INT == 32 + } + /* On 32bit platforms, if the low 32bit value is 0, checkout the + upper 32bit value. */ + else if (hval != 0 + && (n = exact_log2 (hval & (- hval)) - 1) != -1 + && (hval >> n) < 64) + { + operands[1] = GEN_INT (hval >> n); + operands[2] = GEN_INT (n + 32); + return "ashq %2,%1,%0"; +#endif + } + } + + if (TARGET_QMATH + && (!MEM_P (operands[0]) + || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC + || GET_CODE (XEXP (operands[0], 0)) == POST_INC + || !illegal_addsub_di_memory_operand (operands[0], DImode)) + && ((CONST_INT_P (operands[1]) + && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64) + || GET_CODE (operands[1]) == CONST_DOUBLE)) + { + hi[0] = operands[0]; + hi[1] = operands[1]; + + split_quadword_operands (insn, SET, hi, lo, 2); + + pattern_lo = vax_output_int_move (NULL, lo, SImode); + pattern_hi = vax_output_int_move (NULL, hi, SImode); + + /* The patterns are just movl/movl or pushl/pushl then a movq will + be shorter (1 opcode byte + 1 addrmode byte + 8 immediate value + bytes .vs. 2 opcode bytes + 2 addrmode bytes + 8 immediate value + value bytes. */ + if ((!strncmp (pattern_lo, "movl", 4) + && !strncmp (pattern_hi, "movl", 4)) + || (!strncmp (pattern_lo, "pushl", 5) + && !strncmp (pattern_hi, "pushl", 5))) + return "movq %1,%0"; + + if (MEM_P (operands[0]) + && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + output_asm_insn (pattern_hi, hi); + operands[0] = lo[0]; + operands[1] = lo[1]; + operands[2] = lo[2]; + return pattern_lo; + } + else + { + output_asm_insn (pattern_lo, lo); + operands[0] = hi[0]; + operands[1] = hi[1]; + operands[2] = hi[2]; + return pattern_hi; + } + } + return "movq %1,%0"; + case SImode: - if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) + if (symbolic_operand (operands[1], SImode)) { if (push_operand (operands[0], SImode)) return "pushab %a1"; return "movab %a1,%0"; } + if (operands[1] == const0_rtx) - return "clrl %0"; + { + if (push_operand (operands[1], SImode)) + return "pushl %1"; + return "clrl %0"; + } + if (CONST_INT_P (operands[1]) - && (unsigned) INTVAL (operands[1]) >= 64) + && (unsigned HOST_WIDE_INT) INTVAL (operands[1]) >= 64) { - int i = INTVAL (operands[1]); - if ((unsigned)(~i) < 64) + HOST_WIDE_INT i = INTVAL (operands[1]); + int n; + if ((unsigned HOST_WIDE_INT)(~i) < 64) return "mcoml %N1,%0"; - if ((unsigned)i < 0x100) + if ((unsigned HOST_WIDE_INT)i < 0x100) return "movzbl %1,%0"; if (i >= -0x80 && i < 0) return "cvtbl %1,%0"; - if ((unsigned)i < 0x10000) + if (optimize_size + && (n = exact_log2 (i & (-i))) != -1 + && ((unsigned HOST_WIDE_INT)i >> n) < 64) + { + operands[1] = GEN_INT ((unsigned HOST_WIDE_INT)i >> n); + operands[2] = GEN_INT (n); + return "ashl %2,%1,%0"; + } + if ((unsigned HOST_WIDE_INT)i < 0x10000) return "movzwl %1,%0"; if (i >= -0x8000 && i < 0) return "cvtwl %1,%0"; @@ -939,25 +1187,27 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands, case HImode: if (CONST_INT_P (operands[1])) { - int i = INTVAL (operands[1]); + HOST_WIDE_INT i = INTVAL (operands[1]); if (i == 0) return "clrw %0"; - else if ((unsigned int)i < 64) + else if ((unsigned HOST_WIDE_INT)i < 64) return "movw %1,%0"; - else if ((unsigned int)~i < 64) + else if ((unsigned HOST_WIDE_INT)~i < 64) return "mcomw %H1,%0"; - else if ((unsigned int)i < 256) + else if ((unsigned HOST_WIDE_INT)i < 256) return "movzbw %1,%0"; + else if (i >= -0x80 && i < 0) + return "cvtbw %1,%0"; } return "movw %1,%0"; case QImode: if (CONST_INT_P (operands[1])) { - int i = INTVAL (operands[1]); + HOST_WIDE_INT i = INTVAL (operands[1]); if (i == 0) return "clrb %0"; - else if ((unsigned int)~i < 64) + else if ((unsigned HOST_WIDE_INT)~i < 64) return "mcomb %B1,%0"; } return "movb %1,%0"; @@ -982,11 +1232,96 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands, which are not modified very often. */ const char * -vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, - enum machine_mode mode) +vax_output_int_add (rtx insn, rtx *operands, enum machine_mode mode) { switch (mode) { + case DImode: + { + rtx low[3]; + const char *pattern; + int carry = 1; + bool sub; + + if (TARGET_QMATH && 0) + debug_rtx (insn); + + split_quadword_operands (insn, PLUS, operands, low, 3); + + if (TARGET_QMATH) + { + gcc_assert (rtx_equal_p (operands[0], operands[1])); +#ifdef NO_EXTERNAL_INDIRECT_ADDRESSS + gcc_assert (!flag_pic || !external_memory_operand (low[2], SImode)); + gcc_assert (!flag_pic || !external_memory_operand (low[0], SImode)); +#endif + + /* No reason to add a 0 to the low part and thus no carry, so just + emit the appropriate add/sub instruction. */ + if (low[2] == const0_rtx) + return vax_output_int_add (NULL, operands, SImode); + + /* Are we doing addition or subtraction? */ + sub = CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0; + + /* We can't use vax_output_int_add since some the patterns don't + modify the carry bit. */ + if (sub) + { + if (low[2] == constm1_rtx) + pattern = "decl %0"; + else + pattern = "subl2 $%n2,%0"; + } + else + { + if (low[2] == const1_rtx) + pattern = "incl %0"; + else + pattern = "addl2 %2,%0"; + } + output_asm_insn (pattern, low); + + /* In 2's complement, -n = ~n + 1. Since we are dealing with + two 32bit parts, we complement each and then add one to + low part. We know that the low part can't overflow since + it's value can never be 0. */ + if (sub) + return "sbwc %N2,%0"; + return "adwc %2,%0"; + } + + /* Add low parts. */ + if (rtx_equal_p (operands[0], operands[1])) + { + if (low[2] == const0_rtx) + /* Should examine operand, punt if not POST_INC. */ + pattern = "tstl %0", carry = 0; + else if (low[2] == const1_rtx) + pattern = "incl %0"; + else + pattern = "addl2 %2,%0"; + } + else + { + if (low[2] == const0_rtx) + pattern = "movl %1,%0", carry = 0; + else + pattern = "addl3 %2,%1,%0"; + } + if (pattern) + output_asm_insn (pattern, low); + if (!carry) + /* If CARRY is 0, we don't have any carry value to worry about. */ + return get_insn_template (CODE_FOR_addsi3, insn); + /* %0 = C + %1 + %2 */ + if (!rtx_equal_p (operands[0], operands[1])) + output_asm_insn ((operands[1] == const0_rtx + ? "clrl %0" + : "movl %1,%0"), operands); + return "adwc %2,%0"; + } + case SImode: if (rtx_equal_p (operands[0], operands[1])) { @@ -995,19 +1330,25 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, if (operands[2] == constm1_rtx) return "decl %0"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subl2 $%n2,%0"; if (CONST_INT_P (operands[2]) - && (unsigned) INTVAL (operands[2]) >= 64 + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 64 && REG_P (operands[1]) && ((INTVAL (operands[2]) < 32767 && INTVAL (operands[2]) > -32768) || REGNO (operands[1]) > 11)) return "movab %c2(%1),%0"; + if (REG_P (operands[0]) && symbolic_operand (operands[2], SImode)) + return "movab %a2[%0],%0"; return "addl2 %2,%0"; } if (rtx_equal_p (operands[0], operands[2])) - return "addl2 %1,%0"; + { + if (REG_P (operands[0]) && symbolic_operand (operands[1], SImode)) + return "movab %a1[%0],%0"; + return "addl2 %1,%0"; + } if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32767 @@ -1017,11 +1358,11 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, return "pushab %c2(%1)"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subl3 $%n2,%1,%0"; if (CONST_INT_P (operands[2]) - && (unsigned) INTVAL (operands[2]) >= 64 + && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 64 && REG_P (operands[1]) && ((INTVAL (operands[2]) < 32767 && INTVAL (operands[2]) > -32768) || REGNO (operands[1]) > 11)) @@ -1031,6 +1372,30 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, if (REG_P (operands[1]) && REG_P (operands[2])) return "movab (%1)[%2],%0"; */ + + if (REG_P (operands[1]) && symbolic_operand (operands[2], SImode)) + { + if (push_operand (operands[0], SImode)) + return "pushab %a2[%1]"; + return "movab %a2[%1],%0"; + } + + if (REG_P (operands[2]) && symbolic_operand (operands[1], SImode)) + { + if (push_operand (operands[0], SImode)) + return "pushab %a1[%2]"; + return "movab %a1[%2],%0"; + } + + if (flag_pic && REG_P (operands[0]) + && symbolic_operand (operands[2], SImode)) + return "movab %a2,%0;addl2 %1,%0"; + + if (flag_pic + && (symbolic_operand (operands[1], SImode) + || symbolic_operand (operands[1], SImode))) + debug_rtx (insn); + return "addl3 %1,%2,%0"; case HImode: @@ -1041,14 +1406,14 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, if (operands[2] == constm1_rtx) return "decw %0"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subw2 $%n2,%0"; return "addw2 %2,%0"; } if (rtx_equal_p (operands[0], operands[2])) return "addw2 %1,%0"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subw3 $%n2,%1,%0"; return "addw3 %1,%2,%0"; @@ -1060,14 +1425,14 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, if (operands[2] == constm1_rtx) return "decb %0"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subb2 $%n2,%0"; return "addb2 %2,%0"; } if (rtx_equal_p (operands[0], operands[2])) return "addb2 %1,%0"; if (CONST_INT_P (operands[2]) - && (unsigned) (- INTVAL (operands[2])) < 64) + && (unsigned HOST_WIDE_INT) (- INTVAL (operands[2])) < 64) return "subb3 $%n2,%1,%0"; return "addb3 %1,%2,%0"; @@ -1076,6 +1441,81 @@ vax_output_int_add (rtx insn ATTRIBUTE_UNUSED, rtx *operands, } } +const char * +vax_output_int_subtract (rtx insn, rtx *operands, enum machine_mode mode) +{ + switch (mode) + { + case DImode: + { + rtx low[3]; + const char *pattern; + int carry = 1; + + if (TARGET_QMATH && 0) + debug_rtx (insn); + + split_quadword_operands (insn, MINUS, operands, low, 3); + + if (TARGET_QMATH) + { + if (operands[1] == const0_rtx && low[1] == const0_rtx) + { + /* Negation is tricky. It's basically complement and increment. + Negate hi, then lo, and subtract the carry back. */ + if ((MEM_P (low[0]) && GET_CODE (XEXP (low[0], 0)) == POST_INC) + || (MEM_P (operands[0]) + && GET_CODE (XEXP (operands[0], 0)) == POST_INC)) + fatal_insn ("illegal operand detected", insn); + output_asm_insn ("mnegl %2,%0", operands); + output_asm_insn ("mnegl %2,%0", low); + return "sbwc $0,%0"; + } + gcc_assert (rtx_equal_p (operands[0], operands[1])); + gcc_assert (rtx_equal_p (low[0], low[1])); + if (low[2] == const1_rtx) + output_asm_insn ("decl %0", low); + else + output_asm_insn ("subl2 %2,%0", low); + return "sbwc %2,%0"; + } + + /* Subtract low parts. */ + if (rtx_equal_p (operands[0], operands[1])) + { + if (low[2] == const0_rtx) + pattern = 0, carry = 0; + else if (low[2] == constm1_rtx) + pattern = "decl %0"; + else + pattern = "subl2 %2,%0"; + } + else + { + if (low[2] == constm1_rtx) + pattern = "decl %0"; + else if (low[2] == const0_rtx) + pattern = get_insn_template (CODE_FOR_movsi, insn), carry = 0; + else + pattern = "subl3 %2,%1,%0"; + } + if (pattern) + output_asm_insn (pattern, low); + if (carry) + { + if (!rtx_equal_p (operands[0], operands[1])) + return "movl %1,%0;sbwc %2,%0"; + return "sbwc %2,%0"; + /* %0 = %2 - %1 - C */ + } + return get_insn_template (CODE_FOR_subsi3, insn); + } + + default: + gcc_unreachable (); + } +} + /* Output a conditional branch. */ const char * vax_output_conditional_branch (enum rtx_code code) @@ -1093,27 +1533,36 @@ vax_output_conditional_branch (enum rtx_code code) case GEU: return "jgequ %l0"; case LEU: return "jlequ %l0"; default: - gcc_unreachable (); + gcc_unreachable (); } } -/* 1 if X is an rtx for a constant that is a valid address. */ +/* True if X is an rtx for a constant that is a valid address. */ -int +bool legitimate_constant_address_p (rtx x) { - return (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF - || CONST_INT_P (x) || GET_CODE (x) == CONST - || GET_CODE (x) == HIGH); + if (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF + || CONST_INT_P (x) || GET_CODE (x) == HIGH) + return true; + if (GET_CODE (x) != CONST) + return false; +#ifdef NO_EXTERNAL_INDIRECT_ADDRESS + if (flag_pic + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0))) + return false; +#endif + return true; } -/* Nonzero if the constant value X is a legitimate general operand. +/* True if the constant value X is a legitimate general operand. It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ -int +bool legitimate_constant_p (rtx x ATTRIBUTE_UNUSED) { - return 1; + return true; } /* The other macros defined here are used only in legitimate_address_p (). */ @@ -1133,78 +1582,78 @@ legitimate_constant_p (rtx x ATTRIBUTE_UNUSED) /* Re-definition of CONSTANT_ADDRESS_P, which is true only when there are no SYMBOL_REFs for external symbols present. */ -static int -indirectable_constant_address_p (rtx x) +static bool +indirectable_constant_address_p (rtx x, bool indirect) { - if (!CONSTANT_ADDRESS_P (x)) - return 0; - if (GET_CODE (x) == CONST && GET_CODE (XEXP ((x), 0)) == PLUS) - x = XEXP (XEXP (x, 0), 0); - if (GET_CODE (x) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (x)) - return 0; - - return 1; + if (GET_CODE (x) == SYMBOL_REF) + return !flag_pic || SYMBOL_REF_LOCAL_P (x) || !indirect; + + if (GET_CODE (x) == CONST) + return !flag_pic + || GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF + || SYMBOL_REF_LOCAL_P (XEXP (XEXP (x, 0), 0)); + + return CONSTANT_ADDRESS_P (x); } #else /* not NO_EXTERNAL_INDIRECT_ADDRESS */ -static int -indirectable_constant_address_p (rtx x) +static bool +indirectable_constant_address_p (rtx x, bool indirect ATTRIBUTE_UNUSED) { return CONSTANT_ADDRESS_P (x); } #endif /* not NO_EXTERNAL_INDIRECT_ADDRESS */ -/* Nonzero if X is an address which can be indirected. External symbols +/* True if X is an address which can be indirected. External symbols could be in a sharable image library, so we disallow those. */ -static int -indirectable_address_p(rtx x, int strict) +static bool +indirectable_address_p (rtx x, bool strict, bool indirect) { - if (indirectable_constant_address_p (x)) - return 1; - if (BASE_REGISTER_P (x, strict)) - return 1; - if (GET_CODE (x) == PLUS - && BASE_REGISTER_P (XEXP (x, 0), strict) - && indirectable_constant_address_p (XEXP (x, 1))) - return 1; - return 0; + if (indirectable_constant_address_p (x, indirect) + || BASE_REGISTER_P (x, strict)) + return true; + if (GET_CODE (x) != PLUS + || !BASE_REGISTER_P (XEXP (x, 0), strict) + || (flag_pic && !CONST_INT_P (XEXP (x, 1)))) + return false; + return indirectable_constant_address_p (XEXP (x, 1), indirect); } -/* Return 1 if x is a valid address not using indexing. +/* Return true if x is a valid address not using indexing. (This much is the easy part.) */ -static int -nonindexed_address_p (rtx x, int strict) +static bool +nonindexed_address_p (rtx x, bool strict) { rtx xfoo0; if (REG_P (x)) { extern rtx *reg_equiv_mem; - if (!reload_in_progress + if (! reload_in_progress || reg_equiv_mem[REGNO (x)] == 0 - || indirectable_address_p (reg_equiv_mem[REGNO (x)], strict)) - return 1; + || indirectable_address_p (reg_equiv_mem[REGNO (x)], strict, false)) + return true; } - if (indirectable_constant_address_p (x)) - return 1; - if (indirectable_address_p (x, strict)) - return 1; + if (indirectable_constant_address_p (x, false)) + return true; + if (indirectable_address_p (x, strict, false)) + return true; xfoo0 = XEXP (x, 0); - if (MEM_P (x) && indirectable_address_p (xfoo0, strict)) - return 1; + if (MEM_P (x) && indirectable_address_p (xfoo0, strict, true)) + return true; if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC) && BASE_REGISTER_P (xfoo0, strict)) - return 1; - return 0; + return true; + return false; } -/* 1 if PROD is either a reg times size of mode MODE and MODE is less +/* True if PROD is either a reg times size of mode MODE and MODE is less than or equal 8 bytes, or just a reg if MODE is one byte. */ -static int -index_term_p (rtx prod, enum machine_mode mode, int strict) +static bool +index_term_p (rtx prod, enum machine_mode mode, bool strict) { rtx xfoo0, xfoo1; @@ -1212,7 +1661,7 @@ index_term_p (rtx prod, enum machine_mode mode, int strict) return BASE_REGISTER_P (prod, strict); if (GET_CODE (prod) != MULT || GET_MODE_SIZE (mode) > 8) - return 0; + return false; xfoo0 = XEXP (prod, 0); xfoo1 = XEXP (prod, 1); @@ -1220,52 +1669,65 @@ index_term_p (rtx prod, enum machine_mode mode, int strict) if (CONST_INT_P (xfoo0) && INTVAL (xfoo0) == (int)GET_MODE_SIZE (mode) && INDEX_REGISTER_P (xfoo1, strict)) - return 1; + return true; if (CONST_INT_P (xfoo1) && INTVAL (xfoo1) == (int)GET_MODE_SIZE (mode) && INDEX_REGISTER_P (xfoo0, strict)) - return 1; + return true; - return 0; + return false; } -/* Return 1 if X is the sum of a register +/* Return true if X is the sum of a register and a valid index term for mode MODE. */ -static int -reg_plus_index_p (rtx x, enum machine_mode mode, int strict) +static bool +reg_plus_index_p (rtx x, enum machine_mode mode, bool strict) { rtx xfoo0, xfoo1; if (GET_CODE (x) != PLUS) - return 0; + return false; xfoo0 = XEXP (x, 0); xfoo1 = XEXP (x, 1); if (BASE_REGISTER_P (xfoo0, strict) && index_term_p (xfoo1, mode, strict)) - return 1; + return true; if (BASE_REGISTER_P (xfoo1, strict) && index_term_p (xfoo0, mode, strict)) - return 1; + return true; - return 0; + return false; } -/* legitimate_address_p returns 1 if it recognizes an RTL expression "x" +/* Return true if xfoo0 and xfoo1 constitute a valid indexed address. */ +static bool +indexable_address_p (rtx xfoo0, rtx xfoo1, enum machine_mode mode, bool strict) +{ + if (!CONSTANT_ADDRESS_P (xfoo0)) + return false; + if (BASE_REGISTER_P (xfoo1, strict)) + return !flag_pic || mode == QImode; + if (flag_pic && symbolic_operand (xfoo0, SImode)) + return false; + return reg_plus_index_p (xfoo1, mode, strict); +} + +/* legitimate_address_p returns true if it recognizes an RTL expression "x" that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. */ -int -legitimate_address_p (enum machine_mode mode, rtx x, int strict) +bool +legitimate_address_p (enum machine_mode mode, rtx x, bool strict) { rtx xfoo0, xfoo1; if (nonindexed_address_p (x, strict)) - return 1; + return true; if (GET_CODE (x) != PLUS) - return 0; + return false; /* Handle
[index] represented with index-sum outermost */ @@ -1274,50 +1736,265 @@ legitimate_address_p (enum machine_mode mode, rtx x, int strict) if (index_term_p (xfoo0, mode, strict) && nonindexed_address_p (xfoo1, strict)) - return 1; + return true; if (index_term_p (xfoo1, mode, strict) && nonindexed_address_p (xfoo0, strict)) - return 1; + return true; /* Handle offset(reg)[index] with offset added outermost */ - if (indirectable_constant_address_p (xfoo0) - && (BASE_REGISTER_P (xfoo1, strict) - || reg_plus_index_p (xfoo1, mode, strict))) - return 1; - - if (indirectable_constant_address_p (xfoo1) - && (BASE_REGISTER_P (xfoo0, strict) - || reg_plus_index_p (xfoo0, mode, strict))) - return 1; + if (indexable_address_p (xfoo0, xfoo1, mode, strict) + || indexable_address_p (xfoo1, xfoo0, mode, strict)) + return true; - return 0; + return false; } -/* Return 1 if x (a legitimate address expression) has an effect that +/* Return true if x (a legitimate address expression) has an effect that depends on the machine mode it is used for. On the VAX, the predecrement and postincrement address depend thus (the amount of decrement or increment being the length of the operand) and all indexed address depend thus (because the index scale factor is the length of the operand). */ -int +bool vax_mode_dependent_address_p (rtx x) { rtx xfoo0, xfoo1; /* Auto-increment cases are now dealt with generically in recog.c. */ - if (GET_CODE (x) != PLUS) - return 0; + return false; xfoo0 = XEXP (x, 0); xfoo1 = XEXP (x, 1); - if (CONSTANT_ADDRESS_P (xfoo0) && REG_P (xfoo1)) - return 0; - if (CONSTANT_ADDRESS_P (xfoo1) && REG_P (xfoo0)) - return 0; + if (CONST_INT_P (xfoo0) && REG_P (xfoo1)) + return false; + if (CONST_INT_P (xfoo1) && REG_P (xfoo0)) + return false; + if (!flag_pic && CONSTANT_ADDRESS_P (xfoo0) && REG_P (xfoo1)) + return false; + if (!flag_pic && CONSTANT_ADDRESS_P (xfoo1) && REG_P (xfoo0)) + return false; + + return true; +} + +static rtx +fixup_mathdi_operand (rtx x, enum machine_mode mode) +{ + if (illegal_addsub_di_memory_operand (x, mode)) + { + rtx addr = XEXP (x, 0); + rtx temp = gen_reg_rtx (Pmode); + rtx offset = 0; +#ifdef NO_EXTERNAL_INDIRECT_ADDRESS + if (GET_CODE (addr) == CONST && flag_pic) + { + offset = XEXP (XEXP (addr, 0), 1); + addr = XEXP (XEXP (addr, 0), 0); + } +#endif + emit_move_insn (temp, addr); + if (offset) + temp = gen_rtx_PLUS (Pmode, temp, offset); + x = gen_rtx_MEM (DImode, temp); + } + return x; +} + +void +vax_expand_addsub_di_operands (rtx * operands, enum rtx_code code) +{ + int hi_only = operand_subword (operands[2], 0, 0, DImode) == const0_rtx; + rtx temp; + + rtx (*gen_old_insn)(rtx, rtx, rtx); + rtx (*gen_si_insn)(rtx, rtx, rtx); + rtx (*gen_insn)(rtx, rtx, rtx); + + if (code == PLUS) + { + gen_old_insn = gen_adddi3_old; + gen_si_insn = gen_addsi3; + gen_insn = gen_adcdi3; + } + else if (code == MINUS) + { + gen_old_insn = gen_subdi3_old; + gen_si_insn = gen_subsi3; + gen_insn = gen_sbcdi3; + } + else + gcc_unreachable (); + + /* If this is addition (thus operands are commutative) and if there is one + addend that duplicates the desination, we want that addend to be the + first addend. */ + if (code == PLUS + && rtx_equal_p (operands[0], operands[2]) + && !rtx_equal_p (operands[1], operands[2])) + { + temp = operands[2]; + operands[2] = operands[1]; + operands[1] = temp; + } + + if (!TARGET_QMATH) + { + emit_insn ((*gen_old_insn) (operands[0], operands[1], operands[2])); + } + else if (hi_only) + { + if (!rtx_equal_p (operands[0], operands[1]) + && (REG_P (operands[0]) && MEM_P (operands[1]))) + { + emit_move_insn (operands[0], operands[1]); + operands[1] = operands[0]; + } + + operands[0] = fixup_mathdi_operand (operands[0], DImode); + operands[1] = fixup_mathdi_operand (operands[1], DImode); + operands[2] = fixup_mathdi_operand (operands[2], DImode); + + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operand_subword (operands[0], 0, 0, DImode), + operand_subword (operands[1], 0, 0, DImode)); + + emit_insn ((*gen_si_insn) (operand_subword (operands[0], 1, 0, DImode), + operand_subword (operands[1], 1, 0, DImode), + operand_subword (operands[2], 1, 0, DImode))); + } + else + { + /* If are adding the same value together, that's really a multiply by 2, + and that's just a left shift of 1. */ + if (rtx_equal_p (operands[1], operands[2])) + { + gcc_assert (code != MINUS); + emit_insn (gen_ashldi3 (operands[0], operands[1], const1_rtx)); + return; + } + + operands[0] = fixup_mathdi_operand (operands[0], DImode); + + /* If an operand is the same as operand[0], use the operand[0] rtx + because fixup will an equivalent rtx but not an equal one. */ + + if (rtx_equal_p (operands[0], operands[1])) + operands[1] = operands[0]; + else + operands[1] = fixup_mathdi_operand (operands[1], DImode); + + if (rtx_equal_p (operands[0], operands[2])) + operands[2] = operands[0]; + else + operands[2] = fixup_mathdi_operand (operands[2], DImode); + + /* If we are subtracting not from ourselves [d = a - b], and because the + carry ops are two operand only, we would need to do a move prior to + the subtract. And if d == b, we would need a temp otherwise + [d = a, d -= d] and we end up with 0. Instead we rewrite d = a - b + into d = -b, d += a. Since -b can never overflow, even if b == d, + no temp is needed. + + If we are doing addition, since the carry ops are two operand, if + we aren't adding to ourselves, move the first addend to the + destination first. */ + + gcc_assert (operands[1] != const0_rtx || code == MINUS); + if (!rtx_equal_p (operands[0], operands[1]) && operands[1] != const0_rtx) + { + if (code == MINUS && CONSTANT_P (operands[1])) + { + temp = gen_reg_rtx (DImode); + emit_insn (gen_sbcdi3 (operands[0], const0_rtx, operands[2])); + code = PLUS; + gen_insn = gen_adcdi3; + operands[2] = operands[1]; + operands[1] = operands[0]; + } + else + emit_move_insn (operands[0], operands[1]); + } + + /* Subtracting a constant will have been rewritten to an addition of the + negative of that constant before we get here. */ + gcc_assert (!CONSTANT_P (operands[2]) || code == PLUS); + emit_insn ((*gen_insn) (operands[0], operands[1], operands[2])); + } +} + +bool +adjacent_operands_p (rtx lo, rtx hi, enum machine_mode mode) +{ + HOST_WIDE_INT lo_offset; + HOST_WIDE_INT hi_offset; + + if (GET_CODE (lo) != GET_CODE (hi)) + return false; + + if (REG_P (lo)) + return mode == SImode && REGNO (lo) + 1 == REGNO (hi); + if (CONST_INT_P (lo)) + return INTVAL (hi) == 0 && 0 <= INTVAL (lo) && INTVAL (lo) < 64; + if (CONST_INT_P (lo)) + return mode != SImode; + + if (!MEM_P (lo)) + return false; + + if (MEM_VOLATILE_P (lo) || MEM_VOLATILE_P (hi)) + return false; + + lo = XEXP (lo, 0); + hi = XEXP (hi, 0); + + if (GET_CODE (lo) == POST_INC /* || GET_CODE (lo) == PRE_DEC */) + return rtx_equal_p (lo, hi); + + switch (GET_CODE (lo)) + { + case REG: + case SYMBOL_REF: + lo_offset = 0; + break; + case CONST: + lo = XEXP (lo, 0); + /* FALLTHROUGH */ + case PLUS: + if (!CONST_INT_P (XEXP (lo, 1))) + return false; + lo_offset = INTVAL (XEXP (lo, 1)); + lo = XEXP (lo, 0); + break; + default: + return false; + } + + switch (GET_CODE (hi)) + { + case REG: + case SYMBOL_REF: + hi_offset = 0; + break; + case CONST: + hi = XEXP (hi, 0); + /* FALLTHROUGH */ + case PLUS: + if (!CONST_INT_P (XEXP (hi, 1))) + return false; + hi_offset = INTVAL (XEXP (hi, 1)); + hi = XEXP (hi, 0); + break; + default: + return false; + } + + if (GET_CODE (lo) == MULT || GET_CODE (lo) == PLUS) + return false; - return 1; + return rtx_equal_p (lo, hi) + && hi_offset - lo_offset == GET_MODE_SIZE (mode); } diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index da264ec..997029e 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler. VAX version. Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -104,7 +104,7 @@ along with GCC; see the file COPYING3. If not see #define STRUCTURE_SIZE_BOUNDARY 8 /* A bit-field declared as `int' forces `int' alignment for the struct. */ -#define PCC_BITFIELD_TYPE_MATTERS (!TARGET_VAXC_ALIGNMENT) +#define PCC_BITFIELD_TYPE_MATTERS (! TARGET_VAXC_ALIGNMENT) /* No data type wants to be aligned rounder than this. */ #define BIGGEST_ALIGNMENT 32 @@ -181,6 +181,9 @@ along with GCC; see the file COPYING3. If not see This is computed in `reload', in reload1.c. */ #define FRAME_POINTER_REQUIRED 1 +/* Offset from the frame pointer register value to the top of stack. */ +#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0 + /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM VAX_AP_REGNUM @@ -228,6 +231,20 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #define REG_CLASS_NAMES \ { "NO_REGS", "ALL_REGS" } +/* The following macro defines cover classes for Integrated Register + Allocator. Cover classes is a set of non-intersected register + classes covering all hard registers used for register allocation + purpose. Any move between two registers of a cover class should be + cheaper than load or store of the registers. The macro value is + array of register classes with LIM_REG_CLASSES used as the end + marker. */ +#define IRA_COVER_CLASSES { ALL_REGS, LIM_REG_CLASSES } + +/* Return the maximum number of consecutive registers + needed to represent mode MODE in a register of class CLASS. */ +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + /* Define which registers fit in which classes. This is an initializer for a vector of HARD_REG_SET of length N_REG_CLASSES. */ @@ -246,54 +263,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; #define INDEX_REG_CLASS ALL_REGS #define BASE_REG_CLASS ALL_REGS -/* Get reg_class from a letter such as appears in the machine description. */ - -#define REG_CLASS_FROM_LETTER(C) NO_REGS - -/* The letters I, J, K, L, M, N, and O in a register constraint string - can be used to stand for particular ranges of immediate operands. - This macro defines what the ranges are. - C is the letter, and VALUE is a constant value. - Return 1 if VALUE is in the range specified by C. - - `I' is the constant zero. - `J' is a value between 0 .. 63 (inclusive) - `K' is a value between -128 and 127 (inclusive) - 'L' is a value between -32768 and 32767 (inclusive) - `M' is a value between 0 and 255 (inclusive) - 'N' is a value between 0 and 65535 (inclusive) - `O' is a value between -63 and -1 (inclusive) */ - -#define CONST_OK_FOR_LETTER_P(VALUE, C) \ - ( (C) == 'I' ? (VALUE) == 0 \ - : (C) == 'J' ? 0 <= (VALUE) && (VALUE) < 64 \ - : (C) == 'O' ? -63 <= (VALUE) && (VALUE) < 0 \ - : (C) == 'K' ? -128 <= (VALUE) && (VALUE) < 128 \ - : (C) == 'M' ? 0 <= (VALUE) && (VALUE) < 256 \ - : (C) == 'L' ? -32768 <= (VALUE) && (VALUE) < 32768 \ - : (C) == 'N' ? 0 <= (VALUE) && (VALUE) < 65536 \ - : 0) - -/* Similar, but for floating constants, and defining letters G and H. - Here VALUE is the CONST_DOUBLE rtx itself. - - `G' is a floating-point zero. */ - -#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? ((VALUE) == CONST0_RTX (DFmode) \ - || (VALUE) == CONST0_RTX (SFmode)) \ - : 0) - -/* Optional extra constraints for this machine. - - For the VAX, `Q' means that OP is a MEM that does not have a mode-dependent - address. */ - -#define EXTRA_CONSTRAINT(OP, C) \ - ((C) == 'Q' \ - ? MEM_P (OP) && !mode_dependent_address_p (XEXP (OP, 0)) \ - : 0) - /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines @@ -621,6 +590,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; in one reasonably fast instruction. */ #define MOVE_MAX 8 +/* If a memory-to-memory move would take MOVE_RATIO or more simple + move-instruction pairs, we will do a movmem or libcall instead. */ +#define MOVE_RATIO(speed) ((speed) ? 6 : 3) +#define CLEAR_RATIO(speed) ((speed) ? 6 : 2) + /* Nonzero if access to memory by bytes is slow and undesirable. */ #define SLOW_BYTE_ACCESS 0 @@ -851,49 +825,11 @@ VAX operand formatting codes: # define NEG_HWI_PRINT_HEX16 "0xffffffff%08lx" #endif -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ((CODE) == '#' || (CODE) == '|') -#define PRINT_OPERAND(FILE, X, CODE) \ -{ if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE); \ - else if (CODE == '|') \ - fputs (REGISTER_PREFIX, FILE); \ - else if (CODE == 'C') \ - fputs (rev_cond_name (X), FILE); \ - else if (CODE == 'D' && CONST_INT_P (X) && INTVAL (X) < 0) \ - fprintf (FILE, "$" NEG_HWI_PRINT_HEX16, INTVAL (X)); \ - else if (CODE == 'P' && CONST_INT_P (X)) \ - fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, INTVAL (X) + 1); \ - else if (CODE == 'N' && CONST_INT_P (X)) \ - fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, ~ INTVAL (X)); \ - /* rotl instruction cannot deal with negative arguments. */ \ - else if (CODE == 'R' && CONST_INT_P (X)) \ - fprintf (FILE, "$" HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (X)); \ - else if (CODE == 'H' && CONST_INT_P (X)) \ - fprintf (FILE, "$%d", (int) (0xffff & ~ INTVAL (X))); \ - else if (CODE == 'h' && CONST_INT_P (X)) \ - fprintf (FILE, "$%d", (short) - INTVAL (x)); \ - else if (CODE == 'B' && CONST_INT_P (X)) \ - fprintf (FILE, "$%d", (int) (0xff & ~ INTVAL (X))); \ - else if (CODE == 'b' && CONST_INT_P (X)) \ - fprintf (FILE, "$%d", (int) (0xff & - INTVAL (X))); \ - else if (CODE == 'M' && CONST_INT_P (X)) \ - fprintf (FILE, "$%d", ~((1 << INTVAL (x)) - 1)); \ - else if (REG_P (X)) \ - fprintf (FILE, "%s", reg_names[REGNO (X)]); \ - else if (MEM_P (X)) \ - output_address (XEXP (X, 0)); \ - else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ - { char dstr[30]; \ - real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (X), \ - sizeof (dstr), 0, 1); \ - fprintf (FILE, "$0f%s", dstr); } \ - else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \ - { char dstr[30]; \ - real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (X), \ - sizeof (dstr), 0, 1); \ - fprintf (FILE, "$0%c%s", ASM_DOUBLE_CHAR, dstr); } \ - else { putc ('$', FILE); output_addr_const (FILE, X); }} +#define PRINT_OPERAND(FILE, X, CODE) \ + print_operand (FILE, X, CODE) /* Print a memory operand whose address is X, on file FILE. This uses a function in output-vax.c. */ diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md index 0bc05b4..da3ca48 100644 --- a/gcc/config/vax/vax.md +++ b/gcc/config/vax/vax.md @@ -1,6 +1,6 @@ ;; Machine description for GNU compiler, VAX Version ;; Copyright (C) 1987, 1988, 1991, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -;; 2002, 2004, 2005, 2007 Free Software Foundation, Inc. +;; 2002, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. ;; This file is part of GCC. @@ -43,7 +43,9 @@ ;; Integer modes supported on VAX, with a mapping from machine mode ;; to mnemonic suffix. DImode is always a special case. (define_mode_iterator VAXint [QI HI SI]) -(define_mode_attr isfx [(QI "b") (HI "w") (SI "l")]) +(define_mode_iterator VAXintQH [QI HI]) +(define_mode_iterator VAXintQHSD [QI HI SI DI]) +(define_mode_attr isfx [(QI "b") (HI "w") (SI "l") (DI "q")]) ;; Similar for float modes supported on VAX. (define_mode_iterator VAXfp [SF DF]) @@ -52,13 +54,17 @@ ;; Some output patterns want integer immediates with a prefix... (define_mode_attr iprefx [(QI "B") (HI "H") (SI "N")]) +;; +(include "constraints.md") +(include "predicates.md") + ;; We don't want to allow a constant operand for test insns because ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. (define_insn "tst" [(set (cc0) - (match_operand:VAXint 0 "nonimmediate_operand" "g"))] + (match_operand:VAXint 0 "nonimmediate_operand" "nrmT"))] "" "tst %0") @@ -70,8 +76,8 @@ (define_insn "cmp" [(set (cc0) - (compare (match_operand:VAXint 0 "nonimmediate_operand" "g") - (match_operand:VAXint 1 "general_operand" "g")))] + (compare (match_operand:VAXint 0 "nonimmediate_operand" "nrmT") + (match_operand:VAXint 1 "general_operand" "nrmT")))] "" "cmp %0,%1") @@ -86,8 +92,8 @@ (define_insn "*bit" [(set (cc0) - (and:VAXint (match_operand:VAXint 0 "general_operand" "g") - (match_operand:VAXint 1 "general_operand" "g")))] + (and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT") + (match_operand:VAXint 1 "general_operand" "nrmT")))] "" "bit %0,%1") @@ -115,12 +121,10 @@ ;; "movh %1,%0") (define_insn "movdi" - [(set (match_operand:DI 0 "nonimmediate_operand" "=g,g") - (match_operand:DI 1 "general_operand" "I,g"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=g") + (match_operand:DI 1 "general_operand" "g"))] "" - "@ - clrq %0 - movq %D1,%0") + "* return vax_output_int_move (insn, operands, DImode);") ;; The VAX move instructions have space-time tradeoffs. On a MicroVAX ;; register-register mov instructions take 3 bytes and 2 CPU cycles. clrl @@ -139,9 +143,37 @@ ;; Loads of constants between 64 and 128 used to be done with ;; "addl3 $63,#,dst" but this is slower than movzbl and takes as much space. +(define_expand "movsi" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" + " +{ +#ifdef NO_EXTERNAL_INDIRECT_ADDRESS + if (flag_pic + && GET_CODE (operands[1]) == CONST + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF + && !SYMBOL_REF_LOCAL_P (XEXP (XEXP (operands[1], 0), 0))) + { + rtx symbol_ref = XEXP (XEXP (operands[1], 0), 0); + rtx const_int = XEXP (XEXP (operands[1], 0), 1); + rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); + emit_move_insn (temp, symbol_ref); + emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, const_int)); + DONE; + } +#endif +}") + +(define_insn "movsi_2" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (match_operand:SI 1 "nonsymbolic_operand" "nrmT"))] + "" + "* return vax_output_int_move (insn, operands, SImode);") + (define_insn "mov" - [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g") - (match_operand:VAXint 1 "general_operand" "g"))] + [(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g") + (match_operand:VAXintQH 1 "general_operand" "g"))] "" "* return vax_output_int_move (insn, operands, mode);") @@ -192,17 +224,19 @@ (match_operand 3 "" "")] "" " +{ emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2])); DONE; -") +}") ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it won't successfully combine with anything. + (define_insn "movmemhi1" - [(set (match_operand:BLK 0 "memory_operand" "=m") - (match_operand:BLK 1 "memory_operand" "m")) + [(set (match_operand:BLK 0 "memory_operand" "=o") + (match_operand:BLK 1 "memory_operand" "o")) (use (match_operand:HI 2 "general_operand" "g")) (clobber (reg:SI 0)) (clobber (reg:SI 1)) @@ -217,13 +251,13 @@ (define_insn "truncsiqi2" [(set (match_operand:QI 0 "nonimmediate_operand" "=g") - (truncate:QI (match_operand:SI 1 "nonimmediate_operand" "g")))] + (truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))] "" "cvtlb %1,%0") (define_insn "truncsihi2" [(set (match_operand:HI 0 "nonimmediate_operand" "=g") - (truncate:HI (match_operand:SI 1 "nonimmediate_operand" "g")))] + (truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))] "" "cvtlw %1,%0") @@ -309,56 +343,62 @@ add2 %1,%0 add3 %1,%2,%0") +(define_insn "pushlclsymreg" + [(set (match_operand:SI 0 "push_operand" "=g") + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "local_symbolic_operand" "i")))] + "flag_pic" + "pushab %a2[%1]") + +(define_insn "pushextsymreg" + [(set (match_operand:SI 0 "push_operand" "=g") + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "external_symbolic_operand" "i")))] + "flag_pic" + "pushab %a2[%1]") + +(define_insn "movlclsymreg" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "local_symbolic_operand" "i")))] + "flag_pic" + "movab %a2[%1],%0") + +(define_insn "movextsymreg" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "external_symbolic_operand" "i")))] + "flag_pic" + "movab %a2[%1],%0") + (define_insn "add3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g") - (plus:VAXint (match_operand:VAXint 1 "general_operand" "g") - (match_operand:VAXint 2 "general_operand" "g")))] + (plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT")))] "" "* return vax_output_int_add (insn, operands, mode);") +(define_expand "adddi3" + [(set (match_operand:DI 0 "nonimmediate_operand" "=g") + (plus:DI (match_operand:DI 1 "general_operand" "g") + (match_operand:DI 2 "general_operand" "g")))] + "!reload_in_progress" + "vax_expand_addsub_di_operands (operands, PLUS); DONE;") + +(define_insn "adcdi3" + [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr") + (plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0") + (match_operand:DI 2 "general_addsub_di_operand" "nRr")))] + "TARGET_QMATH" + "* return vax_output_int_add (insn, operands, DImode);") + ;; The add-with-carry (adwc) instruction only accepts two operands. -(define_insn "adddi3" +(define_insn "adddi3_old" [(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>") (plus:DI (match_operand:DI 1 "general_operand" "%0,ro>") - (match_operand:DI 2 "general_operand" "Fro,F")))] - "" - "* -{ - rtx low[3]; - const char *pattern; - int carry = 1; - - split_quadword_operands (operands, low, 3); - /* Add low parts. */ - if (rtx_equal_p (operands[0], operands[1])) - { - if (low[2] == const0_rtx) - /* Should examine operand, punt if not POST_INC. */ - pattern = \"tstl %0\", carry = 0; - else if (low[2] == const1_rtx) - pattern = \"incl %0\"; - else - pattern = \"addl2 %2,%0\"; - } - else - { - if (low[2] == const0_rtx) - pattern = \"movl %1,%0\", carry = 0; - else - pattern = \"addl3 %2,%1,%0\"; - } - if (pattern) - output_asm_insn (pattern, low); - if (!carry) - /* If CARRY is 0, we don't have any carry value to worry about. */ - return get_insn_template (CODE_FOR_addsi3, insn); - /* %0 = C + %1 + %2 */ - if (!rtx_equal_p (operands[0], operands[1])) - output_asm_insn ((operands[1] == const0_rtx - ? \"clrl %0\" - : \"movl %1,%0\"), operands); - return \"adwc %2,%0\"; -}") + (match_operand:DI 2 "general_operand" "Fsro,Fs")))] + "!TARGET_QMATH" + "* return vax_output_int_add (insn, operands, DImode);") ;;- All kinds of subtract instructions. @@ -373,56 +413,34 @@ (define_insn "sub3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g") - (minus:VAXint (match_operand:VAXint 1 "general_operand" "0,g") - (match_operand:VAXint 2 "general_operand" "g,g")))] + (minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))] "" "@ sub2 %2,%0 sub3 %2,%1,%0") +(define_expand "subdi3" + [(set (match_operand:DI 0 "nonimmediate_operand" "=g") + (minus:DI (match_operand:DI 1 "general_operand" "g") + (match_operand:DI 2 "general_operand" "g")))] + "!reload_in_progress" + "vax_expand_addsub_di_operands (operands, MINUS); DONE;") + +(define_insn "sbcdi3" + [(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,=Rr") + (minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I") + (match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))] + "TARGET_QMATH" + "* return vax_output_int_subtract (insn, operands, DImode);") + ;; The subtract-with-carry (sbwc) instruction only takes two operands. -(define_insn "subdi3" +(define_insn "subdi3_old" [(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>") (minus:DI (match_operand:DI 1 "general_operand" "0,or>") - (match_operand:DI 2 "general_operand" "For,F")))] - "" - "* -{ - rtx low[3]; - const char *pattern; - int carry = 1; - - split_quadword_operands (operands, low, 3); - /* Subtract low parts. */ - if (rtx_equal_p (operands[0], operands[1])) - { - if (low[2] == const0_rtx) - pattern = 0, carry = 0; - else if (low[2] == constm1_rtx) - pattern = \"decl %0\"; - else - pattern = \"subl2 %2,%0\"; - } - else - { - if (low[2] == constm1_rtx) - pattern = \"decl %0\"; - else if (low[2] == const0_rtx) - pattern = get_insn_template (CODE_FOR_movsi, insn), carry = 0; - else - pattern = \"subl3 %2,%1,%0\"; - } - if (pattern) - output_asm_insn (pattern, low); - if (carry) - { - if (!rtx_equal_p (operands[0], operands[1])) - return \"movl %1,%0\;sbwc %2,%0\"; - return \"sbwc %2,%0\"; - /* %0 = %2 - %1 - C */ - } - return get_insn_template (CODE_FOR_subsi3, insn); -}") + (match_operand:DI 2 "general_operand" "Fsor,Fs")))] + "!TARGET_QMATH" + "* return vax_output_int_subtract (insn, operands, DImode);") ;;- Multiply instructions. @@ -438,8 +456,8 @@ (define_insn "mul3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g") - (mult:VAXint (match_operand:VAXint 1 "general_operand" "0,g,g") - (match_operand:VAXint 2 "general_operand" "g,0,g")))] + (mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))] "" "@ mul2 %2,%0 @@ -449,9 +467,9 @@ (define_insn "mulsidi3" [(set (match_operand:DI 0 "nonimmediate_operand" "=g") (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "g")) + (match_operand:SI 1 "nonimmediate_operand" "nrmT")) (sign_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "g"))))] + (match_operand:SI 2 "nonimmediate_operand" "nrmT"))))] "" "emul %1,%2,$0,%0") @@ -459,9 +477,9 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=g") (plus:DI (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "g")) + (match_operand:SI 1 "nonimmediate_operand" "nrmT")) (sign_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "g"))) + (match_operand:SI 2 "nonimmediate_operand" "nrmT"))) (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))] "" "emul %1,%2,%3,%0") @@ -471,9 +489,9 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=g") (plus:DI (mult:DI (sign_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "g")) + (match_operand:SI 1 "nonimmediate_operand" "nrmT")) (sign_extend:DI - (match_operand:SI 2 "nonimmediate_operand" "g"))) + (match_operand:SI 2 "nonimmediate_operand" "nrmT"))) (match_operand:DI 3 "immediate_operand" "F")))] "GET_CODE (operands[3]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)" @@ -497,8 +515,8 @@ (define_insn "div3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g") - (div:VAXint (match_operand:VAXint 1 "general_operand" "0,g") - (match_operand:VAXint 2 "general_operand" "g,g")))] + (div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))] "" "@ div2 %2,%0 @@ -527,7 +545,7 @@ rtx op1 = operands[1]; /* If there is a constant argument, complement that one. */ - if (CONST_INT_P (operands[2]) && !CONST_INT_P (op1)) + if (CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) { operands[1] = operands[2]; operands[2] = op1; @@ -542,8 +560,8 @@ (define_insn "*and" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g") - (and:VAXint (not:VAXint (match_operand:VAXint 1 "general_operand" "g,g")) - (match_operand:VAXint 2 "general_operand" "0,g")))] + (and:VAXint (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT,nrmT")) + (match_operand:VAXint 2 "general_operand" "0,nrmT")))] "" "@ bic2 %1,%0 @@ -556,7 +574,7 @@ (define_insn "*and_const_int" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g") - (and:VAXint (match_operand:VAXint 1 "general_operand" "0,g") + (and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT") (match_operand:VAXint 2 "const_int_operand" "n,n")))] "" "@ @@ -568,8 +586,8 @@ (define_insn "ior3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g") - (ior:VAXint (match_operand:VAXint 1 "general_operand" "0,g,g") - (match_operand:VAXint 2 "general_operand" "g,0,g")))] + (ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))] "" "@ bis2 %2,%0 @@ -580,8 +598,8 @@ (define_insn "xor3" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g") - (xor:VAXint (match_operand:VAXint 1 "general_operand" "0,g,g") - (match_operand:VAXint 2 "general_operand" "g,0,g")))] + (xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT") + (match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))] "" "@ xor2 %2,%0 @@ -597,13 +615,13 @@ (define_insn "neg2" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g") - (neg:VAXint (match_operand:VAXint 1 "general_operand" "g")))] + (neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))] "" "mneg %1,%0") (define_insn "one_cmpl2" [(set (match_operand:VAXint 0 "nonimmediate_operand" "=g") - (not:VAXint (match_operand:VAXint 1 "general_operand" "g")))] + (not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))] "" "mcom %1,%0") @@ -620,43 +638,50 @@ "" " { - if (!CONST_INT_P (operands[2])) + if (! CONST_INT_P(operands[2])) operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); }") (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") + (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "const_int_operand" "n")))] "" "ashl $%n2,%1,%0") (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") + (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT") (neg:QI (match_operand:QI 2 "general_operand" "g"))))] "" "ashl %2,%1,%0") (define_insn "ashlsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (ashift:SI (match_operand:SI 1 "general_operand" "g") + (ashift:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1])) return \"addl2 %0,%0\"; - if (REG_P (operands[1]) - && CONST_INT_P (operands[2])) + if (REG_P (operands[1]) && CONST_INT_P (operands[2])) { int i = INTVAL (operands[2]); if (i == 1) return \"addl3 %1,%1,%0\"; - if (i == 2) - return \"moval 0[%1],%0\"; - if (i == 3) - return \"movad 0[%1],%0\"; + if (i == 2 && !optimize_size) + { + if (push_operand (operands[0], SImode)) + return \"pushal 0[%1]\"; + return \"moval 0[%1],%0\"; + } + if (i == 3 && !optimize_size) + { + if (push_operand (operands[0], SImode)) + return \"pushaq 0[%1]\"; + return \"movaq 0[%1],%0\"; + } } return \"ashl %2,%1,%0\"; }") @@ -695,7 +720,7 @@ [(set (match_dup 3) (minus:QI (const_int 32) (match_dup 4))) - (set (match_operand:SI 0 "general_operand" "=g") + (set (match_operand:SI 0 "nonimmediate_operand" "=g") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (match_dup 3) (match_operand:SI 2 "register_operand" "g")))] @@ -714,27 +739,27 @@ "" " { - if (!CONST_INT_P (operands[2])) + if (! CONST_INT_P (operands[2])) operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); }") (define_insn "rotlsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (rotate:SI (match_operand:SI 1 "general_operand" "g") + (rotate:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "general_operand" "g")))] "" "rotl %2,%1,%0") (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (rotatert:SI (match_operand:SI 1 "general_operand" "g") + (rotatert:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "const_int_operand" "n")))] "" "rotl %R2,%1,%0") (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (rotatert:SI (match_operand:SI 1 "general_operand" "g") + (rotatert:SI (match_operand:SI 1 "general_operand" "nrmT") (neg:QI (match_operand:QI 2 "general_operand" "g"))))] "" "rotl %2,%1,%0") @@ -761,7 +786,7 @@ "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 && (REG_P (operands[0]) - || !mode_dependent_address_p (XEXP (operands[0], 0)))" + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" "* { if (REG_P (operands[0])) @@ -789,7 +814,7 @@ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (REG_P (operands[1]) - || !mode_dependent_address_p (XEXP (operands[1], 0)))" + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" "* { if (REG_P (operands[1])) @@ -816,7 +841,7 @@ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (REG_P (operands[1]) - || !mode_dependent_address_p (XEXP (operands[1], 0)))" + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" "* { if (REG_P (operands[1])) @@ -842,8 +867,8 @@ (compare (sign_extract:SI (match_operand:SI 0 "register_operand" "r") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT")))] "" "cmpv %2,%1,%0,%3") @@ -852,8 +877,8 @@ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "r") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT")))] "" "cmpzv %2,%1,%0,%3") @@ -866,13 +891,12 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (sign_extract:SI (match_operand:SI 1 "register_operand" "ro") (match_operand:QI 2 "general_operand" "g") - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 3 "general_operand" "nrmT")))] "" "* { - if (!CONST_INT_P (operands[3]) - || !CONST_INT_P (operands[2]) - || !REG_P (operands[0]) + if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2]) + || ! REG_P (operands[0]) || (INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16)) return \"extv %3,%2,%1,%0\"; if (INTVAL (operands[2]) == 8) @@ -884,13 +908,12 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (zero_extract:SI (match_operand:SI 1 "register_operand" "ro") (match_operand:QI 2 "general_operand" "g") - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 3 "general_operand" "nrmT")))] "" "* { - if (!CONST_INT_P (operands[3]) - || !CONST_INT_P (operands[2]) - || !REG_P (operands[0])) + if (! CONST_INT_P (operands[3]) || ! CONST_INT_P (operands[2]) + || ! REG_P (operands[0])) return \"extzv %3,%2,%1,%0\"; if (INTVAL (operands[2]) == 8) return \"rotl %R3,%1,%0\;movzbl %0,%0\"; @@ -912,8 +935,8 @@ (compare (sign_extract:SI (match_operand:QI 0 "memory_operand" "m") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT")))] "" "cmpv %2,%1,%0,%3") @@ -922,8 +945,8 @@ (compare (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT")))] "" "cmpzv %2,%1,%0,%3") @@ -931,12 +954,11 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (sign_extract:SI (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g") - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 3 "general_operand" "nrmT")))] "" "* { - if (!REG_P (operands[0]) - || !CONST_INT_P (operands[2]) + if (!REG_P (operands[0]) || !CONST_INT_P (operands[2]) || !CONST_INT_P (operands[3]) || (INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16) || INTVAL (operands[2]) + INTVAL (operands[3]) > 32 @@ -961,12 +983,11 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (zero_extract:SI (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g") - (match_operand:SI 3 "general_operand" "g")))] + (match_operand:SI 3 "general_operand" "nrmT")))] "" "* { - if (!REG_P (operands[0]) - || !CONST_INT_P (operands[2]) + if (!REG_P (operands[0]) || !CONST_INT_P (operands[2]) || !CONST_INT_P (operands[3]) || INTVAL (operands[2]) + INTVAL (operands[3]) > 32 || side_effects_p (operands[1]) @@ -977,6 +998,28 @@ return \"rotl %R3,%1,%0\;movzbl %0,%0\"; if (INTVAL (operands[2]) == 16) return \"rotl %R3,%1,%0\;movzwl %0,%0\"; + if (MEM_P (operands[1]) + && GET_CODE (XEXP (operands[1], 0)) == PLUS + && REG_P (XEXP (XEXP (operands[1], 0), 0)) + && CONST_INT_P (XEXP (XEXP (operands[1], 0), 1)) + && CONST_INT_P (operands[2]) + && CONST_INT_P (operands[3])) + { + HOST_WIDE_INT o = INTVAL (XEXP (XEXP (operands[1], 0), 1)); + HOST_WIDE_INT l = INTVAL (operands[2]); + HOST_WIDE_INT v = INTVAL (operands[3]); + if ((o & 3) && (o & 3) * 8 + v + l <= 32) + { + rtx tmp; + tmp = XEXP (XEXP (operands[1], 0), 0); + if (o & ~3) + tmp = gen_rtx_PLUS (SImode, tmp, GEN_INT (o & ~3)); + operands[1] = gen_rtx_MEM (QImode, tmp); + operands[3] = GEN_INT (v + (o & 3) * 8); + } + if (optimize_size) + return \"extzv %3,%2,%1,%0\"; + } return \"rotl %R3,%1,%0\;bicl2 %M2,%0\"; }") @@ -991,16 +1034,39 @@ (define_insn "" [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+g") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g"))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT"))] "" - "insv %3,%2,%1,%0") + "* +{ + if (MEM_P (operands[0]) + && GET_CODE (XEXP (operands[0], 0)) == PLUS + && REG_P (XEXP (XEXP (operands[0], 0), 0)) + && CONST_INT_P (XEXP (XEXP (operands[0], 0), 1)) + && CONST_INT_P (operands[1]) + && CONST_INT_P (operands[2])) + { + HOST_WIDE_INT o = INTVAL (XEXP (XEXP (operands[0], 0), 1)); + HOST_WIDE_INT v = INTVAL (operands[2]); + HOST_WIDE_INT l = INTVAL (operands[1]); + if ((o & 3) && (o & 3) * 8 + v + l <= 32) + { + rtx tmp; + tmp = XEXP (XEXP (operands[0], 0), 0); + if (o & ~3) + tmp = gen_rtx_PLUS (SImode, tmp, GEN_INT (o & ~3)); + operands[0] = gen_rtx_MEM (QImode, tmp); + operands[2] = GEN_INT (v + (o & 3) * 8); + } + } + return \"insv %3,%2,%1,%0\"; +}") (define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (match_operand:QI 1 "general_operand" "g") - (match_operand:SI 2 "general_operand" "g")) - (match_operand:SI 3 "general_operand" "g"))] + (match_operand:SI 2 "general_operand" "nrmT")) + (match_operand:SI 3 "general_operand" "nrmT"))] "" "insv %3,%2,%1,%0") @@ -1044,7 +1110,7 @@ (if_then_else (ne (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,g") (const_int 1) - (match_operand:SI 1 "general_operand" "I,g")) + (match_operand:SI 1 "general_operand" "I,nrmT")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] @@ -1058,7 +1124,7 @@ (if_then_else (eq (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,g") (const_int 1) - (match_operand:SI 1 "general_operand" "I,g")) + (match_operand:SI 1 "general_operand" "I,nrmT")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] @@ -1072,7 +1138,7 @@ (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) - (match_operand:SI 1 "general_operand" "I,g")) + (match_operand:SI 1 "general_operand" "I,nrmT")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] @@ -1086,7 +1152,7 @@ (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) - (match_operand:SI 1 "general_operand" "I,g")) + (match_operand:SI 1 "general_operand" "I,nrmT")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] @@ -1135,7 +1201,7 @@ (if_then_else (lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int 1)) - (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 1 "general_operand" "nrmT")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) @@ -1148,7 +1214,7 @@ [(set (pc) (if_then_else (lt (match_operand:SI 0 "nonimmediate_operand" "+g") - (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 1 "general_operand" "nrmT")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) @@ -1162,7 +1228,7 @@ (if_then_else (le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int 1)) - (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 1 "general_operand" "nrmT")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) @@ -1175,7 +1241,7 @@ [(set (pc) (if_then_else (le (match_operand:SI 0 "nonimmediate_operand" "+g") - (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 1 "general_operand" "nrmT")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) @@ -1278,7 +1344,7 @@ (define_expand "call_value" [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "") - (match_operand:SI 2 "const_int_operand" "")))] + (match_operand:SI 2 "const_int_operand" "")))] "" " { @@ -1299,9 +1365,9 @@ (define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] "" " { @@ -1413,13 +1479,37 @@ [(match_operand:SI 1 "const_int_operand" "n") (set (pc) (plus:SI (sign_extend:SI - (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "general_operand" "g") + (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "general_operand" "nrmT") (const_int 2)) (pc)))) (label_ref:SI (match_operand 2 "" ""))))] "" "casel %0,$0,%1") +(define_insn "pushextsym" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:SI 1 "external_symbolic_operand" "i"))] + "" + "pushab %a1") + +(define_insn "movextsym" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (match_operand:SI 1 "external_symbolic_operand" "i"))] + "" + "movab %a1,%0") + +(define_insn "pushlclsym" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:SI 1 "local_symbolic_operand" "i"))] + "" + "pushab %a1") + +(define_insn "movlclsym" + [(set (match_operand:SI 0 "nonimmediate_operand" "=g") + (match_operand:SI 1 "local_symbolic_operand" "i"))] + "" + "movab %a1,%0") + ;;- load or push effective address ;; These come after the move and add/sub patterns ;; because we don't want pushl $1 turned into pushad 1. @@ -1428,77 +1518,29 @@ ;; It does not work to use constraints to distinguish pushes from moves, ;; because < matches any autodecrement, not just a push. -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushab %a1\"; - else - return \"movab %a1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:HI 1 "address_operand" "p"))] - "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushaw %a1\"; - else - return \"movaw %a1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:SI 1 "address_operand" "p"))] +(define_insn "pushaddr" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:VAXintQHSD 1 "address_operand" "p"))] "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushal %a1\"; - else - return \"moval %a1,%0\"; -}") + "pusha %a1") -(define_insn "" +(define_insn "movaddr" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:DI 1 "address_operand" "p"))] + (match_operand:VAXintQHSD 1 "address_operand" "p"))] "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushaq %a1\"; - else - return \"movaq %a1,%0\"; -}") + "mova %a1,%0") -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:SF 1 "address_operand" "p"))] +(define_insn "pushaddr" + [(set (match_operand:SI 0 "push_operand" "=g") + (match_operand:VAXfp 1 "address_operand" "p"))] "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushaf %a1\"; - else - return \"movaf %a1,%0\"; -}") + "pusha %a1") -(define_insn "" +(define_insn "movaddr" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") - (match_operand:DF 1 "address_operand" "p"))] + (match_operand:VAXfp 1 "address_operand" "p"))] "" - "* -{ - if (push_operand (operands[0], SImode)) - return \"pushad %a1\"; - else - return \"movad %a1,%0\"; -}") + "mova %a1,%0") ;; These used to be peepholes, but it is more straightforward to do them ;; as single insns. However, we must force the output to be a register @@ -1515,7 +1557,7 @@ (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=ro") - (and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") + (and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0" @@ -1537,7 +1579,7 @@ (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=ro") - (and:SI (ashift:SI (match_operand:SI 1 "general_operand" "g") + (and:SI (ashift:SI (match_operand:SI 1 "general_operand" "nrmT") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "" @@ -1553,3 +1595,29 @@ [(unspec_volatile [(const_int 0)] VUNSPEC_SYNC_ISTREAM)] "" "movpsl -(%|sp)\;pushal 1(%|pc)\;rei") + +(define_expand "nonlocal_goto" + [(use (match_operand 0 "general_operand" "")) + (use (match_operand 1 "general_operand" "")) + (use (match_operand 2 "general_operand" "")) + (use (match_operand 3 "general_operand" ""))] + "" +{ + rtx lab = operands[1]; + rtx stack = operands[2]; + rtx fp = operands[3]; + + emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); + emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); + + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + + emit_use (hard_frame_pointer_rtx); + emit_use (stack_pointer_rtx); + + /* We'll convert this to direct jump via a peephole optimization. */ + emit_indirect_jump (copy_to_reg (lab)); + emit_barrier (); + DONE; +}) diff --git a/gcc/config/vax/vax.opt b/gcc/config/vax/vax.opt index 2a6339c..82d6dee 100644 --- a/gcc/config/vax/vax.opt +++ b/gcc/config/vax/vax.opt @@ -1,6 +1,6 @@ ; Options for the VAX port of the compiler. -; Copyright (C) 2005, 2007 Free Software Foundation, Inc. +; Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. ; ; This file is part of GCC. ; @@ -45,3 +45,7 @@ Generate code for UNIX assembler mvaxc-alignment Target RejectNegative Mask(VAXC_ALIGNMENT) Use VAXC structure conventions + +mqmath +Target Mask(QMATH) +Use new adddi3/subdi3 patterns