;;- Machine description for the pdp11 for GNU C compiler
-;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005
+;; 2007, 2008, 2010 Free Software Foundation, Inc.
;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
-;; This file is part of GNU CC.
+;; This file is part of GCC.
-;; GNU CC is free software; you can redistribute it and/or modify
+;; 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)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
-;; GNU CC is distributed in the hope that it will be useful,
+;; 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 GNU CC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(include "predicates.md")
+(include "constraints.md")
+
+(define_constants
+ [
+ ;; Register numbers
+ (R0_REGNUM 0)
+ (RETVAL_REGNUM 0)
+ (HARD_FRAME_POINTER_REGNUM 5)
+ (STACK_POINTER_REGNUM 6)
+ (PC_REGNUM 7)
+ (AC0_REGNUM 8)
+ (AC3_REGNUM 11)
+ (AC4_REGNUM 12)
+ (AC5_REGNUM 13)
+ ;; The next two are not physical registers but are used for addressing
+ ;; arguments.
+ (FRAME_POINTER_REGNUM 14)
+ (ARG_POINTER_REGNUM 15)
+ (FIRST_PSEUDO_REGISTER 16)
+ ;; Branch offset limits, as byte offsets from instruction address
+ (MIN_BRANCH -254)
+ (MAX_BRANCH 256)
+ (MIN_SOB -126)
+ (MAX_SOB 0)])
;; HI is 16 bit
;; QI is 8 bit
+;; Integer modes supported on the PDP11, with a mapping from machine mode
+;; to mnemonic suffix. SImode and DImode always are special cases.
+(define_mode_iterator PDPint [QI HI])
+(define_mode_attr isfx [(QI "b") (HI "")])
+
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;; default is arith
(define_attr "type" "unknown,arith,fp" (const_string "arith"))
-;; length default is 1 word each
-(define_attr "length" "" (const_int 1))
+;; length default is 2 bytes each
+(define_attr "length" "" (const_int 2))
;; a user's asm statement
(define_asm_attributes
[(set_attr "type" "unknown")
-; all bets are off how long it is - make it 256, forces long jumps
-; whenever jumping around it !!!
- (set_attr "length" "256")])
+; length for asm is the max length per statement. That would be
+; 5 words, for a floating point instruction with a literal constant
+; argument.
+ (set_attr "length" "10")])
;; define function units
;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
;; compare
-(define_insn "cmpdf"
- [(set (cc0)
- (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
- (match_operand:DF 1 "register_operand" "a,a,a")))]
- "TARGET_FPU"
- "*
-{
- cc_status.flags = CC_IN_FPU;
- return \"{cmpd|cmpf} %0, %1\;cfcc\";
-}"
- [(set_attr "length" "2,3,6")])
-
-;; a bit of brain damage, maybe inline later -
-;; problem is - gcc seems to NEED SImode because
-;; of the cmp weirdness - maybe change gcc to handle this?
-
-(define_expand "cmpsi"
- [(set (reg:SI 0)
- (match_operand:SI 0 "general_operand" "g"))
- (set (reg:SI 2)
- (match_operand:SI 1 "general_operand" "g"))
- (parallel [(set (cc0)
- (compare (reg:SI 0)
- (reg:SI 2)))
- (clobber (reg:SI 0))])]
- "0" ;; disable for test
- "")
-
-;; check for next insn for branch code - does this still
-;; work in gcc 2.* ?
-
-(define_insn ""
- [(set (cc0)
- (compare (reg:SI 0)
- (reg:SI 2)))
- (clobber (reg:SI 0))]
- ""
- "*
-{
- rtx br_insn = NEXT_INSN (insn);
- RTX_CODE br_code;
-
- if (GET_CODE (br_insn) != JUMP_INSN)
- abort();
- br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
-
- switch(br_code)
- {
- case GEU:
- case LTU:
- case GTU:
- case LEU:
-
- return \"jsr pc, ___ucmpsi\;cmp $1,r0\";
-
- case GE:
- case LT:
- case GT:
- case LE:
- case EQ:
- case NE:
-
- return \"jsr pc, ___cmpsi\;tst r0\";
-
- default:
-
- abort();
- }
-}"
- [(set_attr "length" "4")])
-
-
-(define_insn "cmphi"
- [(set (cc0)
- (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi")
- (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))]
- ""
- "cmp %0,%1"
- [(set_attr "length" "1,2,2,3")])
-
-(define_insn "cmpqi"
+(define_insn "*cmpdf"
[(set (cc0)
- (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi")
- (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))]
- ""
- "cmpb %0,%1"
- [(set_attr "length" "1,2,2,3")])
-
-
-;; We have to have this because cse can optimize the previous pattern
-;; into this one.
-
-(define_insn "tstdf"
- [(set (cc0)
- (match_operand:DF 0 "general_operand" "fR,Q"))]
+ (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
+ (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
"TARGET_FPU"
"*
{
cc_status.flags = CC_IN_FPU;
- return \"{tstd|tstf} %0\;cfcc\";
+ if (which_alternative == 0 || which_alternative == 2)
+ return \"{tstd|tstf} %0\;cfcc\";
+ else
+ return \"{cmpd|cmpf} %0, %1\;cfcc\";
}"
- [(set_attr "length" "2,3")])
-
-
-(define_expand "tstsi"
- [(set (reg:SI 0)
- (match_operand:SI 0 "general_operand" "g"))
- (parallel [(set (cc0)
- (reg:SI 0))
- (clobber (reg:SI 0))])]
- "0" ;; disable for test
- "")
-
-(define_insn ""
- [(set (cc0)
- (reg:SI 0))
- (clobber (reg:SI 0))]
- ""
- "jsr pc, ___tstsi\;tst r0"
- [(set_attr "length" "3")])
-
+ [(set_attr "length" "4,4,6,6,12")])
-(define_insn "tsthi"
+(define_insn "*cmp<mode>"
[(set (cc0)
- (match_operand:HI 0 "general_operand" "rR,Q"))]
+ (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
+ (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
""
- "tst %0"
- [(set_attr "length" "1,2")])
-
-(define_insn "tstqi"
- [(set (cc0)
- (match_operand:QI 0 "general_operand" "rR,Q"))]
- ""
- "tstb %0"
- [(set_attr "length" "1,2")])
+ "@
+ tst<PDPint:isfx> %0
+ cmp<PDPint:isfx> %0,%1
+ cmp<PDPint:isfx> %0,%1
+ tst<PDPint:isfx> %0
+ cmp<PDPint:isfx> %0,%1
+ cmp<PDPint:isfx> %0,%1"
+ [(set_attr "length" "2,2,4,4,4,6")])
;; sob instruction - we need an assembler which can make this instruction
;; valid under _all_ circumstances!
static int labelcount = 0;
static char buf[1000];
- if (get_attr_length (insn) == 1)
+ if (get_attr_length (insn) == 2)
return \"sob %0, %l1\";
/* emulate sob */
return \"\";
}"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+ [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
(pc))
- (const_int -256))
- (ge (minus (match_dup 0)
+ (const_int MIN_SOB))
+ (gt (minus (match_dup 0)
(pc))
- (const_int 0)))
- (const_int 4)
- (const_int 1)))])
+ (const_int MAX_SOB)))
+ (const_int 8)
+ (const_int 2)))])
;; These control RTL generation for conditional jump insns
;; and match them for register allocation.
-;; problem with too short jump distance! we need an assembler which can
-;; make this valid for all jump distances!
-;; e.g. gas!
-
-;; these must be changed to check for CC_IN_FCCR if float is to be
-;; enabled
-
-(define_insn "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-
-(define_insn "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchdf4"
+ [(set (cc0)
+ (compare (match_operand:DF 1 "general_operand")
+ (match_operand:DF 2 "register_or_const0_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
- ""
- "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
+ "TARGET_FPU"
+ "")
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "cbranch<mode>4"
+ [(set (cc0)
+ (compare (match_operand:PDPint 1 "general_operand")
+ (match_operand:PDPint 2 "general_operand")))
+ (set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
(pc)))]
""
- "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+ "")
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+;; problem with too short jump distance! we need an assembler which can
+;; make this valid for all jump distances!
+;; e.g. gas!
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+;; these must be changed to check for CC_IN_FCCR if float is to be
+;; enabled
-(define_insn "ble"
+(define_insn "*branch"
[(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
(pc)))]
""
- "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+ "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
+ [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
(pc))
- (const_int -128))
- (ge (minus (match_dup 0)
+ (const_int MIN_BRANCH))
+ (gt (minus (match_dup 1)
(pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+ (const_int MAX_BRANCH)))
+ (const_int 6)
+ (const_int 2)))])
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-\f
;; These match inverted jump insns for register allocation.
-(define_insn ""
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
+(define_insn "*branch_inverted"
[(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(cc0) (const_int 0)])
(pc)
- (label_ref (match_operand 0 "" ""))))]
+ (label_ref (match_operand 1 "" ""))))]
""
- "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+ "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
+ [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
(pc))
- (const_int -128))
- (ge (minus (match_dup 0)
+ (const_int MIN_BRANCH))
+ (gt (minus (match_dup 1)
(pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
- [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
- (pc))
- (const_int -128))
- (ge (minus (match_dup 0)
- (pc))
- (const_int 128)))
- (const_int 3)
- (const_int 1)))])
+ (const_int MAX_BRANCH)))
+ (const_int 6)
+ (const_int 2)))])
\f
;; Move instructions
(define_insn "movdi"
- [(set (match_operand:DI 0 "general_operand" "=g,rm,m")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=g,rm,o")
(match_operand:DI 1 "general_operand" "m,r,a"))]
""
"* return output_move_quad (operands);"
;; what's the mose expensive code - say twice movsi = 16
- [(set_attr "length" "16,16,16")])
+ [(set_attr "length" "32,32,32")])
(define_insn "movsi"
- [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,rm,m")
(match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
""
"* return output_move_double (operands);"
;; what's the most expensive code ? - I think 8!
;; we could split it up and make several sub-cases...
- [(set_attr "length" "2,3,4,8,8")])
+ [(set_attr "length" "4,6,8,16,16")])
-(define_insn "movhi"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
- (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
+(define_insn "mov<mode>"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+ (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
""
"*
{
if (operands[1] == const0_rtx)
- return \"clr %0\";
+ return \"clr<PDPint:isfx> %0\";
- return \"mov %1, %0\";
+ return \"mov<PDPint:isfx> %1, %0\";
}"
- [(set_attr "length" "1,2,2,3")])
+ [(set_attr "length" "2,4,4,6")])
-(define_insn "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
- (match_operand:QI 1 "general_operand" "g"))]
- ""
- "*
-{
- if (operands[1] == const0_rtx)
- return \"clrb %0\";
-
- return \"movb %1, %0\";
-}"
- [(set_attr "length" "1")])
-
-;; do we have to supply all these moves? e.g. to
-;; NO_LOAD_FPU_REGs ?
(define_insn "movdf"
- [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,m")
- (match_operand:DF 1 "general_operand" "fFR,a,Q,a,m"))]
- ""
- "* if (which_alternative ==0)
+ [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+ (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
+ "TARGET_FPU"
+ "* if (which_alternative ==0 || which_alternative == 2)
return \"ldd %1, %0\";
- else if (which_alternative == 1)
+ else if (which_alternative == 1 || which_alternative == 3)
return \"std %1, %0\";
else
return output_move_quad (operands); "
;; just a guess..
- [(set_attr "length" "1,1,5,5,16")])
+ [(set_attr "length" "2,2,10,10,32")])
(define_insn "movsf"
- [(set (match_operand:SF 0 "general_operand" "=g,r,g")
- (match_operand:SF 1 "general_operand" "r,rmF,g"))]
+ [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+ (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
"TARGET_FPU"
- "* return output_move_double (operands);"
- [(set_attr "length" "8,8,8")])
+ "* if (which_alternative ==0 || which_alternative == 2)
+ return \"{ldcfd|movof} %1, %0\";
+ else if (which_alternative == 1 || which_alternative == 3)
+ return \"{stcdf|movfo} %1, %0\";
+ else
+ return output_move_double (operands); "
+;; just a guess..
+ [(set_attr "length" "2,2,10,10,16")])
;; maybe fiddle a bit with move_ratio, then
;; let constraints only accept a register ...
-(define_expand "movstrhi"
+(define_expand "movmemhi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
(match_operand:BLK 1 "general_operand" "g,g"))
- (use (match_operand:HI 2 "arith_operand" "n,&mr"))
+ (use (match_operand:HI 2 "general_operand" "n,&mr"))
(use (match_operand:HI 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 5))
}")
-(define_insn "" ; "movstrhi"
- [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
- (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
- (use (match_operand:HI 2 "arith_operand" "n,&r"))
+(define_insn "" ; "movmemhi"
+ [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
+ (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
+ (use (match_operand:HI 2 "general_operand" "+n,&r"))
(use (match_operand:HI 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X"))
(clobber (match_dup 0))
"(TARGET_BCOPY_BUILTIN)"
"* return output_block_move (operands);"
;;; just a guess
- [(set_attr "length" "40")])
+ [(set_attr "length" "80")])
\f
;;- truncation instructions
(define_insn "truncdfsf2"
- [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
- (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
+ [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
"TARGET_FPU"
"* if (which_alternative ==0)
{
- output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
- output_asm_insn(\"mov (sp)+, %0\", operands);
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
- output_asm_insn(\"mov (sp)+, %0\", operands);
return \"\";
}
else if (which_alternative == 1)
else
return \"{stcdf|movfo} %1, %0\";
"
- [(set_attr "length" "3,1,2")])
+ [(set_attr "length" "0,2,4")])
(define_expand "truncsihi2"
- [(set (match_operand:HI 0 "general_operand" "=g")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(subreg:HI
(match_operand:SI 1 "general_operand" "or")
0))]
;;- zero extension instructions
(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=r")
- (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
""
"bic $0177400, %0"
- [(set_attr "length" "2")])
+ [(set_attr "length" "4,6")])
(define_expand "zero_extendhisi2"
[(set (subreg:HI
;;- sign extension instructions
(define_insn "extendsfdf2"
- [(set (match_operand:DF 0 "register_operand" "=a,a,a")
- (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
+ [(set (match_operand:DF 0 "register_operand" "=f,a,a")
+ (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
"TARGET_FPU"
"@
- mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
+ /* nothing */
{ldcfd|movof} %1, %0
{ldcfd|movof} %1, %0"
- [(set_attr "length" "2,1,2")])
+ [(set_attr "length" "0,2,4")])
;; does movb sign extend in register-to-register move?
(define_insn "extendqihi2"
(sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
""
"movb %1, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
return \"\";
}"
- [(set_attr "length" "2,3")])
+ [(set_attr "length" "4,6")])
;; maybe we have to use define_expand to say that we have the instruction,
;; unconditionally, and then match dependent on CPU type:
(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=g")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
""
"")
(define_insn "" ; "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=o,<,r")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
(sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
"TARGET_40_PLUS"
"*
default:
- abort();
+ gcc_unreachable ();
}
}"
- [(set_attr "length" "5,3,3")])
+ [(set_attr "length" "10,6,6")])
(define_insn ""
return \"\";
}"
- [(set_attr "length" "6")])
+ [(set_attr "length" "12")])
;; make float to int and vice versa
;; using the cc_status.flag field we could probably cut down
else
return \"setl\;{ldcld|movif} %1, %0\;seti\";
"
- [(set_attr "length" "5,3,4")])
+ [(set_attr "length" "10,6,8")])
(define_insn "floathidf2"
[(set (match_operand:DF 0 "register_operand" "=a,a")
(float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
"TARGET_FPU"
"{ldcid|movif} %1, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; cut float to int
(define_insn "fix_truncdfsi2"
- [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
"TARGET_FPU"
"* if (which_alternative ==0)
else
return \"setl\;{stcdl|movfi} %1, %0\;seti\";
"
- [(set_attr "length" "5,3,4")])
+ [(set_attr "length" "10,6,8")])
(define_insn "fix_truncdfhi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
"TARGET_FPU"
"{stcdi|movfi} %1, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
\f
;;- arithmetic instructions
(match_operand:DF 2 "general_operand" "fR,Q,F")))]
"TARGET_FPU"
"{addd|addf} %2, %0"
- [(set_attr "length" "1,2,5")])
+ [(set_attr "length" "2,4,10")])
(define_insn "addsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o,r,r,r,o,o,o")
(plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
(match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
""
return \"\";
}"
- [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
+ [(set_attr "length" "6,10,12,16,6,2,10,10,6,16")])
(define_insn "addhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
(match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
""
return \"add %2, %0\";
}"
- [(set_attr "length" "1,2,2,3")])
-
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
- (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
- (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
- ""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL(operands[2]) == 1)
- return \"incb %0\";
- else if (INTVAL(operands[2]) == -1)
- return \"decb %0\";
- }
-
- return \"add %2, %0\";
-}"
- [(set_attr "length" "1,2,2,3")])
+ [(set_attr "length" "2,4,4,6")])
\f
;;- subtract instructions
(match_operand:DF 2 "general_operand" "fR,Q")))]
"TARGET_FPU"
"{subd|subf} %2, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
(define_insn "subsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
(minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
(match_operand:SI 2 "general_operand" "r,o,r,o")))]
""
return \"\";
}"
;; offsettable memory addresses always are expensive!!!
- [(set_attr "length" "3,5,6,8")])
+ [(set_attr "length" "6,10,12,16")])
(define_insn "subhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
(minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
(match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
""
"*
{
- if (GET_CODE (operands[2]) == CONST_INT)
- abort();
-
- return \"sub %2, %0\";
-}"
- [(set_attr "length" "1,2,2,3")])
-
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
- (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
- (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
- ""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- abort();
+ gcc_assert (GET_CODE (operands[2]) != CONST_INT);
return \"sub %2, %0\";
}"
- [(set_attr "length" "1,2,2,3")])
+ [(set_attr "length" "2,4,4,6")])
;;;;- and instructions
;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
- (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
- (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
- ""
- "*
-{ /* Here we trust that operands don't overlap
-
- or is lateoperands the low word?? - looks like it! */
-
- rtx lateoperands[3];
-
- lateoperands[0] = operands[0];
-
- if (REG_P (operands[0]))
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
- else
- operands[0] = adjust_address (operands[0], HImode, 2);
-
- if (! CONSTANT_P(operands[2]))
- {
- lateoperands[2] = operands[2];
-
- if (REG_P (operands[2]))
- operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
- else
- operands[2] = adjust_address (operands[2], HImode, 2);
-
- output_asm_insn (\"bic %2, %0\", operands);
- output_asm_insn (\"bic %2, %0\", lateoperands);
- return \"\";
- }
-
- lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
-
- /* these have different lengths, so we should have
- different constraints! */
- if (INTVAL(operands[2]))
- output_asm_insn (\"bic %2, %0\", operands);
-
- if (INTVAL(lateoperands[2]))
- output_asm_insn (\"bic %2, %0\", lateoperands);
-
- return \"\";
-}"
- [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
-
-(define_insn "andhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
- (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
- (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
- ""
- "bic %2, %0"
- [(set_attr "length" "1,2,2,3")])
-
-(define_insn "andqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
- (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
- (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
- ""
- "bicb %2, %0"
- [(set_attr "length" "1,2,2,3")])
-
-;;- Bit set (inclusive or) instructions
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
- (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
+(define_expand "and<mode>3"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
+ (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
+ (match_operand:PDPint 2 "general_operand" "")))]
""
- "*
-{ /* Here we trust that operands don't overlap
-
- or is lateoperands the low word?? - looks like it! */
-
- rtx lateoperands[3];
-
- lateoperands[0] = operands[0];
+ "
+{
+ rtx op1 = operands[1];
- if (REG_P (operands[0]))
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
- else
- operands[0] = adjust_address (operands[0], HImode, 2);
-
- if (! CONSTANT_P(operands[2]))
+ /* If there is a constant argument, complement that one.
+ Similarly, if one of the inputs is the same as the output,
+ complement the other input. */
+ if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
+ rtx_equal_p (operands[0], operands[1]))
{
- lateoperands[2] = operands[2];
-
- if (REG_P (operands[2]))
- operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
- else
- operands[2] = adjust_address (operands[2], HImode, 2);
-
- output_asm_insn (\"bis %2, %0\", operands);
- output_asm_insn (\"bis %2, %0\", lateoperands);
- return \"\";
+ operands[1] = operands[2];
+ operands[2] = op1;
+ op1 = operands[1];
}
- lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
-
- /* these have different lengths, so we should have
- different constraints! */
- if (INTVAL(operands[2]))
- output_asm_insn (\"bis %2, %0\", operands);
-
- if (INTVAL(lateoperands[2]))
- output_asm_insn (\"bis %2, %0\", lateoperands);
-
- return \"\";
-}"
- [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
+ if (CONST_INT_P (op1))
+ operands[1] = GEN_INT (~INTVAL (op1));
+ else
+ operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
+}")
-(define_insn "iorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
- (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
- (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
+(define_insn "*bic<mode>"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+ (and:PDPint
+ (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
+ (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
""
- "bis %2, %0"
- [(set_attr "length" "1,2,2,3")])
+ "bic<PDPint:isfx> %1, %0"
+ [(set_attr "length" "2,4,4,6")])
-(define_insn "iorqi3"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
- (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
+;;- Bit set (inclusive or) instructions
+(define_insn "ior<mode>3"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+ (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
+ (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
""
- "bisb %2, %0")
+ "bis<PDPint:isfx> %2, %0"
+ [(set_attr "length" "2,4,4,6")])
;;- xor instructions
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "arith_operand" "r")))]
- "TARGET_40_PLUS"
- "*
-{ /* Here we trust that operands don't overlap */
-
- rtx lateoperands[3];
-
- lateoperands[0] = operands[0];
- operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
-
- if (REG_P(operands[2]))
- {
- lateoperands[2] = operands[2];
- operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
-
- output_asm_insn (\"xor %2, %0\", operands);
- output_asm_insn (\"xor %2, %0\", lateoperands);
-
- return \"\";
- }
-
-}"
- [(set_attr "length" "2")])
-
(define_insn "xorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "register_operand" "r,r")))]
"TARGET_40_PLUS"
"xor %2, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;;- one complement instructions
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
- (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
+ (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
""
- "com %0"
- [(set_attr "length" "1,2")])
-
-(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "general_operand" "=rR,rR")
- (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
- ""
- "@
- comb %0
- movb %1, %0\; comb %0"
- [(set_attr "length" "1,2")])
+ "com<PDPint:isfx> %0"
+ [(set_attr "length" "2,4")])
;;- arithmetic shift instructions
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:HI 2 "general_operand" "rR,Qi")))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"ashc %2,%0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; Arithmetic right shift on the pdp works by negating the shift count.
(define_expand "ashrsi3"
;; asl
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(ashift:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int 1)))]
""
"asl %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; and another possibility for asr is << -1
;; might cause problems since -1 can also be encoded as 65535!
;; asr
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(ashift:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int -1)))]
""
"asr %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; lsr
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+(define_insn "lsrhi1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
(const_int 1)))]
""
"clc\;ror %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
-(define_insn "lshrsi3"
+(define_insn "lsrsi1"
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
(const_int 1)))]
""
-{ /* Here we trust that operands don't overlap */
+{
rtx lateoperands[2];
return \"\";
}
- [(set_attr "length" "5")])
+ [(set_attr "length" "10")])
+
+(define_expand "lshrsi3"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "0")
+ (match_operand:HI 2 "general_operand" "")]
+ ""
+ "
+{
+ rtx r;
+
+ if (!TARGET_40_PLUS &&
+ (GET_CODE (operands[2]) != CONST_INT ||
+ (unsigned) INTVAL (operands[2]) > 3))
+ FAIL;
+ emit_insn (gen_lsrsi1 (operands[0], operands[1]));
+ if (GET_CODE (operands[2]) != CONST_INT)
+ {
+ r = gen_reg_rtx (HImode);
+ emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
+ emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
+ }
+ else if ((unsigned) INTVAL (operands[2]) != 1)
+ {
+ emit_insn (gen_ashlsi3 (operands[0], operands[0],
+ GEN_INT (1 - INTVAL (operands[2]))));
+ }
+ DONE;
+}
+"
+)
;; shift is by arbitrary count is expensive,
;; shift by one cheap - so let's do that, if
;; space doesn't matter
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=r")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
(ashift:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "expand_shift_operand" "O")))]
"! optimize_size"
return \"\";
}"
;; longest is 4
- [(set (attr "length") (const_int 4))])
+ [(set (attr "length") (const_int 8))])
;; aslb
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=r,o")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
(ashift:QI (match_operand:QI 1 "general_operand" "0,0")
- (match_operand:HI 2 "const_immediate_operand" "n,n")))]
+ (match_operand:HI 2 "const_int_operand" "n,n")))]
""
"*
{ /* allowing predec or post_inc is possible, but hairy! */
}"
;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
[(set_attr_alternative "length"
- [(const_int 7)
- (const_int 14)])])
+ [(const_int 14)
+ (const_int 28)])])
;;; asr
;(define_insn ""
-; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
; (const_int 1)))]
; ""
; "asr %0"
-; [(set_attr "length" "1,2")])
+; [(set_attr "length" "2,4")])
;; asrb
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=r,o")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
(ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
- (match_operand:HI 2 "const_immediate_operand" "n,n")))]
+ (match_operand:HI 2 "const_int_operand" "n,n")))]
""
"*
{ /* allowing predec or post_inc is possible, but hairy! */
return \"\";
}"
[(set_attr_alternative "length"
- [(const_int 7)
- (const_int 14)])])
+ [(const_int 14)
+ (const_int 28)])])
;; the following is invalid - too complex!!! - just say 14 !!!
; [(set (attr "length") (plus (and (match_dup 2)
-; (const_int 7))
+; (const_int 14))
; (and (match_dup 2)
-; (const_int 7))))])
+; (const_int 14))))])
[(set (match_operand:HI 0 "register_operand" "=r,r")
(ashift:HI (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "general_operand" "rR,Qi")))]
- ""
+ "TARGET_40_PLUS"
"*
{
if (GET_CODE(operands[2]) == CONST_INT)
return \"ash %2,%0\";
}"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; Arithmetic right shift on the pdp works by negating the shift count.
(define_expand "ashrhi3"
operands[2] = negate_rtx (HImode, operands[2]);
}")
-;;;;- logical shift instructions
-;;(define_insn "lshrsi3"
-;; [(set (match_operand:HI 0 "register_operand" "=r")
-;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
-;; (match_operand:HI 2 "arith_operand" "rI")))]
-;; ""
-;; "srl %0,%2")
+(define_expand "lshrhi3"
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "general_operand" "")]
+ ""
+ "
+{
+ rtx r;
+
+ if (!TARGET_40_PLUS &&
+ (GET_CODE (operands[2]) != CONST_INT ||
+ (unsigned) INTVAL (operands[2]) > 3))
+ FAIL;
+ emit_insn (gen_lsrhi1 (operands[0], operands[1]));
+ if (GET_CODE (operands[2]) != CONST_INT)
+ {
+ r = gen_reg_rtx (HImode);
+ emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
+ emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
+ }
+ else if ((unsigned) INTVAL (operands[2]) != 1)
+ {
+ emit_insn (gen_ashlhi3 (operands[0], operands[0],
+ GEN_INT (1 - INTVAL (operands[2]))));
+ }
+ DONE;
+}
+"
+)
;; absolute
(define_insn "absdf2"
- [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
(abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
"TARGET_FPU"
"{absd|absf} %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
(define_insn "abshi2"
- [(set (match_operand:HI 0 "general_operand" "=r,o")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,o")
(abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
- "TARGET_ABSHI_BUILTIN"
+ ""
"*
{
static int count = 0;
return \"\";
}"
- [(set_attr "length" "3,5")])
+ [(set_attr "length" "6,10")])
;; define expand abshi - is much better !!! - but
; -- just a thought - don't have time to check
;
;(define_expand "abshi2"
-; [(match_operand:HI 0 "general_operand" "")
+; [(match_operand:HI 0 "nonimmediate_operand" "")
; (match_operand:HI 1 "general_operand" "")]
; ""
; "
;
; /* allow REG_NOTES to be set on last insn (labels don't have enough
; fields, and can't be used for REG_NOTES anyway). */
-; emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+; emit_use (stack_pointer_rtx);
; DONE;
;}")
;; negate insns
(define_insn "negdf2"
- [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+ [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
(neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
"TARGET_FPU"
"{negd|negf} %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
""
-{ /* Here we trust that operands don't overlap */
+{
rtx lateoperands[2];
lateoperands[1] = operands[1];
operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
- output_asm_insn (\"com %0\", operands);
output_asm_insn (\"com %0\", lateoperands);
- output_asm_insn (\"inc %0\", operands);
+ output_asm_insn (\"com %0\", operands);
+ output_asm_insn (\"add $1, %0\", operands);
output_asm_insn (\"adc %0\", lateoperands);
return \"\";
}
- [(set_attr "length" "5")])
+ [(set_attr "length" "14")])
(define_insn "neghi2"
- [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
(neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
""
"neg %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
(define_insn "negqi2"
- [(set (match_operand:QI 0 "general_operand" "=rR,Q")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
(neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
""
"negb %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; Unconditional and other jump instructions
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
- "jmp %l0"
- [(set_attr "length" "2")])
+ "*
+{
+ if (get_attr_length (insn) == 2)
+ return \"br %l0\";
+ return \"jmp %l0\";
+}"
+ [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
+ (pc))
+ (const_int MIN_BRANCH))
+ (gt (minus (match_dup 0)
+ (pc))
+ (const_int MAX_BRANCH)))
+ (const_int 4)
+ (const_int 2)))])
(define_insn ""
[(set (pc)
(clobber (const_int 1))]
""
"jmp %l0"
- [(set_attr "length" "2")])
+ [(set_attr "length" "4")])
(define_insn "tablejump"
[(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
(use (label_ref (match_operand 1 "" "")))]
""
"jmp %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; indirect jump - let's be conservative!
;; allow only register_operand, even though we could also
;;- Don't use operand 1 for most machines.
""
"jsr pc, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;;- jump to subroutine
(define_insn "call_value"
;;- Don't use operand 2 for most machines.
""
"jsr pc, %1"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;;- nop instruction
(define_insn "nop"
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=a,a,a")
(mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
- (match_operand:DF 2 "general_operand" "fR,Q,F")))]
+ (match_operand:DF 2 "float_operand" "fR,Q,F")))]
"TARGET_FPU"
"{muld|mulf} %2, %0"
- [(set_attr "length" "1,2,5")])
+ [(set_attr "length" "2,4,10")])
;; 16 bit result multiply:
;; currently we multiply only into odd registers, so we don't use two
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
(mult:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "rR,Qi")))]
- "TARGET_45"
+ (match_operand:HI 2 "float_operand" "rR,Qi")))]
+ "TARGET_40_PLUS"
"mul %2, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;; 32 bit result
(define_expand "mulhisi3"
[(set (match_dup 3)
- (match_operand:HI 1 "general_operand" "g,g"))
+ (match_operand:HI 1 "nonimmediate_operand" "g,g"))
(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
(mult:SI (truncate:HI
(match_dup 0))
(match_operand:HI 2 "general_operand" "rR,Qi")))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"operands[3] = gen_lowpart(HImode, operands[1]);")
(define_insn ""
(mult:SI (truncate:HI
(match_operand:SI 1 "register_operand" "%0,0"))
(match_operand:HI 2 "general_operand" "rR,Qi")))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"mul %2, %0"
- [(set_attr "length" "1,2")])
+ [(set_attr "length" "2,4")])
;(define_insn "mulhisi3"
; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
; (mult:SI (truncate:HI
; (match_operand:SI 1 "register_operand" "%0,0"))
; (match_operand:HI 2 "general_operand" "rR,Qi")))]
-; "TARGET_45"
+; "TARGET_40_PLUS"
; "mul %2, %0"
-; [(set_attr "length" "1,2")])
+; [(set_attr "length" "2,4")])
;;- divide
(define_insn "divdf3"
(match_operand:DF 2 "general_operand" "fR,Q,F")))]
"TARGET_FPU"
"{divd|divf} %2, %0"
- [(set_attr "length" "1,2,5")])
+ [(set_attr "length" "2,4,10")])
(define_expand "divhi3"
[(set (subreg:HI (match_dup 1) 0)
- (div:HI (match_operand:SI 1 "general_operand" "0")
+ (div:HI (match_operand:SI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
- (set (match_operand:HI 0 "general_operand" "=r")
+ (set (match_operand:HI 0 "register_operand" "=r")
(subreg:HI (match_dup 1) 0))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"")
(define_insn ""
- [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+ [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
(div:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"div %2,%0"
- [(set_attr "length" "2")])
+ [(set_attr "length" "4")])
(define_expand "modhi3"
[(set (subreg:HI (match_dup 1) 2)
- (mod:HI (match_operand:SI 1 "general_operand" "0")
+ (mod:HI (match_operand:SI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
- (set (match_operand:HI 0 "general_operand" "=r")
+ (set (match_operand:HI 0 "register_operand" "=r")
(subreg:HI (match_dup 1) 2))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"")
(define_insn ""
- [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
+ [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
- "TARGET_45"
+ "TARGET_40_PLUS"
"div %2,%0"
- [(set_attr "length" "2")])
+ [(set_attr "length" "4")])
;(define_expand "divmodhi4"
; [(parallel [(set (subreg:HI (match_dup 1) 0)
-; (div:HI (match_operand:SI 1 "general_operand" "0")
+; (div:HI (match_operand:SI 1 "register_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 1) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))])
-; (set (match_operand:HI 3 "general_operand" "=r")
+; (set (match_operand:HI 3 "register_operand" "=r")
; (subreg:HI (match_dup 1) 2))
-; (set (match_operand:HI 0 "general_operand" "=r")
+; (set (match_operand:HI 0 "register_operand" "=r")
; (subreg:HI (match_dup 1) 0))]
-; "TARGET_45"
+; "TARGET_40_PLUS"
; "")
;
;(define_insn ""
-; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 0) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))]
-; "TARGET_45"
+; "TARGET_40_PLUS"
; "div %2, %0")
;