--- gcc/config/m88k.md 2018/04/24 17:59:20 1.1.1.3 +++ gcc/config/m88k.md 2018/04/24 18:04:59 1.1.1.4 @@ -28,48 +28,39 @@ (define_expand "m88k_sccs_id" [(match_operand:SI 0 "" "")] "" - "{ static char sccs_id[] = \"@(#)m88k.md 2.1.11.6 29 May 1992 10:55:49\"; + "{ static char sccs_id[] = \"@(#)m88k.md 2.3.2.2 11/05/92 09:03:51\"; FAIL; }") ;; 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 +; load,store,loadd,loada, ; data unit instructions ; spadd,dpadd,spcmp,dpcmp,spdiv,dpdiv,idiv, ; FPU add instructions ; spmul,dpmul,imul, ; FPU multiply instructions ; arith,bit,mov ; integer unit instructions -; marith,mbit,mfp,weird" ; multi-word 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,spcmp,dpcmp,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,bit,mov,marith,mbit,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 "unit" "bit,memory,multiply,divide,fpadd,other" - (cond [(eq_attr "type" "bit,mbit") (const_string "bit") - (eq_attr "type" "load,store") (const_string "memory") - (eq_attr "type" "spmul,dpmul,imul") (const_string "multiply") - (eq_attr "type" "spdiv,dpdiv,idiv") (const_string "divide") - (eq_attr "type" "spadd,dpadd,spcmp,dpcmp,mfp") (const_string "fpadd")] - (const_string "other"))) - (define_attr "fpu" "yes,no" (if_then_else - (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spcmp,dpcmp,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,mbit,mfp") + (cond [(eq_attr "type" "marith") (const_int 2)] (const_int 1))) @@ -88,8 +79,8 @@ (define_delay (eq_attr "type" "branch,jump") [(and (and - (eq_attr "type" "!branch,jump,call,marith,mbit,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) @@ -97,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,mbit,mfp,weird") ; required. + [(eq_attr "type" "!branch,call,marith,weird") ; required. (nil) (nil)]) ; An abstract block diagram of the function units for the m88100. @@ -139,76 +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,marith,mbit,mfp,weird") 1 0) -;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,mbit,weird") 2 0) +; "!store,marith,weird") 1 0) +;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0) (define_function_unit "alu" 1 0 - (and (eq_attr "type" "loada,arith,bit,mov") (eq_attr "cpu" "!m88100")) 2 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,mbit,weird") (eq_attr "cpu" "!m88100")) 4 0) + (and (eq_attr "type" "marith,weird") (eq_attr "cpu" "!m88100")) 4 0) -(define_function_unit "memory" 1 3 - (and (eq_attr "type" "load") (eq_attr "cpu" "m88100")) 3 2) -(define_function_unit "memory" 1 3 - (and (eq_attr "type" "load") (eq_attr "cpu" "!m88100")) 4 2) +(define_function_unit "bit" 1 0 + (and (eq_attr "type" "bit") (eq_attr "cpu" "!m88100")) 2 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 "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 - (and (eq_attr "type" "spmul") (eq_attr "cpu" "m88100")) 4 2) ; 6-8 -(define_function_unit "fpmul" 1 4 - (and (eq_attr "type" "dpmul,mfp") (eq_attr "cpu" "m88100")) 7 2) ; 9-10 -(define_function_unit "fpmul" 1 4 - (and (eq_attr "type" "imul") (eq_attr "cpu" "m88100")) 3 2) ; 4 - -(define_function_unit "fpmul" 1 4 - (and (eq_attr "type" "imul,spmul,dpmul,mfp") - (eq_attr "cpu" "!m88100")) 6 2) ; 3 - -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "spadd,spcmp") (eq_attr "cpu" "m88100")) 3 2) ; 5-6 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "dpadd,dpcmp") (eq_attr "cpu" "m88100")) 4 2) ; 6-7 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "spdiv") (eq_attr "cpu" "m88100")) 30 2) ; 30-31 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "m88100")) 60 2) ; 60-61 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "m88100")) 38 2) ; 38 - -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "spadd,dpadd") (eq_attr "cpu" "!m88100")) 6 2) ; 3 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "spcmp,dpcmp") (eq_attr "cpu" "!m88100")) 2 2) ; 3 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "spdiv") (eq_attr "cpu" "!m88100")) 26 2) ; 13 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "dpdiv") (eq_attr "cpu" "!m88100")) 46 2) ; 23 -(define_function_unit "fpadd" 1 3 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "!m88100")) 36 2) ; 18 - -;(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,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") 0 1) -;(define_function_unit "memory" 1 3 (eq_attr "type" "store") 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 @@ -219,37 +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])" - "* -{ - 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") - (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])" - "* -{ - 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. (define_insn "" @@ -313,6 +392,277 @@ }" [(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 ;; CCmode. @@ -1008,6 +1358,51 @@ 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 @@ -1017,10 +1412,25 @@ "" " { - 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,r,x,x,x,m") (match_operand:SI 1 "move_operand" "rI,m,rO,J,M,x,r,x,m,x"))] @@ -1029,15 +1439,15 @@ || 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 mov.s %0,%1 mov.s %0,%1 mov %0,%1 - ld %0,%1 - st %1,%0" + %V1ld %0,%1 + %v0st %1,%0" [(set_attr "type" "arith,load,store,arith,bit,mov,mov,mov,load,store")]) (define_insn "" @@ -1074,7 +1484,7 @@ "" " { - if (emit_move_sequence (operands, HImode)) + if (emit_move_sequence (operands, HImode, 0)) DONE; }") @@ -1086,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")]) @@ -1106,7 +1516,7 @@ "" " { - if (emit_move_sequence (operands, QImode)) + if (emit_move_sequence (operands, QImode, 0)) DONE; }") @@ -1118,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")]) @@ -1138,7 +1548,7 @@ "" " { - if (emit_move_sequence (operands, DImode)) + if (emit_move_sequence (operands, DImode, 0)) DONE; }") @@ -1157,14 +1567,14 @@ "" "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 - ld.d %0,%1 - st.d %1,%0 + %V1ld.d %0,%1 + %v0st.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,mov,mov,mov,load,store")]) + %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") @@ -1189,7 +1599,7 @@ "" " { - if (emit_move_sequence (operands, DFmode)) + if (emit_move_sequence (operands, DFmode, 0)) DONE; }") @@ -1211,7 +1621,7 @@ ; 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\"; ; } ;}") @@ -1230,14 +1640,14 @@ "" "@ or %0,%#r0,%1\;or %d0,%#r0,%d1 - ld.d %0,%1 - st.d %1,%0 + %V1ld.d %0,%1 + %v0st.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,mov,mov,mov,load,store")]) + %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") @@ -1262,7 +1672,7 @@ "" " { - if (emit_move_sequence (operands, SFmode)) + if (emit_move_sequence (operands, SFmode, 0)) DONE; }") @@ -1282,13 +1692,13 @@ "" "@ or %0,%#r0,%1 - ld %0,%1 - st %r1,%0 + %V1ld %0,%1 + %v0st %r1,%0 mov.s %0,%1 mov.s %0,%1 mov %0,%1 - ld %0,%1 - st %r1,%0" + %V1ld %0,%1 + %v0st %r1,%0" [(set_attr "type" "arith,load,store,mov,mov,mov,load,store")]) (define_insn "" @@ -1308,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" ""))])] "" @@ -1332,39 +1742,41 @@ ;; operand 5 is the register to hold the value (r4 or r5) (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 (match_dup 5)) - (parallel [(call (mem:SI (match_operand 0 "" "")) - (const_int 0)) + (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 (match_dup 5)) (use (reg:SI 6)) - (parallel [(call (mem:SI (match_operand 0 "" "")) - (const_int 0)) + (parallel [(set (reg:DI 2) + (call (mem:SI (match_operand 0 "" "")) + (const_int 0))) (clobber (reg:SI 1))])] "" "") @@ -1380,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 "" @@ -1390,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" @@ -1402,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 "" @@ -1412,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" @@ -1425,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; @@ -1439,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 @@ -1462,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 "" @@ -1473,7 +1885,7 @@ ext %0,%1,16<0> or %0,%#r0,%h1 subu %0,%#r0,%H1 - ld.h %0,%1" + %V1ld.h %0,%1" [(set_attr "type" "bit,arith,arith,load")]) (define_expand "extendqihi2" @@ -1485,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 "" @@ -1496,7 +1908,7 @@ ext %0,%1,8<0> or %0,%#r0,%q1 subu %0,%#r0,%Q1 - ld.b %0,%1" + %V1ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) (define_expand "extendqisi2" @@ -1508,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 "" @@ -1519,7 +1931,7 @@ ext %0,%1,8<0> or %0,%#r0,%q1 subu %0,%#r0,%Q1 - ld.b %0,%1" + %V1ld.b %0,%1" [(set_attr "type" "bit,arith,arith,load")]) ;; Conversions between float and double. @@ -1611,32 +2023,6 @@ 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 @@ -1697,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")]) @@ -1706,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")]) @@ -1714,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 @@ -1788,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")]) @@ -1797,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")]) @@ -1805,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 ;; @@ -1933,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; }") @@ -1962,7 +2405,6 @@ if (op2 == const0_rtx) { emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); emit_insn (gen_dummy (op0)); DONE; } @@ -2004,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)); @@ -2073,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)); @@ -2134,7 +2569,6 @@ if (op2 == const0_rtx) { emit_insn (gen_trap_divide_by_zero ()); - emit_barrier (); emit_insn (gen_dummy (operands[0])); DONE; } @@ -2532,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 "" @@ -2540,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 "" @@ -2548,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 "" @@ -2556,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. @@ -2764,6 +3198,25 @@ "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. (define_insn "" @@ -2883,18 +3336,14 @@ 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") @@ -2905,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") @@ -3061,10 +3506,26 @@ (define_insn "return" [(return)] - "null_epilogue ()" + "reload_completed" "jmp%. %#r1" [(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"))] ""