(define_expand "m88k_sccs_id"
[(match_operand:SI 0 "" "")]
""
- "{ static char sccs_id[] = \"@(#)m88k.md 2.0.3.3 18 Mar 1992 15:40:12\";
+ "{ static char sccs_id[] = \"@(#)m88k.md 2.2.7.5 08/24/92 10:41:24\";
FAIL; }")
\f
;; Attribute specifications
; Target CPU.
-(define_attr "cpu" "m88000,m88100,m88110"
+(define_attr "cpu" "m88100,m88110,m88000"
(const (symbol_ref "m88k_cpu")))
; Type of each instruction. Default is arithmetic.
; I'd like to write the list as this, but genattrtab won't accept it.
;
; "branch,jump,call, ; flow-control instructions
-; load,store,loada, ; data unit instructions
-; spadd,dpadd,spdiv,dpdiv,idiv, ; FPU add instructions
+; load,store,loadd,loada, ; data unit instructions
+; spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions
; spmul,dpmul,imul, ; FPU multiply instructions
-; arith, ; integer unit instructions
-; marith,mstore,mfp,weird" ; multi-word instructions
+; arith,bit,mov ; integer unit instructions
+; marith,weird" ; multi-word instructions
; Classification of each insn. Some insns of TYPE_BRANCH are multi-word.
(define_attr "type"
- "branch,jump,call,load,store,loada,spadd,dpadd,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,marith,mstore,mfp,weird"
+ "branch,jump,call,load,store,loadd,loada,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,weird"
(const_string "arith"))
-; Convenience attributes.
(define_attr "fpu" "yes,no"
(if_then_else
- (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spdiv,dpdiv,idiv,mfp")
+ (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv")
(const_string "yes") (const_string "no")))
; Length in # of instructions of each insn. The values are not exact, but
; are safe.
(define_attr "length" ""
- (cond [(eq_attr "type" "marith,mstore,mfp")
+ (cond [(eq_attr "type" "marith")
(const_int 2)]
(const_int 1)))
(define_delay (eq_attr "type" "branch,jump")
[(and
(and
- (eq_attr "type" "!branch,jump,call,marith,mstore,mfp,weird") ; required.
- (eq_attr "type" "!load")) ; issue as-soon-as-possible.
+ (eq_attr "type" "!branch,jump,call,marith,weird") ; required.
+ (eq_attr "type" "!load,loadd")) ; issue as-soon-as-possible.
(eq_attr "fpu" "no")) ; issue as-soon-as-possible.
(eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1)
; a call. (@@ Support for this case is expected in reorg.c soon.)
(define_delay (eq_attr "type" "call")
- [(eq_attr "type" "!branch,call,marith,mstore,mfp,weird") ; required.
+ [(eq_attr "type" "!branch,call,marith,weird") ; required.
(nil) (nil)])
\f
; An abstract block diagram of the function units for the m88100.
; Consideration of writeback contention is critical to superb scheduling.
;
; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
-; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST])
+; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
-;(define_function_unit "decode" 1 1 (const_int 1) 0 1)
-
-; Describing the alu is currently not useful.
+; Describing the '100 alu is currently not useful.
;(define_function_unit "alu" 1 0 (eq_attr "type"
-; "!store,mstore,marith,mfp,weird") 1 0)
+; "!store,marith,weird") 1 0)
;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0)
-(define_function_unit "memory" 1 3 (eq_attr "type" "load") 3 2)
-
-; The fp1 and fplast descriptions currently have no effect.
-;(define_function_unit "fp1" 1 1 (eq_attr "fpu" "yes") 1 2)
+(define_function_unit "alu" 1 0
+ (and (eq_attr "type" "loada,arith,mov") (eq_attr "cpu" "!m88100")) 2 0)
+(define_function_unit "alu" 1 0
+ (and (eq_attr "type" "marith,weird") (eq_attr "cpu" "!m88100")) 4 0)
+
+(define_function_unit "bit" 1 0
+ (and (eq_attr "type" "bit") (eq_attr "cpu" "!m88100")) 2 2)
+
+(define_function_unit "mem100" 1 0
+ (and (eq_attr "type" "store,loada") (eq_attr "cpu" "m88100")) 1 0)
+(define_function_unit "mem100" 1 0
+ (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 0)
+(define_function_unit "mem100" 1 0
+ (and (eq_attr "type" "loadd") (eq_attr "cpu" "m88100")) 3 2
+ [(eq_attr "type" "load,store,loadd,loada")])
+
+(define_function_unit "mem110" 1 0
+ (and (eq_attr "type" "load") (eq_attr "cpu" "!m88100")) 3 2)
+(define_function_unit "mem110" 1 0
+ (and (eq_attr "type" "loadd") (eq_attr "cpu" "!m88100")) 3 3
+ [(eq_attr "type" "load")])
+(define_function_unit "mem110" 1 0
+ (and (eq_attr "type" "loadd") (eq_attr "cpu" "!m88100")) 3 2
+ [(eq_attr "type" "!load")])
+(define_function_unit "mem110" 1 0
+ (and (eq_attr "type" "store") (eq_attr "cpu" "!m88100")) 0 2)
; The times are adjusted to include fp1 and fplast, but then are further
; adjusted based on the actual generated code. The notation to the right
; is the total latency. A range denotes a group of instructions and/or
; conditions (the extra clock of fplast time with some sequences).
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "spmul") 4 2) ; 6-8
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "dpmul,mfp") 7 2) ; 9-10
-(define_function_unit "fpmul" 1 4 (eq_attr "type" "imul") 3 2) ; 4
-
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "spadd") 3 2) ; 5-6
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "dpadd") 4 2) ; 6-7
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "spdiv") 30 2) ; 30-31
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "dpdiv") 60 2) ; 60-61
-(define_function_unit "fpadd" 1 3 (eq_attr "type" "idiv") 38 2) ; 38
-
-;(define_function_unit "fplast" 1 1 (eq_attr "fpu" "yes") 1 2)
-
-; Describing writeback contention is currently not useful.
-;(define_function_unit "writeback" 1 1
-; (eq_attr "type" "!store,mstore,branch,jump,call") 0 1)
-
-; Describing stores is currently not useful. The suggestion here is that the
-; function unit ordering has already been established (writeback is last) and
-; that store insns use the units in an unusual order.
-;(define_function_unit "writeback" 1 1 (eq_attr "type" "store,mstore") 0 1)
-;(define_function_unit "memory" 1 3 (eq_attr "type" "store,mstore") 1 2)
+
+(define_function_unit "fpmul100" 1 0
+ (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 0) ; 6-8
+(define_function_unit "fpmul100" 1 0
+ (and (eq_attr "type" "dpmul") (eq_attr "cpu" "m88100")) 7 0) ; 9-10
+(define_function_unit "fpmul100" 1 0
+ (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 0) ; 4
+
+(define_function_unit "fpmul110" 1 0
+ (and (eq_attr "type" "imul,spmul,dpmul")
+ (eq_attr "cpu" "!m88100")) 5 2) ; 3
+
+(define_function_unit "fpadd100" 1 5
+ (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 0) ; 5-6
+(define_function_unit "fpadd100" 1 5
+ (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 0) ; 6-7
+
+(define_function_unit "fpadd110" 1 0
+ (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 5 2) ; 3
+(define_function_unit "fpadd110" 1 0
+ (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2) ; 1
+
+(define_function_unit "fpadd100" 1 5
+ (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 0) ; 30-31
+(define_function_unit "fpadd100" 1 5
+ (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 0) ; 60-61
+(define_function_unit "fpadd100" 1 5
+ (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 0) ; 38
+
+(define_function_unit "div" 1 1
+ (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 25 2) ; 13
+(define_function_unit "div" 1 1
+ (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 45 2) ; 23
+(define_function_unit "div" 1 1
+ (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 35 2) ; 18
+\f
+;; Superoptimizer sequences
+
+;; geu+: { r = ((unsigned_word) v0 >= (unsigned_word) v1) + v2; }
+;; subu.co r5,r2,r3
+;; addu.cio r6,r4,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (geu:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "register_operand" "r"))))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+ (set (match_dup 0)
+ (plus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 0)))]
+ "")
+
+;; leu+: { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; }
+;; subu.co r5,r3,r2
+;; addu.cio r6,r4,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (leu:SI (match_operand:SI 3 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+ (set (match_dup 0)
+ (plus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 0)))]
+ "")
+
+;; eq0+: { r = (v0 == 0) + v1; }
+;; subu.co r4,r0,r2
+;; addu.cio r5,r3,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (eq:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 0))))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1))
+ (set (match_dup 0)
+ (plus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 0)))]
+ "")
+
+;; ltu-: { r = v2 - ((unsigned_word) v0 < (unsigned_word) v1); }
+;; subu.co r5,r2,r3
+;; subu.cio r6,r4,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (ltu:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "register_operand" "r"))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+ (set (match_dup 0)
+ (minus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 1)))]
+ "")
+
+;; gtu-: { r = v2 - ((unsigned_word) v0 > (unsigned_word) v1); }
+;; subu.co r5,r3,r2
+;; subu.cio r6,r4,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (gtu:SI (match_operand:SI 3 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 3)] 1))
+ (set (match_dup 0)
+ (minus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 1)))]
+ "")
+
+;; ne0-: { r = v1 - (v0 != 0); }
+;; subu.co r4,r0,r2
+;; subu.cio r5,r3,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (ne:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 0))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(const_int 0) (match_dup 2)] 1))
+ (set (match_dup 0)
+ (minus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 1)))]
+ "")
+
+;; ges0-: { r = v1 - ((signed_word) v0 >= 0); }
+;; addu.co r4,r2,r2
+;; subu.cio r5,r3,r0
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (xor:SI (lshiftrt:SI
+ (match_operand:SI 2 "register_operand" "r")
+ (const_int 31))
+ (const_int 1))))]
+ ""
+ [(set (reg:CC 0) (unspec:CC [(match_dup 2) (match_dup 2)] 0))
+ (set (match_dup 0)
+ (minus:SI (match_dup 1)
+ (unspec:SI [(const_int 0)
+ (reg:CC 0)] 1)))]
+ "")
\f
;; This rich set of complex patterns are mostly due to Torbjorn Granlund
;; (tege@sics.se). They've changed since then, so don't complain to him
operands[4] = gen_rtx (CONST_INT, SImode,
INTVAL (operands[3]) - INTVAL (operands[2]));
return \"ext %0,%1,%w3<%4>\"; /* <(%3-%2)> */
-}")
+}"
+ [(set_attr "type" "bit")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
operands[4] = gen_rtx (CONST_INT, SImode,
INTVAL (operands[3]) - INTVAL (operands[2]));
return \"extu %0,%1,%w3<%4>\"; /* <(%3-%2)> */
-}")
+}"
+ [(set_attr "type" "bit")])
;; Optimize possible cases of the set instruction.
(ashift:SI (const_int -1)
(match_operand:SI 1 "register_operand" "r")))]
""
- "set %0,%#r0,%1")
+ "set %0,%#r0,%1"
+ [(set_attr "type" "bit")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "register_operand" "r"))
(match_operand:SI 2 "register_operand" "r")))]
""
- "set %0,%2,%1")
+ "set %0,%2,%1"
+ [(set_attr "type" "bit")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (const_int -1)
(match_operand:SI 2 "register_operand" "r"))))]
""
- "set %0,%1,%2")
+ "set %0,%1,%2"
+ [(set_attr "type" "bit")])
;; Optimize possible cases of the mak instruction.
exact_log2 (1 + (INTVAL (operands[3])
>> INTVAL(operands[2]))));
return \"mak %0,%1,%4<%2>\";
-}")
+}"
+ [(set_attr "type" "bit")])
;; Optimize possible cases of output_and.
((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[4]));
return output_and (operands);
}"
- [(set_attr "type" "marith")]) ; length is 1 or 2.
+ [(set_attr "type" "marith")]) ; arith,bit,marith. length is 1 or 2.
+\f
+;; Improve logical operations on compare words
+;;
+;; We define all logical operations on CCmode values to preserve the pairwise
+;; relationship of the compare bits. This allows a future branch prediction
+;; pass the degree of freedom needed to change and/bb0-le into or/bb1-gt.
+;;
+;; Opportunities arise when conditional expressions using && and || are made
+;; unconditional. When these are used to branch, the sequence is
+;; cmp/cmp/extu/extu/{and,or}/bcnd-{eq0,ne0}. When these are used to create
+;; a value, the sequence is cmp/cmp/extu/extu/{and,or} for 1 or 0 or
+;; cmp/cmp/ext/ext/{and,or} for -1 or 0.
+;;
+;; When the extracted conditions are the same, the define_split patterns
+;; below change extu/extu/{and,or} into {and,or}/extu. If the reversed
+;; conditions match, one compare word can be complimented, resulting in
+;; {and.c,or.c}/extu. These changes are done for ext/ext/{and,or} as well.
+;; If the conditions don't line up, one can be rotated. To keep the pairwise
+;; relationship, it may be necessary to both rotate and compliment. Rotating
+;; makes branching cheaper, but doesn't help (or hurt) creating a value, so
+;; we don't do this for ext/ext/{and,or}.
+;;
+;; These changes result in the sequence extu/bcnd-{eq0,ne0} which is combined
+;; into an alternate form of bb0 and bb1.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (neg:SI
+ (match_operator 1 "relop"
+ [(match_operand:CC 2 "register_operand" "%r")
+ (const_int 0)]))
+ (neg:SI
+ (match_operator 3 "relop"
+ [(match_operand:CC 4 "register_operand" "r")
+ (const_int 0)]))))
+ (clobber (match_operand:SI 5 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 5)
+ (ior:CC (match_dup 4)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+ "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0);
+ if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+ ; /* The conditions match. */
+ else if (GET_CODE (operands[1])
+ == reverse_condition (GET_CODE (operands[3])))
+ /* Reverse the condition by complimenting the compare word. */
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+ else
+ {
+ /* Make the condition pairs line up by rotating the compare word. */
+ int cv1 = condition_value (operands[1]);
+ int cv2 = condition_value (operands[3]);
+
+ operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+ gen_rtx (CONST_INT, VOIDmode,
+ ((cv2 & ~1) - (cv1 & ~1)) & 0x1f));
+ /* Reverse the condition if needed. */
+ if ((cv1 & 1) != (cv2 & 1))
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+ }")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operator 1 "relop"
+ [(match_operand:CC 2 "register_operand" "%r")
+ (const_int 0)])
+ (match_operator 3 "relop"
+ [(match_operand:CC 4 "register_operand" "r")
+ (const_int 0)])))
+ (clobber (match_operand:SI 5 "register_operand" "=r"))]
+ "GET_CODE (operands[1]) == GET_CODE (operands[3])
+ || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+ [(set (match_dup 5)
+ (ior:CC (match_dup 4)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+ "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0);
+ /* Reverse the condition by complimenting the compare word. */
+ if (GET_CODE (operands[1]) != GET_CODE (operands[3]))
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (neg:SI
+ (match_operator 1 "relop"
+ [(match_operand:CC 2 "register_operand" "%r")
+ (const_int 0)]))
+ (neg:SI
+ (match_operator 3 "relop"
+ [(match_operand:CC 4 "register_operand" "r")
+ (const_int 0)]))))
+ (clobber (match_operand:SI 5 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 5)
+ (and:CC (match_dup 4)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (neg:SI (match_op_dup 1 [(match_dup 5) (const_int 0)])))]
+ "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0);
+ if (GET_CODE (operands[1]) == GET_CODE (operands[3]))
+ ; /* The conditions match. */
+ else if (GET_CODE (operands[1])
+ == reverse_condition (GET_CODE (operands[3])))
+ /* Reverse the condition by complimenting the compare word. */
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+ else
+ {
+ /* Make the condition pairs line up by rotating the compare word. */
+ int cv1 = condition_value (operands[1]);
+ int cv2 = condition_value (operands[3]);
+
+ operands[4] = gen_rtx (ROTATE, CCmode, operands[4],
+ gen_rtx (CONST_INT, VOIDmode,
+ ((cv2 & ~1) - (cv1 & ~1)) & 0x1f));
+ /* Reverse the condition if needed. */
+ if ((cv1 & 1) != (cv2 & 1))
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);
+ }")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operator 1 "relop"
+ [(match_operand:CC 2 "register_operand" "%r")
+ (const_int 0)])
+ (match_operator 3 "relop"
+ [(match_operand:CC 4 "register_operand" "r")
+ (const_int 0)])))
+ (clobber (match_operand:SI 5 "register_operand" "=r"))]
+ "GET_CODE (operands[1]) == GET_CODE (operands[3])
+ || GET_CODE (operands[1]) == reverse_condition (GET_CODE (operands[3]))"
+ [(set (match_dup 5)
+ (and:CC (match_dup 4)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (match_op_dup 1 [(match_dup 5) (const_int 0)]))]
+ "operands[5] = gen_rtx (SUBREG, CCmode, operands[5], 0);
+ /* Reverse the condition by complimenting the compare word. */
+ if (GET_CODE (operands[1]) != GET_CODE (operands[3]))
+ operands[4] = gen_rtx (NOT, CCmode, operands[4]);")
+\f
+;; Logical operations on compare words.
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (not:CC (match_operand:CC 1 "register_operand" "r"))
+ (match_operand:CC 2 "register_operand" "r")))]
+ ""
+ "and.c %0,%2,%1")
+
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (match_operand:CC 1 "register_operand" "%r")
+ (match_operand:CC 2 "register_operand" "r")))]
+ ""
+ "and %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (not:CC (match_operand:CC 1 "register_operand" "r"))
+ (match_operand:CC 2 "register_operand" "r")))]
+ ""
+ "or.c %0,%2,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (match_operand:CC 1 "register_operand" "%r")
+ (match_operand:CC 2 "register_operand" "r")))]
+ ""
+ "or %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" "")))]
+ ""
+ "rot %0,%1,%2"
+ [(set_attr "type" "bit")])
+
+;; rotate/and[.c] and rotate/ior[.c]
+
+(define_split
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" ""))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_operand:CC 4 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 4)
+ (rotate:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (ior:CC (match_dup 4) (match_dup 3)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" ""))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_scratch:CC 4 "=r"))]
+ ""
+ "#")
+
+(define_split
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" "")))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_operand:CC 4 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 4)
+ (rotate:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (ior:CC (not:CC (match_dup 4)) (match_dup 3)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (ior:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" "")))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_scratch:CC 4 "=r"))]
+ ""
+ "#")
+
+(define_split
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" ""))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_operand:CC 4 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 4)
+ (rotate:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (and:CC (match_dup 4) (match_dup 3)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" ""))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_scratch:CC 4 "=r"))]
+ ""
+ "#")
+
+(define_split
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" "")))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_operand:CC 4 "register_operand" "=r"))]
+ ""
+ [(set (match_dup 4)
+ (rotate:CC (match_dup 1) (match_dup 2)))
+ (set (match_dup 0)
+ (and:CC (not:CC (match_dup 4)) (match_dup 3)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "register_operand" "=r")
+ (and:CC (not:CC (rotate:CC (match_operand:CC 1 "register_operand" "r")
+ (match_operand:CC 2 "int5_operand" "")))
+ (match_operand:CC 3 "register_operand" "r")))
+ (clobber (match_scratch:CC 4 "=r"))]
+ ""
+ "#")
\f
;; Recognize bcnd instructions for integer values. This is distinguished
;; from a conditional branch instruction (below) with SImode instead of
"cmp %0,%r1,%2")
(define_insn ""
- [(set (match_operand:CC 0 "register_operand" "=r,r")
- (compare:CC (match_operand:SF 1 "register_operand" "r,r")
- (match_operand:SF 2 "real_or_0_operand" "r,G")))]
+ [(set (match_operand:CC 0 "register_operand" "=r,r,r,r")
+ (compare:CC (match_operand:SF 1 "register_operand" "r,r,x,x")
+ (match_operand:SF 2 "real_or_0_operand" "r,G,x,G")))]
""
"@
fcmp.sss %0,%1,%2
- fcmp.sss %0,%1,%#r0"
- [(set_attr "type" "spadd")])
+ fcmp.sss %0,%1,%#r0
+ fcmp.sss %0,%1,%2
+ fcmp.sss %0,%1,%#x0"
+ [(set_attr "type" "spcmp")])
(define_insn ""
- [(set (match_operand:CC 0 "register_operand" "=r")
- (compare:CC (match_operand:DF 1 "register_operand" "r")
+ [(set (match_operand:CC 0 "register_operand" "=r,r")
+ (compare:CC (match_operand:DF 1 "register_operand" "r,x")
(float_extend:DF
- (match_operand:SF 2 "register_operand" "r"))))]
+ (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fcmp.sds %0,%1,%2"
- [(set_attr "type" "dpadd")])
+ [(set_attr "type" "dpcmp")])
(define_insn ""
- [(set (match_operand:CC 0 "register_operand" "=r")
+ [(set (match_operand:CC 0 "register_operand" "=r,r")
(compare:CC (float_extend:DF
- (match_operand:SF 1 "register_operand" "r"))
- (match_operand:DF 2 "register_operand" "r")))]
+ (match_operand:SF 1 "register_operand" "r,x"))
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fcmp.ssd %0,%1,%2"
- [(set_attr "type" "dpadd")])
+ [(set_attr "type" "dpcmp")])
(define_insn ""
- [(set (match_operand:CC 0 "register_operand" "=r,r")
- (compare:CC (match_operand:DF 1 "register_operand" "r,r")
- (match_operand:DF 2 "real_or_0_operand" "r,G")))]
+ [(set (match_operand:CC 0 "register_operand" "=r,r,r,r")
+ (compare:CC (match_operand:DF 1 "register_operand" "r,r,x,x")
+ (match_operand:DF 2 "real_or_0_operand" "r,G,x,G")))]
""
"@
fcmp.sdd %0,%1,%2
- fcmp.sds %0,%1,%#r0"
- [(set_attr "type" "dpadd")])
+ fcmp.sds %0,%1,%#r0
+ fcmp.sdd %0,%1,%2
+ fcmp.sds %0,%1,%#x0"
+ [(set_attr "type" "dpcmp")])
\f
;; Store condition code insns. The compare insns set a register
;; rather than cc0 and record that register for use here. See above
;; for the special treatment of cmpsi with a constant operand.
+;; @@ For the m88110, use fcmpu for bxx sxx inequality comparisons.
+
(define_expand "seq"
[(set (match_operand:SI 0 "register_operand" "")
(match_dup 1))]
[(match_operand:CC 2 "register_operand" "r")
(const_int 0)]))]
""
- "ext %0,%2,1<%C1>")
+ "ext %0,%2,1<%C1>"
+ [(set_attr "type" "bit")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
[(match_operand:CC 2 "register_operand" "r")
(const_int 0)])))]
""
- "extu %0,%2,1<%C1>")
+ "extu %0,%2,1<%C1>"
+ [(set_attr "type" "bit")])
\f
;; Conditional branch insns. The compare insns set a register
;; rather than cc0 and record that register for use here. See above
(match_operand 2 "pc_or_label_ref" "")
(match_operand 3 "pc_or_label_ref" "")))]
""
+ "*
+{
+ if (mostly_false_jump (insn, operands[0]))
+ return \"bb0%. %R2%C0,%1,%P2%P3\";
+ else
+ return \"bb1%. %R3%C0,%1,%P2%P3\";
+}"
+ [(set_attr "type" "branch")])
+
+;; Branch conditional on scc values. These arise from manipulations on
+;; compare words above.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (match_operator 0 "relop"
+ [(match_operand:CC 1 "register_operand" "r")
+ (const_int 0)])
+ (const_int 0))
+ (match_operand 2 "pc_or_label_ref" "")
+ (match_operand 3 "pc_or_label_ref" "")))]
+ ""
"bb1%. %R3%C0,%1,%P2%P3"
[(set_attr "type" "branch")])
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (match_operator 0 "relop"
+ [(match_operand:CC 1 "register_operand" "r")
+ (const_int 0)])
+ (const_int 0))
+ (match_operand 2 "pc_or_label_ref" "")
+ (match_operand 3 "pc_or_label_ref" "")))]
+ ""
+ "bb0%. %R3%C0,%1,%P2%P3"
+ [(set_attr "type" "branch")])
+\f
+(define_insn "locate1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (unspec:SI [(label_ref (match_operand 1 "" ""))] 0)))]
+ ""
+ "or.u %0,%#r0,%#hi16(%1#abdiff)")
+
+(define_insn "locate2"
+ [(parallel [(set (reg:SI 1) (pc))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_dup 0)
+ (unspec:SI
+ [(label_ref (match_operand 1 "" ""))] 0)))])]
+ ""
+ "bsr.n %1\;or %0,%0,%#lo16(%1#abdiff)\\n%1:"
+ [(set_attr "length" "2")])
\f
;; SImode move instructions
}")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r")
- (match_operand:SI 1 "move_operand" "rI,m,rO,J,M"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,x,x,x,m")
+ (match_operand:SI 1 "move_operand" "rI,m,rO,J,M,x,r,x,m,x"))]
"(register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| operands[1] == const0_rtx)"
ld %0,%1
st %r1,%0
subu %0,%#r0,%n1
- set %0,%#r0,%s1"
- [(set_attr "type" "arith,load,store,arith,arith")])
+ set %0,%#r0,%s1
+ mov.s %0,%1
+ mov.s %0,%1
+ mov %0,%1
+ ld %0,%1
+ st %1,%0"
+ [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
or.u %0,%#r0,%X1
set %0,%#r0,%s1
or.u %0,%#r0,%X1\;or %0,%0,%x1"
- [(set_attr "type" "arith,arith,arith,arith,marith")])
+ [(set_attr "type" "arith,arith,arith,bit,marith")])
;; @@ Why the constraint "in"? Doesn't `i' include `n'?
(define_insn ""
}")
(define_insn ""
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand" "=r,x")
(const_int 0))]
""
- "or %0,%#r0,0\;or %d0,%#r0,0"
- [(set_attr "type" "marith")])
+ "@
+ or %0,%#r0,0\;or %d0,%#r0,0
+ mov %0,%#x0"
+ [(set_attr "type" "marith,mov")])
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DI 1 "nonimmediate_operand" "r,m,r"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,x,x,x,m")
+ (match_operand:DI 1 "nonimmediate_operand" "r,m,r,x,r,x,m,x"))]
""
"@
or %0,%#r0,%1\;or %d0,%#r0,%d1
ld.d %0,%1
+ st.d %1,%0
+ mov.d %0,%1
+ mov.d %0,%1
+ mov %0,%1
+ ld.d %0,%1
st.d %1,%0"
- [(set_attr "type" "marith,load,store")])
+ [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
;}")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
(const_int 0))]
""
- "or %0,%#r0,0\;or %d0,%#r0,0"
- [(set_attr "type" "marith")])
+ "@
+ or %0,%#r0,0\;or %d0,%#r0,0
+ mov %0,%#x0"
+ [(set_attr "type" "marith,mov")])
(define_insn ""
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DF 1 "nonimmediate_operand" "r,m,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m")
+ (match_operand:DF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))]
""
"@
or %0,%#r0,%1\;or %d0,%#r0,%d1
ld.d %0,%1
+ st.d %1,%0
+ mov.d %0,%1
+ mov.d %0,%1
+ mov %0,%1
+ ld.d %0,%1
st.d %1,%0"
- [(set_attr "type" "marith,load,store")])
+ [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")])
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=r")
;; @@ What happens to fconst0_rtx?
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=r")
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
(const_int 0))]
""
- "or %0,%#r0,0")
+ "@
+ or %0,%#r0,0
+ mov %0,%#x0"
+ [(set_attr "type" "arith,mov")])
(define_insn ""
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,x,r,x,x,m")
+ (match_operand:SF 1 "nonimmediate_operand" "r,m,r,r,x,x,m,x"))]
""
"@
or %0,%#r0,%1
ld %0,%1
+ st %r1,%0
+ mov.s %0,%1
+ mov.s %0,%1
+ mov %0,%1
+ ld %0,%1
st %r1,%0"
- [(set_attr "type" "arith,load,store")])
+ [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")])
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=r")
;; operand 3 is the offset for the source and destination pointers
;; operand 4 is the first value to be loaded
;; operand 5 is the register to hold the value (r4 or r5)
-;; Upon completion, r2 and r3 are unchanged
(define_expand "call_block_move"
- [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
- (match_operand:SI 3 "immediate_operand" "i")))
- (set (match_operand 5 "register_operand" "r")
- (match_operand 4 "memory_operand" "m"))
- (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
+ [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "immediate_operand" "")))
+ (set (match_operand 5 "register_operand" "")
+ (match_operand 4 "memory_operand" ""))
+ (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "")
(match_dup 3)))
(use (reg:SI 2))
(use (reg:SI 3))
- (use (reg:SI 4))
- (use (reg:SI 5))
+ (use (match_dup 5))
(parallel [(call (mem:SI (match_operand 0 "" ""))
(const_int 0))
- (use (reg:SI 1))])
- (clobber (reg:SI 4))
- (clobber (reg:SI 5))]
+ (clobber (reg:SI 1))])]
""
"")
;; operand 6 is the loop count
(define_expand "call_block_move_loop"
- [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
- (match_operand:SI 3 "immediate_operand" "i")))
- (set (match_operand:SI 5 "register_operand" "r")
- (match_operand:SI 4 "memory_operand" "m"))
- (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
+ [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "immediate_operand" "")))
+ (set (match_operand:SI 5 "register_operand" "")
+ (match_operand:SI 4 "memory_operand" ""))
+ (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "")
(match_dup 3)))
- (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "i"))
+ (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" ""))
(use (reg:SI 2))
(use (reg:SI 3))
- (use (reg:SI 4))
- (use (reg:SI 5))
+ (use (match_dup 5))
(use (reg:SI 6))
(parallel [(call (mem:SI (match_operand 0 "" ""))
(const_int 0))
- (use (reg:SI 1))])
- (clobber (reg:SI 4))
- (clobber (reg:SI 5))
- (clobber (reg:SI 6))]
+ (clobber (reg:SI 1))])]
""
"")
\f
or %0,%#r0,%h1
subu %0,%#r0,%H1
ld.h %0,%1"
- [(set_attr "type" "arith,arith,arith,load")])
+ [(set_attr "type" "bit,arith,arith,load")])
(define_expand "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
or %0,%#r0,%q1
subu %0,%#r0,%Q1
ld.b %0,%1"
- [(set_attr "type" "arith,arith,arith,load")])
+ [(set_attr "type" "bit,arith,arith,load")])
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
or %0,%#r0,%q1
subu %0,%#r0,%Q1
ld.b %0,%1"
- [(set_attr "type" "arith,arith,arith,load")])
+ [(set_attr "type" "bit,arith,arith,load")])
\f
;; Conversions between float and double.
;; convert between float and double. In particular, the sign of -0 is
;; not preserved. Interestingly, fsub does conform.
-(define_insn "extendsfdf2"
+(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=r")
(float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
""
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
+ "! TARGET_88110"
"fsub.dss %0,%1,%#r0"
[(set_attr "type" "spadd")])
-(define_insn "truncdfsf2"
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")))]
+ "TARGET_88110"
+ "fcvt.ds %0,%1"
+ [(set_attr "type" "spadd")])
+
+(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=r")
(float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
+ "! TARGET_88110"
"fsub.sds %0,%1,%#r0"
[(set_attr "type" "dpadd")])
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "r,x")))]
+ "TARGET_88110"
+ "fcvt.sd %0,%1"
+ [(set_attr "type" "dpadd")])
+
;; Conversions between floating point and integer
(define_insn "floatsidf2"
- [(set (match_operand:DF 0 "register_operand" "=r")
- (float:DF (match_operand:SI 1 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (float:DF (match_operand:SI 1 "register_operand" "r,r")))]
""
"flt.ds %0,%1"
- [(set_attr "type" "spadd")])
+ [(set_attr "type" "spadd,dpadd")])
(define_insn "floatsisf2"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (float:SF (match_operand:SI 1 "register_operand" "r")))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (float:SF (match_operand:SI 1 "register_operand" "r,r")))]
""
"flt.ss %0,%1"
- [(set_attr "type" "spadd")])
+ [(set_attr "type" "spadd,spadd")])
(define_insn "fix_truncdfsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (fix:SI (match_operand:DF 1 "register_operand" "r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,x")
+ (fix:SI (match_operand:DF 1 "register_operand" "r,r")))]
""
"trnc.sd %0,%1"
- [(set_attr "type" "dpadd")])
+ [(set_attr "type" "dpadd,dpadd")])
(define_insn "fix_truncsfsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (fix:SI (match_operand:SF 1 "register_operand" "r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,x")
+ (fix:SI (match_operand:SF 1 "register_operand" "r,r")))]
""
"trnc.ss %0,%1"
- [(set_attr "type" "spadd")])
+ [(set_attr "type" "spadd,dpadd")])
\f
;;- arithmetic instructions
;; requires double rounding, whereas the 88000 instruction only rounds once.
(define_expand "adddf3"
- [(set (match_operand:DF 0 "register_operand" "=r")
- (plus:DF (match_operand:DF 1 "general_operand" "%r")
- (match_operand:DF 2 "general_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (plus:DF (match_operand:DF 1 "general_operand" "%r,x")
+ (match_operand:DF 2 "general_operand" "r,x")))]
""
"
{
}")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fadd.dss %0,%1,%2"
[(set_attr "type" "spadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (plus:DF (match_operand:DF 1 "register_operand" "r")
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (plus:DF (match_operand:DF 1 "register_operand" "r,x")
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fadd.dds %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fadd.dsd %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (plus:DF (match_operand:DF 1 "register_operand" "%r")
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (plus:DF (match_operand:DF 1 "register_operand" "%r,x")
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fadd.ddd %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn "addsf3"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (plus:SF (match_operand:SF 1 "register_operand" "%r")
- (match_operand:SF 2 "register_operand" "r")))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (plus:SF (match_operand:SF 1 "register_operand" "%r,x")
+ (match_operand:SF 2 "register_operand" "r,x")))]
""
"fadd.sss %0,%1,%2"
[(set_attr "type" "spadd")])
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "r")
(zero_extend:DI
- (match_operand:SI 2 "register_operand" "r"))))]
+ (match_operand:SI 2 "register_operand" "r"))))
+ (clobber (reg:CC 0))]
""
"addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0"
[(set_attr "type" "marith")])
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (zero_extend:DI
(match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))]
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC 0))]
""
"addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2"
[(set_attr "type" "marith")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "%r")
- (match_operand:DI 2 "register_operand" "r")))]
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC 0))]
""
"addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2"
[(set_attr "type" "marith")])
+
+;; Add with carry insns.
+
+(define_insn ""
+ [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+ (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+ (match_operand:SI 2 "reg_or_0_operand" "rO")))
+ (set (reg:CC 0)
+ (unspec:CC [(match_dup 1) (match_dup 2)] 0))])]
+ ""
+ "addu.co %r0,%r1,%r2")
+
+(define_insn ""
+ [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO")
+ (match_operand:SI 1 "reg_or_0_operand" "rO")]
+ 0))]
+ ""
+ "addu.co %#r0,%r0,%r1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+ (plus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+ (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO")
+ (reg:CC 0)] 0)))]
+ ""
+ "addu.ci %r0,%r1,%r2")
\f
;;- subtract instructions
;; requires double rounding, whereas the 88000 instruction only rounds once.
(define_expand "subdf3"
- [(set (match_operand:DF 0 "register_operand" "=r")
- (minus:DF (match_operand:DF 1 "general_operand" "r")
- (match_operand:DF 2 "general_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (minus:DF (match_operand:DF 1 "general_operand" "r,x")
+ (match_operand:DF 2 "general_operand" "r,x")))]
""
"
{
}")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fsub.dss %0,%1,%2"
[(set_attr "type" "spadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (minus:DF (match_operand:DF 1 "register_operand" "r")
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (minus:DF (match_operand:DF 1 "register_operand" "r,x")
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fsub.dds %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fsub.dsd %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (minus:DF (match_operand:DF 1 "register_operand" "r")
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (minus:DF (match_operand:DF 1 "register_operand" "r,x")
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fsub.ddd %0,%1,%2"
[(set_attr "type" "dpadd")])
(define_insn "subsf3"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (minus:SF (match_operand:SF 1 "register_operand" "r")
- (match_operand:SF 2 "register_operand" "r")))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (minus:SF (match_operand:SF 1 "register_operand" "r,x")
+ (match_operand:SF 2 "register_operand" "r,x")))]
""
"fsub.sss %0,%1,%2"
[(set_attr "type" "spadd")])
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
(zero_extend:DI
- (match_operand:SI 2 "register_operand" "r"))))]
+ (match_operand:SI 2 "register_operand" "r"))))
+ (clobber (reg:CC 0))]
""
"subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0"
[(set_attr "type" "marith")])
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (zero_extend:DI
(match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))]
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC 0))]
""
"subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2"
[(set_attr "type" "marith")])
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "register_operand" "r")))]
+ (match_operand:DI 2 "register_operand" "r")))
+ (clobber (reg:CC 0))]
""
"subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2"
[(set_attr "type" "marith")])
+
+;; Subtract with carry insns.
+
+(define_insn ""
+ [(parallel [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+ (match_operand:SI 2 "reg_or_0_operand" "rO")))
+ (set (reg:CC 0)
+ (unspec:CC [(match_dup 1) (match_dup 2)] 1))])]
+ ""
+ "subu.co %r0,%r1,%r2")
+
+(define_insn ""
+ [(set (reg:CC 0) (unspec:CC [(match_operand:SI 0 "reg_or_0_operand" "rO")
+ (match_operand:SI 1 "reg_or_0_operand" "rO")]
+ 1))]
+ ""
+ "subu.co %#r0,%r0,%r1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "reg_or_0_operand" "=r")
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rO")
+ (unspec:SI [(match_operand:SI 2 "reg_or_0_operand" "rO")
+ (reg:CC 0)] 1)))]
+ ""
+ "subu.ci %r0,%r1,%r2")
\f
;;- multiply instructions
;;
"mul %0,%1,%2"
[(set_attr "type" "imul")])
+(define_insn "umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_88110"
+ "mulu.d %0,%1,%2"
+ [(set_attr "type" "imul")])
+
;; patterns for mixed mode floating point
;; Do not define patterns that utilize mixed mode arithmetic that result
;; in narrowing the precision, because it loses accuracy, since the standard
;; requires double rounding, whereas the 88000 instruction only rounds once.
(define_expand "muldf3"
- [(set (match_operand:DF 0 "register_operand" "=r")
- (mult:DF (match_operand:DF 1 "general_operand" "%r")
- (match_operand:DF 2 "general_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (mult:DF (match_operand:DF 1 "general_operand" "%r,x")
+ (match_operand:DF 2 "general_operand" "r,x")))]
""
"
{
}")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fmul.dss %0,%1,%2"
[(set_attr "type" "spmul")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (mult:DF (match_operand:DF 1 "register_operand" "r")
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (mult:DF (match_operand:DF 1 "register_operand" "r,x")
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fmul.dds %0,%1,%2"
[(set_attr "type" "spmul")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fmul.dsd %0,%1,%2"
[(set_attr "type" "spmul")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (mult:DF (match_operand:DF 1 "register_operand" "%r")
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (mult:DF (match_operand:DF 1 "register_operand" "%r,x")
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fmul.ddd %0,%1,%2"
[(set_attr "type" "dpmul")])
(define_insn "mulsf3"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (mult:SF (match_operand:SF 1 "register_operand" "%r")
- (match_operand:SF 2 "register_operand" "r")))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (mult:SF (match_operand:SF 1 "register_operand" "%r,x")
+ (match_operand:SF 2 "register_operand" "r,x")))]
""
"fmul.sss %0,%1,%2"
[(set_attr "type" "spmul")])
;; requires double rounding, whereas the 88000 instruction only rounds once.
(define_expand "divdf3"
- [(set (match_operand:DF 0 "register_operand" "=r")
- (div:DF (match_operand:DF 1 "general_operand" "r")
- (match_operand:DF 2 "general_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (div:DF (match_operand:DF 1 "general_operand" "r,x")
+ (match_operand:DF 2 "general_operand" "r,x")))]
""
"
{
}")
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fdiv.dss %0,%1,%2"
[(set_attr "type" "dpdiv")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (div:DF (match_operand:DF 1 "register_operand" "r")
- (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (div:DF (match_operand:DF 1 "register_operand" "r,x")
+ (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))]
""
"fdiv.dds %0,%1,%2"
[(set_attr "type" "dpdiv")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r,x"))
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fdiv.dsd %0,%1,%2"
[(set_attr "type" "dpdiv")])
(define_insn "divsf3"
- [(set (match_operand:SF 0 "register_operand" "=r")
- (div:SF (match_operand:SF 1 "register_operand" "r")
- (match_operand:SF 2 "register_operand" "r")))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (div:SF (match_operand:SF 1 "register_operand" "r,x")
+ (match_operand:SF 2 "register_operand" "r,x")))]
""
"fdiv.sss %0,%1,%2"
[(set_attr "type" "spdiv")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=r")
- (div:DF (match_operand:DF 1 "register_operand" "r")
- (match_operand:DF 2 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=r,x")
+ (div:DF (match_operand:DF 1 "register_operand" "r,x")
+ (match_operand:DF 2 "register_operand" "r,x")))]
""
"fdiv.ddd %0,%1,%2"
[(set_attr "type" "dpdiv")])
or.u %0,%1,%X2
set %0,%1,%s2
or.u %0,%1,%X2\;or %0,%0,%x2"
- [(set_attr "type" "arith,arith,arith,marith")])
+ [(set_attr "type" "arith,arith,bit,marith")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
""
"@
mak %0,%1,%2
- mak %0,%1,0<%2>")
+ mak %0,%1,0<%2>"
+ [(set_attr "type" "bit")])
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
""
"@
ext %0,%1,%2
- ext %0,%1,0<%2>")
+ ext %0,%1,0<%2>"
+ [(set_attr "type" "bit")])
\f
;;- logical shift instructions. Logical shift left becomes arithmetic
;; shift left. LSHIFT is not normally produced, but is supported.
""
"@
mak %0,%1,%2
- mak %0,%1,0<%2>")
+ mak %0,%1,0<%2>"
+ [(set_attr "type" "bit")])
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
""
"@
extu %0,%1,%2
- extu %0,%1,0<%2>")
+ extu %0,%1,0<%2>"
+ [(set_attr "type" "bit")])
\f
;;- rotate instructions
(rotatert:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
""
- "rot %0,%1,%2")
+ "rot %0,%1,%2"
+ [(set_attr "type" "bit")])
+\f
+;; find first set.
+
+;; The ff1 instruction searches from the most significant bit while ffs
+;; searches from the least significant bit. The bit index and treatment of
+;; zero also differ. This amazing sequence was discovered using the GNU
+;; Superoptimizer.
+
+(define_insn "ffssi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (ffs:SI (match_operand:SI 1 "register_operand" "0,r")))
+ (clobber (reg:CC 0))
+ (clobber (match_scratch:SI 2 "=r,X"))]
+ ""
+ "@
+ subu.co %2,%#r0,%1\;and %2,%2,%1\;addu.ci %2,%2,%2\;ff1 %0,%2
+ subu.co %0,%#r0,%1\;and %0,%0,%1\;addu.ci %0,%0,%0\;ff1 %0,%0"
+ [(set_attr "type" "marith")
+ (set_attr "length" "4")])
\f
;; Bit field instructions.
operands[4] = gen_rtx (CONST_INT, SImode,
(32 - INTVAL (operands[2])) - INTVAL (operands[3]));
return \"ext %0,%1,%2<%4>\"; /* <(32-%2-%3)> */
-}")
+}"
+ [(set_attr "type" "bit")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
operands[4] = gen_rtx (CONST_INT, SImode,
(32 - INTVAL (operands[2])) - INTVAL (operands[3]));
return \"extu %0,%1,%2<%4>\"; /* <(32-%2-%3)> */
-}")
+}"
+ [(set_attr "type" "bit")])
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "int5_operand" "")
(match_operand:SI 2 "int5_operand" ""))
(const_int 0))]
operands[3] = gen_rtx (CONST_INT, SImode,
(32 - INTVAL (operands[1])) - INTVAL (operands[2]));
return \"clr %0,%0,%1<%3>\"; /* <(32-%1-%2)> */
-}")
+}"
+ [(set_attr "type" "bit")])
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "int5_operand" "")
(match_operand:SI 2 "int5_operand" ""))
(const_int -1))]
operands[3] = gen_rtx (CONST_INT, SImode,
(32 - INTVAL (operands[1])) - INTVAL (operands[2]));
return \"set %0,%0,%1<%3>\"; /* <(32-%1-%2)> */
-}")
+}"
+ [(set_attr "type" "bit")])
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=r")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "int5_operand" "")
(match_operand:SI 2 "int5_operand" ""))
(match_operand:SI 3 "int32_operand" "n"))]
"subu %0,%#r0,%1")
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=r")
- (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r"))))]
+ [(set (match_operand:SF 0 "register_operand" "=r,x")
+ (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r,x"))))]
""
- "fsub.ssd %0,%#r0,%1"
+ "@
+ fsub.ssd %0,%#r0,%1
+ fsub.ssd %0,%#x0,%1"
[(set_attr "type" "dpadd")])
-(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "+r")
- (neg:DF (match_dup 0)))]
- ""
- "xor.u %0,%0,0x8000")
-
(define_insn "negdf2"
- [(set (match_operand:DF 0 "register_operand" "=&r")
- (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=&r,r")
+ (neg:DF (match_operand:DF 1 "register_operand" "r,0")))]
""
- "xor.u %0,%1,0x8000\;or %d0,%#r0,%d1"
- [(set_attr "type" "marith")])
+ "@
+ xor.u %0,%1,0x8000\;or %d0,%#r0,%d1
+ xor.u %0,%0,0x8000"
+ [(set_attr "type" "marith,arith")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=r")
;; absolute value insns for floating-point (integer abs can be done using the
;; machine-independent sequence).
-(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "+r")
- (abs:DF (match_dup 0)))]
- ""
- "and.u %0,%0,0x7fff")
-
(define_insn "absdf2"
- [(set (match_operand:DF 0 "register_operand" "=&r")
- (abs:DF (match_operand:DF 1 "register_operand" "r")))]
+ [(set (match_operand:DF 0 "register_operand" "=&r,r")
+ (abs:DF (match_operand:DF 1 "register_operand" "r,0")))]
""
- "and.u %0,%1,0x7fff\;or %d0,%#r0,%d1"
- [(set_attr "type" "marith")])
+ "@
+ and.u %0,%1,0x7fff\;or %d0,%#r0,%d1
+ and.u %0,%0,0x7fff"
+ [(set_attr "type" "marith,arith")])
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=r")
{
register rtx index_diff = gen_reg_rtx (SImode);
register rtx low = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1]));
+ register rtx label = gen_rtx (LABEL_REF, VOIDmode, operands[3]);
+ register rtx base;
+
+ if (! CASE_VECTOR_INSNS)
+ /* These instructions are likely to be scheduled and made loop invariant.
+ This decreases the cost of the dispatch at the expense of the default
+ case. */
+ base = force_reg (SImode, memory_address_noforce (SImode, label));
/* Compute the index difference and handle the default case. */
emit_insn (gen_addsi3 (index_diff,
force_reg (SImode, operands[0]),
ADD_INT (low) ? low : force_reg (SImode, low)));
emit_insn (gen_cmpsi (index_diff, operands[2]));
+ /* It's possible to replace this branch with sgtu/iorsi3 and adding a -1
+ entry to the table. However, that doesn't seem to win on the m88110. */
emit_jump_insn (gen_bgtu (operands[4]));
- /* Call the jump that will branch to the appropriate case. */
- emit_jump_insn (gen_casesi_enter (gen_rtx (LABEL_REF, VOIDmode, operands[3]),
- index_diff,
- operands[3]));
- /* Claim that flow drops into the table so it will be adjacent. */
+ if (CASE_VECTOR_INSNS)
+ /* Call the jump that will branch to the appropriate case. */
+ emit_jump_insn (gen_casesi_enter (label, index_diff, operands[3]));
+ else
+ /* Load the table entry and jump to it. */
+ emit_jump_insn (gen_casesi_jump (gen_reg_rtx (SImode), base, index_diff));
+
+ /* Claim that flow drops into the table so it will be adjacent by not
+ emitting a barrier. */
DONE;
}")
+(define_expand "casesi_jump"
+ [(set (match_operand:SI 0 "" "")
+ (mem:SI (plus:SI (match_operand:SI 1 "" "")
+ (mult:SI (match_operand:SI 2 "" "")
+ (const_int 4)))))
+ (set (pc) (match_dup 0))]
+ ""
+ "")
+
;; The bsr.n instruction is directed to the END of the table. See
;; ASM_OUTPUT_CASE_END.
(define_expand "call"
[(parallel [(call (match_operand:SI 0 "" "")
(match_operand 1 "" ""))
- (use (reg:SI 1))])]
+ (clobber (reg:SI 1))])]
""
"
{
(define_insn ""
[(parallel [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rQ"))
(match_operand 1 "" ""))
- (use (reg:SI 1))])]
+ (clobber (reg:SI 1))])]
""
"* return output_call (operands, operands[0]);"
[(set_attr "type" "call")])
[(parallel [(set (match_operand 0 "register_operand" "")
(call (match_operand:SI 1 "" "")
(match_operand 2 "" "")))
- (use (reg:SI 1))])]
+ (clobber (reg:SI 1))])]
""
"
{
(call (mem:SI
(match_operand:SI 1 "call_address_operand" "rQ"))
(match_operand 2 "" "")))
- (use (reg:SI 1))])]
+ (clobber (reg:SI 1))])]
""
"* return output_call (operands, operands[1]);"
[(set_attr "type" "call")])
(define_insn "nop"
[(const_int 0)]
""
- "ff0 %#r0,%#r0")
+ "ff0 %#r0,%#r0"
+ [(set_attr "type" "bit")])
(define_insn "return"
[(return)]
- "null_epilogue ()"
+ "null_prologue ()"
"jmp%. %#r1"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "jump")])
+
+(define_expand "prologue"
+ [(const_int 0)]
+ ""
+ "m88k_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+ [(set (pc) (reg:SI 1))]
+ "! null_prologue ()"
+ "m88k_expand_epilogue ();")
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] 0)]
+ ""
+ ""
+ [(set_attr "length" "0")])
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"jmp%. %0"
- [(set_attr "type" "branch")])
+ [(set_attr "type" "jump")])
(define_insn "jump"
[(set (pc)