--- gcc/config/m88k.md 2018/04/24 17:51:34 1.1 +++ gcc/config/m88k.md 2018/04/24 18:04:59 1.1.1.4 @@ -28,36 +28,39 @@ (define_expand "m88k_sccs_id" [(match_operand:SI 0 "" "")] "" - "{ static char sccs_id[] = \"@(#)m88k.md 1.96.4.3 1/14/92 09:46:15\"; + "{ static char sccs_id[] = \"@(#)m88k.md 2.3.2.2 11/05/92 09:03:51\"; FAIL; }") ;; Attribute specifications +; Target CPU. +(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))) @@ -76,8 +79,8 @@ (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) @@ -85,7 +88,7 @@ ; 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)]) ; An abstract block diagram of the function units for the m88100. @@ -127,45 +130,195 @@ ; Consideration of writeback contention is critical to superb scheduling. ; ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST]) - -;(define_function_unit "decode" 1 1 (const_int 1) 0 1) +; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) -; 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) + +(define_function_unit "mem110" 1 0 + (and (eq_attr "type" "load,loadd") (eq_attr "cpu" "!m88100")) 3 2) +(define_function_unit "mem110" 1 0 + (and (eq_attr "type" "store") (eq_attr "cpu" "!m88100")) 1 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 unusal 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 + +;; 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)))] + "") ;; 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 @@ -176,25 +329,6 @@ ;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing ;; special needs to be done here. -;; (a << int1) >> int2 optimizations into a single extract. -;; These patterns need to occur before the normal shift patterns - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "int5_operand" "")))] - "INTVAL (operands [2]) <= INTVAL (operands [3])" - "ext %0,%1,%w3<(%3-%2)>") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "int5_operand" "")) - (match_operand:SI 3 "int5_operand" "")))] - "INTVAL (operands [2]) <= INTVAL (operands [3])" - "extu %0,%1,%w3<(%3-%2)>") - ;; Optimize possible cases of the set instruction. (define_insn "" @@ -202,7 +336,8 @@ (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") @@ -210,7 +345,8 @@ (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") @@ -218,7 +354,8 @@ (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. @@ -234,7 +371,8 @@ 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. @@ -252,7 +390,278 @@ ((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. + +;; 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]);") + +;; 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"))] + "" + "#") ;; Recognize bcnd instructions for integer values. This is distinguished ;; from a conditional branch instruction (below) with SImode instead of @@ -642,57 +1051,60 @@ ;; The actual compare instructions. (define_insn "" - [(set (match_operand:CC 0 "register_operand" "=r,r") - (compare:CC (match_operand:SI 1 "register_operand" "rO,I") - (match_operand:SI 2 "arith_operand" "rI,r")))] + [(set (match_operand:CC 0 "register_operand" "=r") + (compare:CC (match_operand:SI 1 "register_operand" "rO") + (match_operand:SI 2 "arith_operand" "rI")))] "" - "@ - cmp %0,%r1,%2 - cmp %0,%2,%1\;xor.c %0,%#r0,%0" - [(set_attr "type" "arith,marith")]) + "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")]) ;; 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))] @@ -761,7 +1173,8 @@ [(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") @@ -770,7 +1183,8 @@ [(match_operand:CC 2 "register_operand" "r") (const_int 0)])))] "" - "extu %0,%2,1<%C1>") + "extu %0,%2,1<%C1>" + [(set_attr "type" "bit")]) ;; Conditional branch insns. The compare insns set a register ;; rather than cc0 and record that register for use here. See above @@ -936,8 +1350,59 @@ (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")]) + +(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")]) ;; SImode move instructions @@ -947,23 +1412,43 @@ "" " { - if (emit_move_sequence (operands, SImode)) + if (emit_move_sequence (operands, SImode, 0)) DONE; }") +(define_expand "reload_insi" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:SI 1 "general_operand" "")) + (clobber (match_operand:SI 2 "register_operand" "=&r"))] + "" + " +{ + if (emit_move_sequence (operands, SImode, operands[2])) + DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; +}") + (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)" "@ or %0,%#r0,%1 - ld %0,%1 - st %r1,%0 + %V1ld %0,%1 + %v0st %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 + %V1ld %0,%1 + %v0st %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") @@ -975,7 +1460,7 @@ 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 "" @@ -999,7 +1484,7 @@ "" " { - if (emit_move_sequence (operands, HImode)) + if (emit_move_sequence (operands, HImode, 0)) DONE; }") @@ -1011,8 +1496,8 @@ || operands[1] == const0_rtx)" "@ or %0,%#r0,%h1 - ld.hu %0,%1 - st.h %r1,%0 + %V1ld.hu %0,%1 + %v0st.h %r1,%0 subu %0,%#r0,%H1" [(set_attr "type" "arith,load,store,arith")]) @@ -1031,7 +1516,7 @@ "" " { - if (emit_move_sequence (operands, QImode)) + if (emit_move_sequence (operands, QImode, 0)) DONE; }") @@ -1043,8 +1528,8 @@ || operands[1] == const0_rtx)" "@ or %0,%#r0,%q1 - ld.bu %0,%1 - st.b %r1,%0 + %V1ld.bu %0,%1 + %v0st.b %r1,%0 subu %r0,%#r0,%Q1" [(set_attr "type" "arith,load,store,arith")]) @@ -1063,26 +1548,33 @@ "" " { - if (emit_move_sequence (operands, DImode)) + if (emit_move_sequence (operands, DImode, 0)) DONE; }") (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" - [(set_attr "type" "marith,load,store")]) + %V1ld.d %0,%1 + %v0st.d %1,%0 + mov.d %0,%1 + mov.d %0,%1 + mov %0,%1 + %V1ld.d %0,%1 + %v0st.d %1,%0" + [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -1107,7 +1599,7 @@ "" " { - if (emit_move_sequence (operands, DFmode)) + if (emit_move_sequence (operands, DFmode, 0)) DONE; }") @@ -1129,26 +1621,33 @@ ; return \"or %0,%#r0,0\;or %d0,%#r0,0\"; ; case 1: ; operands[1] = adj_offsettable_operand (operands[0], 4); -; return \"st %#r0,%0\;st %#r0,%1\"; +; return \"%v0st %#r0,%0\;st %#r0,%1\"; ; } ;}") (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" - [(set_attr "type" "marith,load,store")]) + %V1ld.d %0,%1 + %v0st.d %1,%0 + mov.d %0,%1 + mov.d %0,%1 + mov %0,%1 + %V1ld.d %0,%1 + %v0st.d %1,%0" + [(set_attr "type" "marith,loadd,store,mov,mov,mov,loadd,store")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=r") @@ -1173,26 +1672,34 @@ "" " { - if (emit_move_sequence (operands, SFmode)) + if (emit_move_sequence (operands, SFmode, 0)) DONE; }") ;; @@ 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" - [(set_attr "type" "arith,load,store")]) + %V1ld %0,%1 + %v0st %r1,%0 + mov.s %0,%1 + mov.s %0,%1 + mov %0,%1 + %V1ld %0,%1 + %v0st %r1,%0" + [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=r") @@ -1211,8 +1718,8 @@ ;; String/block move insn. See m88k.c for details. (define_expand "movstrsi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) - (mem:BLK (match_operand:BLK 1 "general_operand" ""))) + [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) + (mem:BLK (match_operand:BLK 1 "" ""))) (use (match_operand:SI 2 "arith32_operand" "")) (use (match_operand:SI 3 "immediate_operand" ""))])] "" @@ -1233,50 +1740,44 @@ ;; 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)) - (parallel [(call (mem:SI (match_operand 0 "" "")) - (const_int 0)) - (use (reg:SI 1))]) - (clobber (reg:SI 4)) - (clobber (reg:SI 5))] + (use (match_dup 5)) + (parallel [(set (reg:DI 2) + (call (mem:SI (match_operand 0 "" "")) + (const_int 0))) + (clobber (reg:SI 1))])] "" "") -;; Call a looping block move library function (e.g. __movstrSI64n68). +;; Call an SImode looping block move library function (e.g. __movstrSI64n68). ;; operands 0-5 as in the non-looping interface ;; 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") +(define_expand "call_movstrsi_loop" + [(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))] + (parallel [(set (reg:DI 2) + (call (mem:SI (match_operand 0 "" "")) + (const_int 0))) + (clobber (reg:SI 1))])] "" "") @@ -1291,7 +1792,7 @@ if (GET_CODE (operands[1]) == MEM && symbolic_address_p (XEXP (operands[1], 0))) operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); }") (define_insn "" @@ -1301,7 +1802,7 @@ "@ mask %0,%1,0xffff or %0,%#r0,%h1 - ld.hu %0,%1" + %V1ld.hu %0,%1" [(set_attr "type" "arith,arith,load")]) (define_expand "zero_extendqihi2" @@ -1313,7 +1814,7 @@ if (GET_CODE (operands[1]) == MEM && symbolic_address_p (XEXP (operands[1], 0))) operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); }") (define_insn "" @@ -1323,7 +1824,7 @@ "@ mask %0,%1,0xff or %0,%#r0,%q1 - ld.bu %0,%1" + %V1ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) (define_expand "zero_extendqisi2" @@ -1336,7 +1837,7 @@ && symbolic_address_p (XEXP (operands[1], 0))) { operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (ZERO_EXTEND, SImode, operands[1]))); DONE; @@ -1350,7 +1851,7 @@ "@ mask %0,%1,0xff or %0,%#r0,%q1 - ld.bu %0,%1" + %V1ld.bu %0,%1" [(set_attr "type" "arith,arith,load")]) ;;- sign extension instructions @@ -1373,7 +1874,7 @@ if (GET_CODE (operands[1]) == MEM && symbolic_address_p (XEXP (operands[1], 0))) operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); }") (define_insn "" @@ -1384,8 +1885,8 @@ ext %0,%1,16<0> or %0,%#r0,%h1 subu %0,%#r0,%H1 - ld.h %0,%1" - [(set_attr "type" "arith,arith,arith,load")]) + %V1ld.h %0,%1" + [(set_attr "type" "bit,arith,arith,load")]) (define_expand "extendqihi2" [(set (match_operand:HI 0 "register_operand" "") @@ -1396,7 +1897,7 @@ if (GET_CODE (operands[1]) == MEM && symbolic_address_p (XEXP (operands[1], 0))) operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); }") (define_insn "" @@ -1407,8 +1908,8 @@ ext %0,%1,8<0> or %0,%#r0,%q1 subu %0,%#r0,%Q1 - ld.b %0,%1" - [(set_attr "type" "arith,arith,arith,load")]) + %V1ld.b %0,%1" + [(set_attr "type" "bit,arith,arith,load")]) (define_expand "extendqisi2" [(set (match_operand:SI 0 "register_operand" "") @@ -1419,7 +1920,7 @@ if (GET_CODE (operands[1]) == MEM && symbolic_address_p (XEXP (operands[1], 0))) operands[1] - = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); + = legitimize_address (flag_pic, operands[1], 0, 0); }") (define_insn "" @@ -1430,8 +1931,8 @@ ext %0,%1,8<0> or %0,%#r0,%q1 subu %0,%#r0,%Q1 - ld.b %0,%1" - [(set_attr "type" "arith,arith,arith,load")]) + %V1ld.b %0,%1" + [(set_attr "type" "bit,arith,arith,load")]) ;; Conversions between float and double. @@ -1439,49 +1940,75 @@ ;; 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")]) ;;- arithmetic instructions @@ -1496,41 +2023,15 @@ addu %0,%1,%2 subu %0,%1,%n2") -;; In unusual contexts, an add of a large value is generated (case statements -;; for example). In these contexts, it is sufficient to accept only those -;; cases where the two registers are different. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,&r") - (plus:SI (match_operand:SI 1 "arith32_operand" "%r,r") - (match_operand:SI 2 "arith32_operand" "r,!n")))] - "" - "* -{ - rtx xoperands[10]; - - if (which_alternative == 0) - return \"addu %0,%1,%2\"; - - xoperands[0] = operands[0]; - xoperands[1] = operands[2]; - output_asm_insn (output_load_const_int (SImode, xoperands), - xoperands); - - return \"addu %0,%1,%0\"; -}" - [(set_attr "type" "arith,marith") - (set_attr "length" "1,3")]) ; may be 2 or 3. - ;; 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 "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")))] "" " { @@ -1539,41 +2040,41 @@ }") (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")]) @@ -1582,7 +2083,8 @@ [(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")]) @@ -1591,7 +2093,8 @@ [(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")]) @@ -1599,10 +2102,37 @@ (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") ;;- subtract instructions @@ -1619,9 +2149,9 @@ ;; 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")))] "" " { @@ -1630,41 +2160,41 @@ }") (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")]) @@ -1673,7 +2203,8 @@ [(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")]) @@ -1682,7 +2213,8 @@ [(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")]) @@ -1690,10 +2222,37 @@ (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") ;;- multiply instructions ;; @@ -1709,15 +2268,23 @@ "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")))] "" " { @@ -1726,41 +2293,41 @@ }") (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")]) @@ -1810,7 +2377,6 @@ emit_insn (gen_cmpsi (operands[0], const0_rtx)); emit_jump_insn (gen_bne (operands[1])); emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); DONE; }") @@ -1839,7 +2405,6 @@ if (op2 == const0_rtx) { emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); emit_insn (gen_dummy (op0)); DONE; } @@ -1881,11 +2446,8 @@ if (TARGET_CHECK_ZERO_DIV) emit_insn (gen_tcnd_divide_by_zero (op2, join_label)); - else - { - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); - } + emit_jump_insn (gen_jump (join_label)); + emit_barrier (); emit_label (label1); /* constant / positive */ emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); @@ -1950,13 +2512,9 @@ emit_jump_insn (gen_bne (join_label)); emit_label (label4); emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); - } - else - { - emit_jump_insn (gen_jump (join_label)); - emit_barrier (); } + emit_jump_insn (gen_jump (join_label)); + emit_barrier (); emit_label (label2); /* pos.-or-0 / neg.-or-0 */ emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2)); @@ -2011,7 +2569,6 @@ if (op2 == const0_rtx) { emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); emit_insn (gen_dummy (operands[0])); DONE; } @@ -2049,9 +2606,9 @@ ;; 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")))] "" " { @@ -2069,41 +2626,41 @@ }") (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")]) @@ -2277,7 +2834,7 @@ 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") @@ -2409,7 +2966,7 @@ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "ld.b %0,%1" + "%V1ld.b %0,%1" [(set_attr "type" "load")]) (define_insn "" @@ -2417,7 +2974,7 @@ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 24)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "ld.bu %0,%1" + "%V1ld.bu %0,%1" [(set_attr "type" "load")]) (define_insn "" @@ -2425,7 +2982,7 @@ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "ld.h %0,%1" + "%V1ld.h %0,%1" [(set_attr "type" "load")]) (define_insn "" @@ -2433,7 +2990,7 @@ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") (const_int 16)))] "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" - "ld.hu %0,%1" + "%V1ld.hu %0,%1" [(set_attr "type" "load")]) ;;- arithmetic shift instructions. @@ -2497,7 +3054,8 @@ "" "@ 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" "") @@ -2541,7 +3099,8 @@ "" "@ ext %0,%1,%2 - ext %0,%1,0<%2>") + ext %0,%1,0<%2>" + [(set_attr "type" "bit")]) ;;- logical shift instructions. Logical shift left becomes arithmetic ;; shift left. LSHIFT is not normally produced, but is supported. @@ -2564,7 +3123,8 @@ "" "@ 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" "") @@ -2606,7 +3166,8 @@ "" "@ extu %0,%1,%2 - extu %0,%1,0<%2>") + extu %0,%1,0<%2>" + [(set_attr "type" "bit")]) ;;- rotate instructions @@ -2634,7 +3195,27 @@ (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")]) + +;; 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")]) ;; Bit field instructions. @@ -2652,7 +3233,13 @@ (match_operand:SI 2 "int5_operand" "") (match_operand:SI 3 "int5_operand" "")))] "" - "ext %0,%1,%2<(32-%2-%3)>") + "* +{ + 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") @@ -2668,26 +3255,44 @@ (match_operand:SI 2 "int5_operand" "") (match_operand:SI 3 "int5_operand" "")))] "" - "extu %0,%1,%2<(32-%2-%3)>") + "* +{ + 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))] "" - "clr %0,%0,%1<(32-%1-%2)>") + "* +{ + 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))] "" - "set %0,%0,%1<(32-%1-%2)>") + "* +{ + 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"))] @@ -2723,24 +3328,22 @@ "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") @@ -2751,18 +3354,14 @@ ;; 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") @@ -2791,22 +3390,45 @@ { 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. @@ -2832,7 +3454,7 @@ (define_expand "call" [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" "")) - (use (reg:SI 1))])] + (clobber (reg:SI 1))])] "" " { @@ -2845,7 +3467,7 @@ (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")]) @@ -2854,7 +3476,7 @@ [(parallel [(set (match_operand 0 "register_operand" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) - (use (reg:SI 1))])] + (clobber (reg:SI 1))])] "" " { @@ -2869,7 +3491,7 @@ (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")]) @@ -2879,19 +3501,36 @@ (define_insn "nop" [(const_int 0)] "" - "ff0 %#r0,%#r0") + "ff0 %#r0,%#r0" + [(set_attr "type" "bit")]) (define_insn "return" [(return)] - "null_epilogue ()" + "reload_completed" "jmp%. %#r1" - [(set_attr "type" "branch")]) + [(set_attr "type" "jump")]) + +(define_expand "prologue" + [(const_int 0)] + "" + "m88k_expand_prologue (); DONE;") + +(define_expand "epilogue" + [(return)] + "! 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)