|
|
1.1 ! root 1: ;;- Machine description for the Motorola 88000 for GNU C compiler ! 2: ;; Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc. ! 3: ;; Contributed by Michael Tiemann ([email protected]) ! 4: ;; Additional changes by Michael Meissner ([email protected]) ! 5: ;; Currently supported by Tom Wood ([email protected]) ! 6: ! 7: ;; This file is part of GNU CC. ! 8: ! 9: ;; GNU CC is free software; you can redistribute it and/or modify ! 10: ;; it under the terms of the GNU General Public License as published by ! 11: ;; the Free Software Foundation; either version 2, or (at your option) ! 12: ;; any later version. ! 13: ! 14: ;; GNU CC is distributed in the hope that it will be useful, ! 15: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 17: ;; GNU General Public License for more details. ! 18: ! 19: ;; You should have received a copy of the GNU General Public License ! 20: ;; along with GNU CC; see the file COPYING. If not, write to ! 21: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 22: ! 23: ! 24: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ! 25: ! 26: ;; SCCS rev field. This is a NOP, just to get the SCCS id into the ! 27: ;; program image. ! 28: (define_expand "m88k_sccs_id" ! 29: [(match_operand:SI 0 "" "")] ! 30: "" ! 31: "{ static char sccs_id[] = \"@(#)m88k.md 1.96.4.3 1/14/92 09:46:15\"; ! 32: FAIL; }") ! 33: ! 34: ;; Attribute specifications ! 35: ! 36: ; Type of each instruction. Default is arithmetic. ! 37: ; I'd like to write the list as this, but genattrtab won't accept it. ! 38: ; ! 39: ; "branch,jump,call, ; flow-control instructions ! 40: ; load,store,loada, ; data unit instructions ! 41: ; spadd,dpadd,spdiv,dpdiv,idiv, ; FPU add instructions ! 42: ; spmul,dpmul,imul, ; FPU multiply instructions ! 43: ; arith, ; integer unit instructions ! 44: ; marith,mstore,mfp,weird" ; multi-word instructions ! 45: ! 46: ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word. ! 47: (define_attr "type" ! 48: "branch,jump,call,load,store,loada,spadd,dpadd,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,marith,mstore,mfp,weird" ! 49: (const_string "arith")) ! 50: ! 51: ; Convenience attributes. ! 52: (define_attr "fpu" "yes,no" ! 53: (if_then_else ! 54: (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spdiv,dpdiv,idiv,mfp") ! 55: (const_string "yes") (const_string "no"))) ! 56: ! 57: ; Length in # of instructions of each insn. The values are not exact, but ! 58: ; are safe. ! 59: (define_attr "length" "" ! 60: (cond [(eq_attr "type" "marith,mstore,mfp") ! 61: (const_int 2)] ! 62: (const_int 1))) ! 63: ! 64: ; Describe a user's asm statement. ! 65: (define_asm_attributes ! 66: [(set_attr "type" "weird")]) ! 67: ! 68: ; Define the delay slot requirements for branches and calls. ! 69: ; The m88100 annuls instructions if a conditional branch is taken. ! 70: ; For insns of TYPE_BRANCH that are multi-word instructions, the ! 71: ; delay slot applies to the first instruction. ! 72: ! 73: ; @@ For the moment, reorg.c requires that the delay slot of a branch not ! 74: ; be a call or branch. ! 75: ! 76: (define_delay (eq_attr "type" "branch,jump") ! 77: [(and ! 78: (and ! 79: (eq_attr "type" "!branch,jump,call,marith,mstore,mfp,weird") ; required. ! 80: (eq_attr "type" "!load")) ; issue as-soon-as-possible. ! 81: (eq_attr "fpu" "no")) ; issue as-soon-as-possible. ! 82: (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1) ! 83: ! 84: ; output_call supports an unconditional branch in the delay slot of ! 85: ; a call. (@@ Support for this case is expected in reorg.c soon.) ! 86: ! 87: (define_delay (eq_attr "type" "call") ! 88: [(eq_attr "type" "!branch,call,marith,mstore,mfp,weird") ; required. ! 89: (nil) (nil)]) ! 90: ! 91: ; An abstract block diagram of the function units for the m88100. ! 92: ; ! 93: ; * ! 94: ; | ! 95: ; +---v----+ ! 96: ; | decode | ! 97: ; +-vv-v-v-+ fpu ! 98: ; ,----------'| | `----------------------. ! 99: ; | | | | ,-----. ! 100: ; load | store | | arith | | | ! 101: ; | | | +-v-v-+ | dp source ! 102: ; | | | | fp1 |---' ! 103: ; store | | | div +-v-v-+ ! 104: ; ,------. | | | ,-----. ,-----------' `-----------. ! 105: ; | | | | | | | | | ! 106: ; | +--v---v--+ ,---' | | +-v-v---+ +---v---+ ! 107: ; | | stage 2 | | | `---| add 2 | | mul 2 | ! 108: ; | +---------+ | +--v--+ +-------+ imul +-------+ ! 109: ; | | stage 1 | | | alu | | add 3 | ,--------| mul 3 | ! 110: ; | +---------+ | +--v--+ +-------+ | +-------+ ! 111: ; | | stage 0 | | | | add 4 | | | mul 4 | ! 112: ; | +--v---v--+ | | +---v---+ | +-------+ ! 113: ; | | | | | | | | mul 5 | ! 114: ; | * | | | | | +---v---+ ! 115: ; | | | | | +----v----+ | ! 116: ; | load | | | fp add `------>| fp last |<------' fp mul ! 117: ; | | | | +---v-v--^+ ! 118: ; | | | | | | | ! 119: ; | | | | | `--' dp dest ! 120: ; | | +--v-----v--+ | ! 121: ; | `--->| writeback |<--------------------' ! 122: ; | +--v-----v--+ ! 123: ; | | | ! 124: ; `------------------' * ! 125: ; ! 126: ; The decode unit need not be specified. ! 127: ; Consideration of writeback contention is critical to superb scheduling. ! 128: ; ! 129: ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY ! 130: ; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST]) ! 131: ! 132: ;(define_function_unit "decode" 1 1 (const_int 1) 0 1) ! 133: ! 134: ; Describing the alu is currently not useful. ! 135: ;(define_function_unit "alu" 1 0 (eq_attr "type" ! 136: ; "!store,mstore,marith,mfp,weird") 1 0) ! 137: ;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0) ! 138: ! 139: (define_function_unit "memory" 1 3 (eq_attr "type" "load") 3 2) ! 140: ! 141: ; The fp1 and fplast descriptions currently have no effect. ! 142: ;(define_function_unit "fp1" 1 1 (eq_attr "fpu" "yes") 1 2) ! 143: ! 144: ; The times are adjusted to include fp1 and fplast, but then are further ! 145: ; adjusted based on the actual generated code. The notation to the right ! 146: ; is the total latency. A range denotes a group of instructions and/or ! 147: ; conditions (the extra clock of fplast time with some sequences). ! 148: (define_function_unit "fpmul" 1 4 (eq_attr "type" "spmul") 4 2) ; 6-8 ! 149: (define_function_unit "fpmul" 1 4 (eq_attr "type" "dpmul,mfp") 7 2) ; 9-10 ! 150: (define_function_unit "fpmul" 1 4 (eq_attr "type" "imul") 3 2) ; 4 ! 151: ! 152: (define_function_unit "fpadd" 1 3 (eq_attr "type" "spadd") 3 2) ; 5-6 ! 153: (define_function_unit "fpadd" 1 3 (eq_attr "type" "dpadd") 4 2) ; 6-7 ! 154: (define_function_unit "fpadd" 1 3 (eq_attr "type" "spdiv") 30 2) ; 30-31 ! 155: (define_function_unit "fpadd" 1 3 (eq_attr "type" "dpdiv") 60 2) ; 60-61 ! 156: (define_function_unit "fpadd" 1 3 (eq_attr "type" "idiv") 38 2) ; 38 ! 157: ! 158: ;(define_function_unit "fplast" 1 1 (eq_attr "fpu" "yes") 1 2) ! 159: ! 160: ; Describing writeback contention is currently not useful. ! 161: ;(define_function_unit "writeback" 1 1 ! 162: ; (eq_attr "type" "!store,mstore,branch,jump,call") 0 1) ! 163: ! 164: ; Describing stores is currently not useful. The suggestion here is that the ! 165: ; function unit ordering has already been established (writeback is last) and ! 166: ; that store insns use the units in an unusal order. ! 167: ;(define_function_unit "writeback" 1 1 (eq_attr "type" "store,mstore") 0 1) ! 168: ;(define_function_unit "memory" 1 3 (eq_attr "type" "store,mstore") 1 2) ! 169: ! 170: ;; This rich set of complex patterns are mostly due to Torbjorn Granlund ! 171: ;; ([email protected]). They've changed since then, so don't complain to him ! 172: ;; if they don't work right. ! 173: ! 174: ;; Regarding shifts, gen_lshlsi3 generates ASHIFT. LSHIFT opcodes are ! 175: ;; not produced and should not normally occur. Also, the gen functions ! 176: ;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing ! 177: ;; special needs to be done here. ! 178: ! 179: ;; (a << int1) >> int2 optimizations into a single extract. ! 180: ;; These patterns need to occur before the normal shift patterns ! 181: ! 182: (define_insn "" ! 183: [(set (match_operand:SI 0 "register_operand" "=r") ! 184: (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 185: (match_operand:SI 2 "int5_operand" "")) ! 186: (match_operand:SI 3 "int5_operand" "")))] ! 187: "INTVAL (operands [2]) <= INTVAL (operands [3])" ! 188: "ext %0,%1,%w3<(%3-%2)>") ! 189: ! 190: (define_insn "" ! 191: [(set (match_operand:SI 0 "register_operand" "=r") ! 192: (lshiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 193: (match_operand:SI 2 "int5_operand" "")) ! 194: (match_operand:SI 3 "int5_operand" "")))] ! 195: "INTVAL (operands [2]) <= INTVAL (operands [3])" ! 196: "extu %0,%1,%w3<(%3-%2)>") ! 197: ! 198: ;; Optimize possible cases of the set instruction. ! 199: ! 200: (define_insn "" ! 201: [(set (match_operand:SI 0 "register_operand" "=r") ! 202: (ashift:SI (const_int -1) ! 203: (match_operand:SI 1 "register_operand" "r")))] ! 204: "" ! 205: "set %0,%#r0,%1") ! 206: ! 207: (define_insn "" ! 208: [(set (match_operand:SI 0 "register_operand" "=r") ! 209: (ior:SI (ashift:SI (const_int -1) ! 210: (match_operand:SI 1 "register_operand" "r")) ! 211: (match_operand:SI 2 "register_operand" "r")))] ! 212: "" ! 213: "set %0,%2,%1") ! 214: ! 215: (define_insn "" ! 216: [(set (match_operand:SI 0 "register_operand" "=r") ! 217: (ior:SI (match_operand:SI 1 "register_operand" "r") ! 218: (ashift:SI (const_int -1) ! 219: (match_operand:SI 2 "register_operand" "r"))))] ! 220: "" ! 221: "set %0,%1,%2") ! 222: ! 223: ;; Optimize possible cases of the mak instruction. ! 224: ! 225: (define_insn "" ! 226: [(set (match_operand:SI 0 "register_operand" "=r") ! 227: (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 228: (match_operand:SI 2 "int5_operand" "")) ! 229: (match_operand:SI 3 "immediate_operand" "n")))] ! 230: "mak_mask_p (INTVAL (operands[3]) >> INTVAL (operands[2]))" ! 231: "* ! 232: { ! 233: operands[4] = gen_rtx (CONST_INT, SImode, ! 234: exact_log2 (1 + (INTVAL (operands[3]) ! 235: >> INTVAL(operands[2])))); ! 236: return \"mak %0,%1,%4<%2>\"; ! 237: }") ! 238: ! 239: ;; Optimize possible cases of output_and. ! 240: ! 241: (define_insn "" ! 242: [(set (match_operand:SI 0 "register_operand" "=r") ! 243: (ashift:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 244: (match_operand:SI 2 "int5_operand" "") ! 245: (match_operand:SI 3 "int5_operand" "")) ! 246: (match_operand:SI 4 "int5_operand" "")))] ! 247: "INTVAL (operands[2]) + INTVAL (operands[3]) + INTVAL (operands[4]) == 32" ! 248: "* ! 249: { ! 250: operands[2] ! 251: = gen_rtx (CONST_INT, SImode, ! 252: ((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[4])); ! 253: return output_and (operands); ! 254: }" ! 255: [(set_attr "type" "marith")]) ; length is 1 or 2. ! 256: ! 257: ;; Recognize bcnd instructions for integer values. This is distinguished ! 258: ;; from a conditional branch instruction (below) with SImode instead of ! 259: ;; CCmode. ! 260: ! 261: (define_insn "" ! 262: [(set (pc) ! 263: (if_then_else ! 264: (match_operator 0 "relop_no_unsigned" ! 265: [(match_operand:SI 1 "register_operand" "r") ! 266: (const_int 0)]) ! 267: (match_operand 2 "pc_or_label_ref" "") ! 268: (match_operand 3 "pc_or_label_ref" "")))] ! 269: "" ! 270: "bcnd%. %R3%B0,%1,%P2%P3" ! 271: [(set_attr "type" "branch")]) ! 272: ! 273: ;; Recognize tests for sign and zero. ! 274: ! 275: (define_insn "" ! 276: [(set (pc) ! 277: (if_then_else ! 278: (match_operator 0 "equality_op" ! 279: [(match_operand:SI 1 "register_operand" "r") ! 280: (const_int -2147483648)]) ! 281: (match_operand 2 "pc_or_label_ref" "") ! 282: (match_operand 3 "pc_or_label_ref" "")))] ! 283: "" ! 284: "bcnd%. %R3%E0,%1,%P2%P3" ! 285: [(set_attr "type" "branch")]) ! 286: ! 287: (define_insn "" ! 288: [(set (pc) ! 289: (if_then_else ! 290: (match_operator 0 "equality_op" ! 291: [(zero_extract:SI ! 292: (match_operand:SI 1 "register_operand" "r") ! 293: (const_int 31) ! 294: (const_int 1)) ! 295: (const_int 0)]) ! 296: (match_operand 2 "pc_or_label_ref" "") ! 297: (match_operand 3 "pc_or_label_ref" "")))] ! 298: "" ! 299: "bcnd%. %R3%D0,%1,%P2%P3" ! 300: [(set_attr "type" "branch")]) ! 301: ! 302: ;; Recognize bcnd instructions for double integer values ! 303: ! 304: (define_insn "" ! 305: [(set (pc) ! 306: (if_then_else ! 307: (match_operator 0 "relop_no_unsigned" ! 308: [(sign_extend:DI ! 309: (match_operand:SI 1 "register_operand" "r")) ! 310: (const_int 0)]) ! 311: (match_operand 2 "pc_or_label_ref" "") ! 312: (match_operand 3 "pc_or_label_ref" "")))] ! 313: "" ! 314: "bcnd%. %R3%B0,%1,%P2%P3" ! 315: [(set_attr "type" "branch")]) ! 316: ! 317: (define_insn "" ! 318: [(set (pc) ! 319: (if_then_else ! 320: (match_operator 0 "equality_op" ! 321: [(zero_extend:DI ! 322: (match_operand:SI 1 "register_operand" "r")) ! 323: (const_int 0)]) ! 324: (match_operand 2 "pc_or_label_ref" "") ! 325: (match_operand 3 "pc_or_label_ref" "")))] ! 326: "" ! 327: "bcnd%. %R3%B0,%1,%P2%P3" ! 328: [(set_attr "type" "branch")]) ! 329: ! 330: ; @@ I doubt this is interesting until cmpdi is provided. Anyway, it needs ! 331: ; to be reworked. ! 332: ; ! 333: ;(define_insn "" ! 334: ; [(set (pc) ! 335: ; (if_then_else ! 336: ; (match_operator 0 "relop_no_unsigned" ! 337: ; [(match_operand:DI 1 "register_operand" "r") ! 338: ; (const_int 0)]) ! 339: ; (match_operand 2 "pc_or_label_ref" "") ! 340: ; (match_operand 3 "pc_or_label_ref" "")))] ! 341: ; "" ! 342: ; "* ! 343: ;{ ! 344: ; switch (GET_CODE (operands[0])) ! 345: ; { ! 346: ; case EQ: ! 347: ; case NE: ! 348: ; /* I'm not sure if it's safe to use .n here. */ ! 349: ; return \"or %!,%1,%d1\;bcnd %R3%B0,%!,%P2%P3\"; ! 350: ; case GE: ! 351: ; case LT: ! 352: ; return \"bcnd%. %R3%B0,%1,%P2%P3\"; ! 353: ; case GT: ! 354: ; { ! 355: ; rtx op2 = operands[2]; ! 356: ; operands[2] = operands[3]; ! 357: ; operands[3] = op2; ! 358: ; } ! 359: ; case LE: ! 360: ; if (GET_CODE (operands[3]) == LABEL_REF) ! 361: ; { ! 362: ; int label_num; ! 363: ; operands[2] = gen_label_rtx (); ! 364: ; label_num = XINT (operands[2], 3); ! 365: ; output_asm_insn ! 366: ; (\"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#ne0,%!,%3\", operands); ! 367: ; output_label (label_num); ! 368: ; return \"\"; ! 369: ; } ! 370: ; else ! 371: ; return \"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#eq0,%!,%2\"; ! 372: ; } ! 373: ;}") ! 374: ! 375: ;; Recognize bcnd instructions for single precision float values ! 376: ;; Exclude relational operations as they must signal NaNs. ! 377: ! 378: ;; @@ These bcnd insns for float and double values don't seem to be recognized. ! 379: ! 380: (define_insn "" ! 381: [(set (pc) ! 382: (if_then_else ! 383: (match_operator 0 "equality_op" ! 384: [(float_extend:DF ! 385: (match_operand:SF 1 "register_operand" "r")) ! 386: (const_int 0)]) ! 387: (match_operand 2 "pc_or_label_ref" "") ! 388: (match_operand 3 "pc_or_label_ref" "")))] ! 389: "" ! 390: "bcnd%. %R3%D0,%1,%P2%P3" ! 391: [(set_attr "type" "branch")]) ! 392: ! 393: (define_insn "" ! 394: [(set (pc) ! 395: (if_then_else ! 396: (match_operator 0 "equality_op" ! 397: [(match_operand:SF 1 "register_operand" "r") ! 398: (const_int 0)]) ! 399: (match_operand 2 "pc_or_label_ref" "") ! 400: (match_operand 3 "pc_or_label_ref" "")))] ! 401: "" ! 402: "bcnd%. %R3%D0,%1,%P2%P3" ! 403: [(set_attr "type" "branch")]) ! 404: ! 405: ;; Recognize bcnd instructions for double precision float values ! 406: ;; Exclude relational operations as they must signal NaNs. ! 407: ! 408: (define_insn "" ! 409: [(set (pc) ! 410: (if_then_else ! 411: (match_operator 0 "equality_op" ! 412: [(match_operand:DF 1 "register_operand" "r") ! 413: (const_int 0)]) ! 414: (match_operand 2 "pc_or_label_ref" "") ! 415: (match_operand 3 "pc_or_label_ref" "")))] ! 416: "" ! 417: "* ! 418: { ! 419: int label_num; ! 420: ! 421: if (GET_CODE (operands[0]) == NE) ! 422: { ! 423: rtx op2 = operands[2]; ! 424: operands[2] = operands[3]; ! 425: operands[3] = op2; ! 426: } ! 427: if (GET_CODE (operands[3]) == LABEL_REF) ! 428: return \"bcnd%. 0x5,%1,%3\;bcnd %#ne0,%d1,%3\"; ! 429: ! 430: operands[3] = gen_label_rtx (); ! 431: label_num = XINT (operands[3], 3); ! 432: output_asm_insn (\"bcnd%. 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands); ! 433: output_label (label_num); ! 434: return \"\"; ! 435: }" ! 436: [(set_attr "type" "branch")]) ! 437: ! 438: ;; Recognize bb0 and bb1 instructions. These use two unusual template ! 439: ;; patterns, %Lx and %Px. %Lx outputs a 1 if operand `x' is a LABEL_REF ! 440: ;; otherwise it outputs a 0. It then may print ".n" if the delay slot ! 441: ;; is used. %Px does noting if `x' is PC and outputs the operand if `x' ! 442: ;; is a LABEL_REF. ! 443: ! 444: (define_insn "" ! 445: [(set (pc) ! 446: (if_then_else ! 447: (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r") ! 448: (const_int 1) ! 449: (match_operand:SI 1 "int5_operand" "")) ! 450: (const_int 0)) ! 451: (match_operand 2 "pc_or_label_ref" "") ! 452: (match_operand 3 "pc_or_label_ref" "")))] ! 453: "" ! 454: "bb%L2 (31-%1),%0,%P2%P3" ! 455: [(set_attr "type" "branch")]) ! 456: ! 457: (define_insn "" ! 458: [(set (pc) ! 459: (if_then_else ! 460: (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r") ! 461: (const_int 1) ! 462: (match_operand:SI 1 "int5_operand" "")) ! 463: (const_int 0)) ! 464: (match_operand 2 "pc_or_label_ref" "") ! 465: (match_operand 3 "pc_or_label_ref" "")))] ! 466: "" ! 467: "bb%L3 (31-%1),%0,%P2%P3" ! 468: [(set_attr "type" "branch")]) ! 469: ! 470: (define_insn "" ! 471: [(set (pc) ! 472: (if_then_else ! 473: (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") ! 474: (const_int 1) ! 475: (match_operand:SI 1 "int5_operand" "")) ! 476: (const_int 0)) ! 477: (match_operand 2 "pc_or_label_ref" "") ! 478: (match_operand 3 "pc_or_label_ref" "")))] ! 479: "" ! 480: "bb%L2 (31-%1),%0,%P2%P3" ! 481: [(set_attr "type" "branch")]) ! 482: ! 483: (define_insn "" ! 484: [(set (pc) ! 485: (if_then_else ! 486: (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") ! 487: (const_int 1) ! 488: (match_operand:SI 1 "int5_operand" "")) ! 489: (const_int 0)) ! 490: (match_operand 2 "pc_or_label_ref" "") ! 491: (match_operand 3 "pc_or_label_ref" "")))] ! 492: "" ! 493: "bb%L3 (31-%1),%0,%P2%P3" ! 494: [(set_attr "type" "branch")]) ! 495: ! 496: (define_insn "" ! 497: [(set (pc) ! 498: (if_then_else ! 499: (eq (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") ! 500: (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) ! 501: (const_int 0)) ! 502: (match_operand 2 "pc_or_label_ref" "") ! 503: (match_operand 3 "pc_or_label_ref" "")))] ! 504: "(GET_CODE (operands[0]) == CONST_INT) ! 505: != (GET_CODE (operands[1]) == CONST_INT)" ! 506: "bb%L3 %p1,%0,%P2%P3" ! 507: [(set_attr "type" "branch")]) ! 508: ! 509: (define_insn "" ! 510: [(set (pc) ! 511: (if_then_else ! 512: (ne (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") ! 513: (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) ! 514: (const_int 0)) ! 515: (match_operand 2 "pc_or_label_ref" "") ! 516: (match_operand 3 "pc_or_label_ref" "")))] ! 517: "(GET_CODE (operands[0]) == CONST_INT) ! 518: != (GET_CODE (operands[1]) == CONST_INT)" ! 519: "bb%L2 %p1,%0,%P2%P3" ! 520: [(set_attr "type" "branch")]) ! 521: ! 522: ;; The comparison operations store the comparison into a register and ! 523: ;; record that register. The following Bxx or Sxx insn uses that ! 524: ;; register as an input. To facilitate use of bcnd instead of cmp/bb1, ! 525: ;; cmpsi records it's operands and produces no code when any operand ! 526: ;; is constant. In this case, the Bxx insns use gen_bcnd and the ! 527: ;; Sxx insns use gen_test to ensure a cmp has been emitted. ! 528: ;; ! 529: ;; This could also be done for SFmode and DFmode having only beq and bne ! 530: ;; use gen_bcnd. The others must signal NaNs. It seems though that zero ! 531: ;; has already been copied into a register. ! 532: ;; ! 533: ;; cmpsi/beq and cmpsi/bne can always be done with bcnd if any operand ! 534: ;; is a constant. (This idea is due to Torbjorn Granlund.) Others can ! 535: ;; use bcnd only if an operand is zero. ! 536: ;; ! 537: ;; It is necessary to distinguish a register holding condition codes. ! 538: ;; This is done by context. ! 539: ! 540: (define_expand "test" ! 541: [(set (match_dup 2) ! 542: (compare:CC (match_operand 0 "" "") ! 543: (match_operand 1 "" "")))] ! 544: "" ! 545: " ! 546: { ! 547: if (m88k_compare_reg) ! 548: abort (); ! 549: ! 550: if (GET_CODE (operands[0]) == CONST_INT ! 551: && ! SMALL_INT (operands[0])) ! 552: operands[0] = force_reg (SImode, operands[0]); ! 553: ! 554: if (GET_CODE (operands[1]) == CONST_INT ! 555: && ! SMALL_INT (operands[1])) ! 556: operands[1] = force_reg (SImode, operands[1]); ! 557: ! 558: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); ! 559: }") ! 560: ! 561: ; @@ The docs say don't do this. It's probably a nop since the insn looks ! 562: ; identical to cmpsi against zero. Is there an advantage to providing ! 563: ; this, perhaps with a different form? ! 564: ! 565: ;(define_expand "tstsi" ! 566: ; [(set (match_dup 1) ! 567: ; (compare:CC (match_operand:SI 0 "register_operand" "") ! 568: ; (const_int 0)))] ! 569: ; "" ! 570: ; " ! 571: ;{ ! 572: ; m88k_compare_reg = 0; ! 573: ; m88k_compare_op0 = operands[0]; ! 574: ; m88k_compare_op1 = const0_rtx; ! 575: ; DONE; ! 576: ;}") ! 577: ! 578: (define_expand "cmpsi" ! 579: [(set (match_dup 2) ! 580: (compare:CC (match_operand:SI 0 "register_operand" "") ! 581: (match_operand:SI 1 "arith32_operand" "")))] ! 582: "" ! 583: " ! 584: { ! 585: if (GET_CODE (operands[0]) == CONST_INT ! 586: || GET_CODE (operands[1]) == CONST_INT) ! 587: { ! 588: m88k_compare_reg = 0; ! 589: m88k_compare_op0 = operands[0]; ! 590: m88k_compare_op1 = operands[1]; ! 591: DONE; ! 592: } ! 593: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); ! 594: }") ! 595: ! 596: (define_expand "cmpsf" ! 597: [(set (match_dup 2) ! 598: (compare:CC (match_operand:SF 0 "register_operand" "") ! 599: (match_operand:SF 1 "register_operand" "")))] ! 600: "" ! 601: "operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);") ! 602: ! 603: (define_expand "cmpdf" ! 604: [(set (match_dup 2) ! 605: (compare:CC (match_operand:DF 0 "general_operand" "") ! 606: (match_operand:DF 1 "general_operand" "")))] ! 607: "" ! 608: " ! 609: { ! 610: operands[0] = legitimize_operand (operands[0], DFmode); ! 611: operands[1] = legitimize_operand (operands[1], DFmode); ! 612: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode); ! 613: }") ! 614: ! 615: ; @@ Get back to this later on. ! 616: ; ! 617: ;(define_insn "cmpdi" ! 618: ; [(set (cc0) ! 619: ; (compare:CC (match_operand:DI 0 "register_operand" "r") ! 620: ; (match_operand:DI 1 "register_operand" "r")))] ! 621: ; "" ! 622: ; "* ! 623: ;{ ! 624: ; if ((cc_status.mdep & MDEP_LS_CHANGE) != 0) ! 625: ; abort (); /* output_move_double MDEP_LS_CHANGE bits were set. */ ! 626: ; ! 627: ; cc_status.mdep &= ~ MDEP_LS_MASK; ! 628: ; ! 629: ; operands[2] = gen_label_rtx (); ! 630: ; /* Remember, %! is the condition code register and %@ is the ! 631: ; literal synthesis register. */ ! 632: ; ! 633: ; output_asm_insn (\"cmp %!,%0,%1\;bb0 %#eq,%!,%l2\;cmp %!,%d0,%d1\", ! 634: ; operands); ! 635: ; ! 636: ; output_asm_insn (\"extu %@,%!,4<8>\;clr %!,%!,4<4>\", operands); ! 637: ; output_asm_insn (\"mak %@,%@,4<4>\;or %!,%!,%@\", operands); ! 638: ; output_label (XINT (operands[2], 3)); ! 639: ; return \"\"; ! 640: ;}" ! 641: ! 642: ;; The actual compare instructions. ! 643: ! 644: (define_insn "" ! 645: [(set (match_operand:CC 0 "register_operand" "=r,r") ! 646: (compare:CC (match_operand:SI 1 "register_operand" "rO,I") ! 647: (match_operand:SI 2 "arith_operand" "rI,r")))] ! 648: "" ! 649: "@ ! 650: cmp %0,%r1,%2 ! 651: cmp %0,%2,%1\;xor.c %0,%#r0,%0" ! 652: [(set_attr "type" "arith,marith")]) ! 653: ! 654: (define_insn "" ! 655: [(set (match_operand:CC 0 "register_operand" "=r,r") ! 656: (compare:CC (match_operand:SF 1 "register_operand" "r,r") ! 657: (match_operand:SF 2 "real_or_0_operand" "r,G")))] ! 658: "" ! 659: "@ ! 660: fcmp.sss %0,%1,%2 ! 661: fcmp.sss %0,%1,%#r0" ! 662: [(set_attr "type" "spadd")]) ! 663: ! 664: (define_insn "" ! 665: [(set (match_operand:CC 0 "register_operand" "=r") ! 666: (compare:CC (match_operand:DF 1 "register_operand" "r") ! 667: (float_extend:DF ! 668: (match_operand:SF 2 "register_operand" "r"))))] ! 669: "" ! 670: "fcmp.sds %0,%1,%2" ! 671: [(set_attr "type" "dpadd")]) ! 672: ! 673: (define_insn "" ! 674: [(set (match_operand:CC 0 "register_operand" "=r") ! 675: (compare:CC (float_extend:DF ! 676: (match_operand:SF 1 "register_operand" "r")) ! 677: (match_operand:DF 2 "register_operand" "r")))] ! 678: "" ! 679: "fcmp.ssd %0,%1,%2" ! 680: [(set_attr "type" "dpadd")]) ! 681: ! 682: (define_insn "" ! 683: [(set (match_operand:CC 0 "register_operand" "=r,r") ! 684: (compare:CC (match_operand:DF 1 "register_operand" "r,r") ! 685: (match_operand:DF 2 "real_or_0_operand" "r,G")))] ! 686: "" ! 687: "@ ! 688: fcmp.sdd %0,%1,%2 ! 689: fcmp.sds %0,%1,%#r0" ! 690: [(set_attr "type" "dpadd")]) ! 691: ! 692: ;; Store condition code insns. The compare insns set a register ! 693: ;; rather than cc0 and record that register for use here. See above ! 694: ;; for the special treatment of cmpsi with a constant operand. ! 695: ! 696: (define_expand "seq" ! 697: [(set (match_operand:SI 0 "register_operand" "") ! 698: (match_dup 1))] ! 699: "" ! 700: "operands[1] = emit_test (EQ, SImode);") ! 701: ! 702: (define_expand "sne" ! 703: [(set (match_operand:SI 0 "register_operand" "") ! 704: (match_dup 1))] ! 705: "" ! 706: "operands[1] = emit_test (NE, SImode);") ! 707: ! 708: (define_expand "sgt" ! 709: [(set (match_operand:SI 0 "register_operand" "") ! 710: (match_dup 1))] ! 711: "" ! 712: "operands[1] = emit_test (GT, SImode);") ! 713: ! 714: (define_expand "sgtu" ! 715: [(set (match_operand:SI 0 "register_operand" "") ! 716: (match_dup 1))] ! 717: "" ! 718: "operands[1] = emit_test (GTU, SImode);") ! 719: ! 720: (define_expand "slt" ! 721: [(set (match_operand:SI 0 "register_operand" "") ! 722: (match_dup 1))] ! 723: "" ! 724: "operands[1] = emit_test (LT, SImode);") ! 725: ! 726: (define_expand "sltu" ! 727: [(set (match_operand:SI 0 "register_operand" "") ! 728: (match_dup 1))] ! 729: "" ! 730: "operands[1] = emit_test (LTU, SImode);") ! 731: ! 732: (define_expand "sge" ! 733: [(set (match_operand:SI 0 "register_operand" "") ! 734: (match_dup 1))] ! 735: "" ! 736: "operands[1] = emit_test (GE, SImode);") ! 737: ! 738: (define_expand "sgeu" ! 739: [(set (match_operand:SI 0 "register_operand" "") ! 740: (match_dup 1))] ! 741: "" ! 742: "operands[1] = emit_test (GEU, SImode);") ! 743: ! 744: (define_expand "sle" ! 745: [(set (match_operand:SI 0 "register_operand" "") ! 746: (match_dup 1))] ! 747: "" ! 748: "operands[1] = emit_test (LE, SImode);") ! 749: ! 750: (define_expand "sleu" ! 751: [(set (match_operand:SI 0 "register_operand" "") ! 752: (match_dup 1))] ! 753: "" ! 754: "operands[1] = emit_test (LEU, SImode);") ! 755: ! 756: ;; The actual set condition code instruction. ! 757: ! 758: (define_insn "" ! 759: [(set (match_operand:SI 0 "register_operand" "=r") ! 760: (match_operator:SI 1 "relop" ! 761: [(match_operand:CC 2 "register_operand" "r") ! 762: (const_int 0)]))] ! 763: "" ! 764: "ext %0,%2,1<%C1>") ! 765: ! 766: (define_insn "" ! 767: [(set (match_operand:SI 0 "register_operand" "=r") ! 768: (neg:SI ! 769: (match_operator:SI 1 "relop" ! 770: [(match_operand:CC 2 "register_operand" "r") ! 771: (const_int 0)])))] ! 772: "" ! 773: "extu %0,%2,1<%C1>") ! 774: ! 775: ;; Conditional branch insns. The compare insns set a register ! 776: ;; rather than cc0 and record that register for use here. See above ! 777: ;; for the special case of cmpsi with a constant operand. ! 778: ! 779: (define_expand "bcnd" ! 780: [(set (pc) ! 781: (if_then_else (match_operand 0 "" "") ! 782: (label_ref (match_operand 1 "" "")) ! 783: (pc)))] ! 784: "" ! 785: "if (m88k_compare_reg) abort ();") ! 786: ! 787: (define_expand "bxx" ! 788: [(set (pc) ! 789: (if_then_else (match_operand 0 "" "") ! 790: (label_ref (match_operand 1 "" "")) ! 791: (pc)))] ! 792: "" ! 793: "if (m88k_compare_reg == 0) abort ();") ! 794: ! 795: (define_expand "beq" ! 796: [(set (pc) ! 797: (if_then_else (eq (match_dup 1) (const_int 0)) ! 798: (label_ref (match_operand 0 "" "")) ! 799: (pc)))] ! 800: "" ! 801: "if (m88k_compare_reg == 0) ! 802: { ! 803: emit_bcnd (EQ, operands[0]); ! 804: DONE; ! 805: } ! 806: operands[1] = m88k_compare_reg;") ! 807: ! 808: (define_expand "bne" ! 809: [(set (pc) ! 810: (if_then_else (ne (match_dup 1) (const_int 0)) ! 811: (label_ref (match_operand 0 "" "")) ! 812: (pc)))] ! 813: "" ! 814: "if (m88k_compare_reg == 0) ! 815: { ! 816: emit_bcnd (NE, operands[0]); ! 817: DONE; ! 818: } ! 819: operands[1] = m88k_compare_reg;") ! 820: ! 821: (define_expand "bgt" ! 822: [(set (pc) ! 823: (if_then_else (gt (match_dup 1) (const_int 0)) ! 824: (label_ref (match_operand 0 "" "")) ! 825: (pc)))] ! 826: "" ! 827: "if (m88k_compare_reg == 0) ! 828: { ! 829: emit_bcnd (GT, operands[0]); ! 830: DONE; ! 831: } ! 832: operands[1] = m88k_compare_reg;") ! 833: ! 834: (define_expand "bgtu" ! 835: [(set (pc) ! 836: (if_then_else (gtu (match_dup 1) (const_int 0)) ! 837: (label_ref (match_operand 0 "" "")) ! 838: (pc)))] ! 839: "" ! 840: "if (m88k_compare_reg == 0) ! 841: { ! 842: emit_jump_insn (gen_bxx (emit_test (GTU, VOIDmode), operands[0])); ! 843: DONE; ! 844: } ! 845: operands[1] = m88k_compare_reg;") ! 846: ! 847: (define_expand "blt" ! 848: [(set (pc) ! 849: (if_then_else (lt (match_dup 1) (const_int 0)) ! 850: (label_ref (match_operand 0 "" "")) ! 851: (pc)))] ! 852: "" ! 853: "if (m88k_compare_reg == 0) ! 854: { ! 855: emit_bcnd (LT, operands[0]); ! 856: DONE; ! 857: } ! 858: operands[1] = m88k_compare_reg;") ! 859: ! 860: (define_expand "bltu" ! 861: [(set (pc) ! 862: (if_then_else (ltu (match_dup 1) (const_int 0)) ! 863: (label_ref (match_operand 0 "" "")) ! 864: (pc)))] ! 865: "" ! 866: "if (m88k_compare_reg == 0) ! 867: { ! 868: emit_jump_insn (gen_bxx (emit_test (LTU, VOIDmode), operands[0])); ! 869: DONE; ! 870: } ! 871: operands[1] = m88k_compare_reg;") ! 872: ! 873: (define_expand "bge" ! 874: [(set (pc) ! 875: (if_then_else (ge (match_dup 1) (const_int 0)) ! 876: (label_ref (match_operand 0 "" "")) ! 877: (pc)))] ! 878: "" ! 879: "if (m88k_compare_reg == 0) ! 880: { ! 881: emit_bcnd (GE, operands[0]); ! 882: DONE; ! 883: } ! 884: operands[1] = m88k_compare_reg;") ! 885: ! 886: (define_expand "bgeu" ! 887: [(set (pc) ! 888: (if_then_else (geu (match_dup 1) (const_int 0)) ! 889: (label_ref (match_operand 0 "" "")) ! 890: (pc)))] ! 891: "" ! 892: "if (m88k_compare_reg == 0) ! 893: { ! 894: emit_jump_insn (gen_bxx (emit_test (GEU, VOIDmode), operands[0])); ! 895: DONE; ! 896: } ! 897: operands[1] = m88k_compare_reg;") ! 898: ! 899: (define_expand "ble" ! 900: [(set (pc) ! 901: (if_then_else (le (match_dup 1) (const_int 0)) ! 902: (label_ref (match_operand 0 "" "")) ! 903: (pc)))] ! 904: "" ! 905: "if (m88k_compare_reg == 0) ! 906: { ! 907: emit_bcnd (LE, operands[0]); ! 908: DONE; ! 909: } ! 910: operands[1] = m88k_compare_reg;") ! 911: ! 912: (define_expand "bleu" ! 913: [(set (pc) ! 914: (if_then_else (leu (match_dup 1) (const_int 0)) ! 915: (label_ref (match_operand 0 "" "")) ! 916: (pc)))] ! 917: "" ! 918: "if (m88k_compare_reg == 0) ! 919: { ! 920: emit_jump_insn (gen_bxx (emit_test (LEU, VOIDmode), operands[0])); ! 921: DONE; ! 922: } ! 923: operands[1] = m88k_compare_reg;") ! 924: ! 925: ;; The actual conditional branch instruction (both directions). This ! 926: ;; uses two unusual template patterns, %Rx and %Px. %Rx is a prefix code ! 927: ;; for the immediately following condition and reverses the condition iff ! 928: ;; operand `x' is a LABEL_REF. %Px does nothing if `x' is PC and outputs ! 929: ;; the operand if `x' is a LABEL_REF. ! 930: ! 931: (define_insn "" ! 932: [(set (pc) (if_then_else ! 933: (match_operator 0 "relop" ! 934: [(match_operand:CC 1 "register_operand" "r") ! 935: (const_int 0)]) ! 936: (match_operand 2 "pc_or_label_ref" "") ! 937: (match_operand 3 "pc_or_label_ref" "")))] ! 938: "" ! 939: "bb1%. %R3%C0,%1,%P2%P3" ! 940: [(set_attr "type" "branch")]) ! 941: ! 942: ;; SImode move instructions ! 943: ! 944: (define_expand "movsi" ! 945: [(set (match_operand:SI 0 "general_operand" "") ! 946: (match_operand:SI 1 "general_operand" ""))] ! 947: "" ! 948: " ! 949: { ! 950: if (emit_move_sequence (operands, SImode)) ! 951: DONE; ! 952: }") ! 953: ! 954: (define_insn "" ! 955: [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r") ! 956: (match_operand:SI 1 "move_operand" "rI,m,rO,J,M"))] ! 957: "(register_operand (operands[0], SImode) ! 958: || register_operand (operands[1], SImode) ! 959: || operands[1] == const0_rtx)" ! 960: "@ ! 961: or %0,%#r0,%1 ! 962: ld %0,%1 ! 963: st %r1,%0 ! 964: subu %0,%#r0,%n1 ! 965: set %0,%#r0,%s1" ! 966: [(set_attr "type" "arith,load,store,arith,arith")]) ! 967: ! 968: (define_insn "" ! 969: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") ! 970: (match_operand:SI 1 "arith32_operand" "rI,J,L,M,n"))] ! 971: "" ! 972: "@ ! 973: or %0,%#r0,%1 ! 974: subu %0,%#r0,%n1 ! 975: or.u %0,%#r0,%X1 ! 976: set %0,%#r0,%s1 ! 977: or.u %0,%#r0,%X1\;or %0,%0,%x1" ! 978: [(set_attr "type" "arith,arith,arith,arith,marith")]) ! 979: ! 980: ;; @@ Why the constraint "in"? Doesn't `i' include `n'? ! 981: (define_insn "" ! 982: [(set (match_operand:SI 0 "register_operand" "=r") ! 983: (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 984: (match_operand:SI 2 "immediate_operand" "in")))] ! 985: "" ! 986: "or %0,%1,%#lo16(%g2)") ! 987: ! 988: (define_insn "" ! 989: [(set (match_operand:SI 0 "register_operand" "=r") ! 990: (high:SI (match_operand 1 "" "")))] ! 991: "" ! 992: "or.u %0,%#r0,%#hi16(%g1)") ! 993: ! 994: ;; HImode move instructions ! 995: ! 996: (define_expand "movhi" ! 997: [(set (match_operand:HI 0 "general_operand" "") ! 998: (match_operand:HI 1 "general_operand" ""))] ! 999: "" ! 1000: " ! 1001: { ! 1002: if (emit_move_sequence (operands, HImode)) ! 1003: DONE; ! 1004: }") ! 1005: ! 1006: (define_insn "" ! 1007: [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") ! 1008: (match_operand:HI 1 "move_operand" "rP,m,rO,N"))] ! 1009: "(register_operand (operands[0], HImode) ! 1010: || register_operand (operands[1], HImode) ! 1011: || operands[1] == const0_rtx)" ! 1012: "@ ! 1013: or %0,%#r0,%h1 ! 1014: ld.hu %0,%1 ! 1015: st.h %r1,%0 ! 1016: subu %0,%#r0,%H1" ! 1017: [(set_attr "type" "arith,load,store,arith")]) ! 1018: ! 1019: (define_insn "" ! 1020: [(set (match_operand:HI 0 "register_operand" "=r") ! 1021: (subreg:HI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1022: (match_operand:SI 2 "immediate_operand" "in")) 0))] ! 1023: "!flag_pic" ! 1024: "or %0,%1,%#lo16(%2)") ! 1025: ! 1026: ;; QImode move instructions ! 1027: ! 1028: (define_expand "movqi" ! 1029: [(set (match_operand:QI 0 "general_operand" "") ! 1030: (match_operand:QI 1 "general_operand" ""))] ! 1031: "" ! 1032: " ! 1033: { ! 1034: if (emit_move_sequence (operands, QImode)) ! 1035: DONE; ! 1036: }") ! 1037: ! 1038: (define_insn "" ! 1039: [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r") ! 1040: (match_operand:QI 1 "move_operand" "rP,m,rO,N"))] ! 1041: "(register_operand (operands[0], QImode) ! 1042: || register_operand (operands[1], QImode) ! 1043: || operands[1] == const0_rtx)" ! 1044: "@ ! 1045: or %0,%#r0,%q1 ! 1046: ld.bu %0,%1 ! 1047: st.b %r1,%0 ! 1048: subu %r0,%#r0,%Q1" ! 1049: [(set_attr "type" "arith,load,store,arith")]) ! 1050: ! 1051: (define_insn "" ! 1052: [(set (match_operand:QI 0 "register_operand" "=r") ! 1053: (subreg:QI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1054: (match_operand:SI 2 "immediate_operand" "in")) 0))] ! 1055: "!flag_pic" ! 1056: "or %0,%1,%#lo16(%2)") ! 1057: ! 1058: ;; DImode move instructions ! 1059: ! 1060: (define_expand "movdi" ! 1061: [(set (match_operand:DI 0 "general_operand" "") ! 1062: (match_operand:DI 1 "general_operand" ""))] ! 1063: "" ! 1064: " ! 1065: { ! 1066: if (emit_move_sequence (operands, DImode)) ! 1067: DONE; ! 1068: }") ! 1069: ! 1070: (define_insn "" ! 1071: [(set (match_operand:DI 0 "register_operand" "=r") ! 1072: (const_int 0))] ! 1073: "" ! 1074: "or %0,%#r0,0\;or %d0,%#r0,0" ! 1075: [(set_attr "type" "marith")]) ! 1076: ! 1077: (define_insn "" ! 1078: [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m") ! 1079: (match_operand:DI 1 "nonimmediate_operand" "r,m,r"))] ! 1080: "" ! 1081: "@ ! 1082: or %0,%#r0,%1\;or %d0,%#r0,%d1 ! 1083: ld.d %0,%1 ! 1084: st.d %1,%0" ! 1085: [(set_attr "type" "marith,load,store")]) ! 1086: ! 1087: (define_insn "" ! 1088: [(set (match_operand:DI 0 "register_operand" "=r") ! 1089: (subreg:DI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1090: (match_operand:SI 2 "immediate_operand" "in")) 0))] ! 1091: "!flag_pic" ! 1092: "or %0,%1,%#lo16(%2)") ! 1093: ! 1094: (define_insn "" ! 1095: [(set (match_operand:DI 0 "register_operand" "=r") ! 1096: (match_operand:DI 1 "immediate_operand" "n"))] ! 1097: "" ! 1098: "* return output_load_const_dimode (operands);" ! 1099: [(set_attr "type" "marith") ! 1100: (set_attr "length" "4")]) ; length is 2, 3 or 4. ! 1101: ! 1102: ;; DFmode move instructions ! 1103: ! 1104: (define_expand "movdf" ! 1105: [(set (match_operand:DF 0 "general_operand" "") ! 1106: (match_operand:DF 1 "general_operand" ""))] ! 1107: "" ! 1108: " ! 1109: { ! 1110: if (emit_move_sequence (operands, DFmode)) ! 1111: DONE; ! 1112: }") ! 1113: ! 1114: ;; @@ This pattern is incomplete and doesn't appear necessary. ! 1115: ;; ! 1116: ;; This pattern forces (set (reg:DF ...) (const_double ...)) ! 1117: ;; to be reloaded by putting the constant into memory. ! 1118: ;; It must come before the more general movdf pattern. ! 1119: ! 1120: ;(define_insn "" ! 1121: ; [(set (match_operand:DF 0 "general_operand" "=r,o") ! 1122: ; (match_operand:DF 1 "" "G,G"))] ! 1123: ; "GET_CODE (operands[1]) == CONST_DOUBLE" ! 1124: ; "* ! 1125: ;{ ! 1126: ; switch (which_alternative) ! 1127: ; { ! 1128: ; case 0: ! 1129: ; return \"or %0,%#r0,0\;or %d0,%#r0,0\"; ! 1130: ; case 1: ! 1131: ; operands[1] = adj_offsettable_operand (operands[0], 4); ! 1132: ; return \"st %#r0,%0\;st %#r0,%1\"; ! 1133: ; } ! 1134: ;}") ! 1135: ! 1136: (define_insn "" ! 1137: [(set (match_operand:DF 0 "register_operand" "=r") ! 1138: (const_int 0))] ! 1139: "" ! 1140: "or %0,%#r0,0\;or %d0,%#r0,0" ! 1141: [(set_attr "type" "marith")]) ! 1142: ! 1143: (define_insn "" ! 1144: [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m") ! 1145: (match_operand:DF 1 "nonimmediate_operand" "r,m,r"))] ! 1146: "" ! 1147: "@ ! 1148: or %0,%#r0,%1\;or %d0,%#r0,%d1 ! 1149: ld.d %0,%1 ! 1150: st.d %1,%0" ! 1151: [(set_attr "type" "marith,load,store")]) ! 1152: ! 1153: (define_insn "" ! 1154: [(set (match_operand:DF 0 "register_operand" "=r") ! 1155: (subreg:DF (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1156: (match_operand:SI 2 "immediate_operand" "in")) 0))] ! 1157: "!flag_pic" ! 1158: "or %0,%1,%#lo16(%2)") ! 1159: ! 1160: (define_insn "" ! 1161: [(set (match_operand:DF 0 "register_operand" "=r") ! 1162: (match_operand:DF 1 "immediate_operand" "F"))] ! 1163: "" ! 1164: "* return output_load_const_double (operands);" ! 1165: [(set_attr "type" "marith") ! 1166: (set_attr "length" "4")]) ; length is 2, 3, or 4. ! 1167: ! 1168: ;; SFmode move instructions ! 1169: ! 1170: (define_expand "movsf" ! 1171: [(set (match_operand:SF 0 "general_operand" "") ! 1172: (match_operand:SF 1 "general_operand" ""))] ! 1173: "" ! 1174: " ! 1175: { ! 1176: if (emit_move_sequence (operands, SFmode)) ! 1177: DONE; ! 1178: }") ! 1179: ! 1180: ;; @@ What happens to fconst0_rtx? ! 1181: (define_insn "" ! 1182: [(set (match_operand:SF 0 "register_operand" "=r") ! 1183: (const_int 0))] ! 1184: "" ! 1185: "or %0,%#r0,0") ! 1186: ! 1187: (define_insn "" ! 1188: [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") ! 1189: (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))] ! 1190: "" ! 1191: "@ ! 1192: or %0,%#r0,%1 ! 1193: ld %0,%1 ! 1194: st %r1,%0" ! 1195: [(set_attr "type" "arith,load,store")]) ! 1196: ! 1197: (define_insn "" ! 1198: [(set (match_operand:SF 0 "register_operand" "=r") ! 1199: (subreg:SF (lo_sum:SI (match_operand:SI 1 "register_operand" "r") ! 1200: (match_operand:SI 2 "immediate_operand" "in")) 0))] ! 1201: "!flag_pic" ! 1202: "or %0,%1,%#lo16(%2)") ! 1203: ! 1204: (define_insn "" ! 1205: [(set (match_operand:SF 0 "register_operand" "=r") ! 1206: (match_operand:SF 1 "immediate_operand" "F"))] ! 1207: "operands[1] != const0_rtx" ! 1208: "* return output_load_const_float (operands);" ! 1209: [(set_attr "type" "marith")]) ; length is 1 or 2. ! 1210: ! 1211: ;; String/block move insn. See m88k.c for details. ! 1212: ! 1213: (define_expand "movstrsi" ! 1214: [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) ! 1215: (mem:BLK (match_operand:BLK 1 "general_operand" ""))) ! 1216: (use (match_operand:SI 2 "arith32_operand" "")) ! 1217: (use (match_operand:SI 3 "immediate_operand" ""))])] ! 1218: "" ! 1219: " ! 1220: { ! 1221: rtx dest_mem = operands[0]; ! 1222: rtx src_mem = operands[1]; ! 1223: operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); ! 1224: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); ! 1225: expand_block_move (dest_mem, src_mem, operands); ! 1226: DONE; ! 1227: }") ! 1228: ! 1229: ;; Call a non-looping block move library function (e.g. __movstrSI96x64). ! 1230: ;; operand 0 is the function name ! 1231: ;; operand 1 is the destination pointer ! 1232: ;; operand 2 is the source pointer ! 1233: ;; operand 3 is the offset for the source and destination pointers ! 1234: ;; operand 4 is the first value to be loaded ! 1235: ;; operand 5 is the register to hold the value (r4 or r5) ! 1236: ;; Upon completion, r2 and r3 are unchanged ! 1237: ! 1238: (define_expand "call_block_move" ! 1239: [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r") ! 1240: (match_operand:SI 3 "immediate_operand" "i"))) ! 1241: (set (match_operand 5 "register_operand" "r") ! 1242: (match_operand 4 "memory_operand" "m")) ! 1243: (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r") ! 1244: (match_dup 3))) ! 1245: (use (reg:SI 2)) ! 1246: (use (reg:SI 3)) ! 1247: (use (reg:SI 4)) ! 1248: (use (reg:SI 5)) ! 1249: (parallel [(call (mem:SI (match_operand 0 "" "")) ! 1250: (const_int 0)) ! 1251: (use (reg:SI 1))]) ! 1252: (clobber (reg:SI 4)) ! 1253: (clobber (reg:SI 5))] ! 1254: "" ! 1255: "") ! 1256: ! 1257: ;; Call a looping block move library function (e.g. __movstrSI64n68). ! 1258: ;; operands 0-5 as in the non-looping interface ! 1259: ;; operand 6 is the loop count ! 1260: ! 1261: (define_expand "call_block_move_loop" ! 1262: [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r") ! 1263: (match_operand:SI 3 "immediate_operand" "i"))) ! 1264: (set (match_operand:SI 5 "register_operand" "r") ! 1265: (match_operand:SI 4 "memory_operand" "m")) ! 1266: (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r") ! 1267: (match_dup 3))) ! 1268: (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "i")) ! 1269: (use (reg:SI 2)) ! 1270: (use (reg:SI 3)) ! 1271: (use (reg:SI 4)) ! 1272: (use (reg:SI 5)) ! 1273: (use (reg:SI 6)) ! 1274: (parallel [(call (mem:SI (match_operand 0 "" "")) ! 1275: (const_int 0)) ! 1276: (use (reg:SI 1))]) ! 1277: (clobber (reg:SI 4)) ! 1278: (clobber (reg:SI 5)) ! 1279: (clobber (reg:SI 6))] ! 1280: "" ! 1281: "") ! 1282: ! 1283: ;;- zero extension instructions ! 1284: ! 1285: (define_expand "zero_extendhisi2" ! 1286: [(set (match_operand:SI 0 "register_operand" "") ! 1287: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] ! 1288: "" ! 1289: " ! 1290: { ! 1291: if (GET_CODE (operands[1]) == MEM ! 1292: && symbolic_address_p (XEXP (operands[1], 0))) ! 1293: operands[1] ! 1294: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1295: }") ! 1296: ! 1297: (define_insn "" ! 1298: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 1299: (zero_extend:SI (match_operand:HI 1 "move_operand" "!r,n,m")))] ! 1300: "GET_CODE (operands[1]) != CONST_INT" ! 1301: "@ ! 1302: mask %0,%1,0xffff ! 1303: or %0,%#r0,%h1 ! 1304: ld.hu %0,%1" ! 1305: [(set_attr "type" "arith,arith,load")]) ! 1306: ! 1307: (define_expand "zero_extendqihi2" ! 1308: [(set (match_operand:HI 0 "register_operand" "") ! 1309: (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] ! 1310: "" ! 1311: " ! 1312: { ! 1313: if (GET_CODE (operands[1]) == MEM ! 1314: && symbolic_address_p (XEXP (operands[1], 0))) ! 1315: operands[1] ! 1316: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1317: }") ! 1318: ! 1319: (define_insn "" ! 1320: [(set (match_operand:HI 0 "register_operand" "=r,r,r") ! 1321: (zero_extend:HI (match_operand:QI 1 "move_operand" "r,n,m")))] ! 1322: "GET_CODE (operands[1]) != CONST_INT" ! 1323: "@ ! 1324: mask %0,%1,0xff ! 1325: or %0,%#r0,%q1 ! 1326: ld.bu %0,%1" ! 1327: [(set_attr "type" "arith,arith,load")]) ! 1328: ! 1329: (define_expand "zero_extendqisi2" ! 1330: [(set (match_operand:SI 0 "register_operand" "") ! 1331: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] ! 1332: "" ! 1333: " ! 1334: { ! 1335: if (GET_CODE (operands[1]) == MEM ! 1336: && symbolic_address_p (XEXP (operands[1], 0))) ! 1337: { ! 1338: operands[1] ! 1339: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1340: emit_insn (gen_rtx (SET, VOIDmode, operands[0], ! 1341: gen_rtx (ZERO_EXTEND, SImode, operands[1]))); ! 1342: DONE; ! 1343: } ! 1344: }") ! 1345: ! 1346: (define_insn "" ! 1347: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 1348: (zero_extend:SI (match_operand:QI 1 "move_operand" "r,n,m")))] ! 1349: "GET_CODE (operands[1]) != CONST_INT" ! 1350: "@ ! 1351: mask %0,%1,0xff ! 1352: or %0,%#r0,%q1 ! 1353: ld.bu %0,%1" ! 1354: [(set_attr "type" "arith,arith,load")]) ! 1355: ! 1356: ;;- sign extension instructions ! 1357: ! 1358: (define_expand "extendsidi2" ! 1359: [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1) ! 1360: (match_operand:SI 1 "general_operand" "g")) ! 1361: (set (subreg:SI (match_dup 0) 0) ! 1362: (ashiftrt:SI (subreg:SI (match_dup 0) 1) ! 1363: (const_int 31)))] ! 1364: "" ! 1365: "") ! 1366: ! 1367: (define_expand "extendhisi2" ! 1368: [(set (match_operand:SI 0 "register_operand" "") ! 1369: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] ! 1370: "" ! 1371: " ! 1372: { ! 1373: if (GET_CODE (operands[1]) == MEM ! 1374: && symbolic_address_p (XEXP (operands[1], 0))) ! 1375: operands[1] ! 1376: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1377: }") ! 1378: ! 1379: (define_insn "" ! 1380: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") ! 1381: (sign_extend:SI (match_operand:HI 1 "move_operand" "!r,P,N,m")))] ! 1382: "GET_CODE (operands[1]) != CONST_INT" ! 1383: "@ ! 1384: ext %0,%1,16<0> ! 1385: or %0,%#r0,%h1 ! 1386: subu %0,%#r0,%H1 ! 1387: ld.h %0,%1" ! 1388: [(set_attr "type" "arith,arith,arith,load")]) ! 1389: ! 1390: (define_expand "extendqihi2" ! 1391: [(set (match_operand:HI 0 "register_operand" "") ! 1392: (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] ! 1393: "" ! 1394: " ! 1395: { ! 1396: if (GET_CODE (operands[1]) == MEM ! 1397: && symbolic_address_p (XEXP (operands[1], 0))) ! 1398: operands[1] ! 1399: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1400: }") ! 1401: ! 1402: (define_insn "" ! 1403: [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") ! 1404: (sign_extend:HI (match_operand:QI 1 "move_operand" "!r,P,N,m")))] ! 1405: "GET_CODE (operands[1]) != CONST_INT" ! 1406: "@ ! 1407: ext %0,%1,8<0> ! 1408: or %0,%#r0,%q1 ! 1409: subu %0,%#r0,%Q1 ! 1410: ld.b %0,%1" ! 1411: [(set_attr "type" "arith,arith,arith,load")]) ! 1412: ! 1413: (define_expand "extendqisi2" ! 1414: [(set (match_operand:SI 0 "register_operand" "") ! 1415: (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] ! 1416: "" ! 1417: " ! 1418: { ! 1419: if (GET_CODE (operands[1]) == MEM ! 1420: && symbolic_address_p (XEXP (operands[1], 0))) ! 1421: operands[1] ! 1422: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode)); ! 1423: }") ! 1424: ! 1425: (define_insn "" ! 1426: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") ! 1427: (sign_extend:SI (match_operand:QI 1 "move_operand" "!r,P,N,m")))] ! 1428: "GET_CODE (operands[1]) != CONST_INT" ! 1429: "@ ! 1430: ext %0,%1,8<0> ! 1431: or %0,%#r0,%q1 ! 1432: subu %0,%#r0,%Q1 ! 1433: ld.b %0,%1" ! 1434: [(set_attr "type" "arith,arith,arith,load")]) ! 1435: ! 1436: ;; Conversions between float and double. ! 1437: ! 1438: ;; The fadd instruction does not conform to IEEE 754 when used to ! 1439: ;; convert between float and double. In particular, the sign of -0 is ! 1440: ;; not preserved. Interestingly, fsub does conform. ! 1441: ! 1442: (define_insn "extendsfdf2" ! 1443: [(set (match_operand:DF 0 "register_operand" "=r") ! 1444: (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] ! 1445: "" ! 1446: "fsub.dss %0,%1,%#r0" ! 1447: [(set_attr "type" "spadd")]) ! 1448: ! 1449: (define_insn "truncdfsf2" ! 1450: [(set (match_operand:SF 0 "register_operand" "=r") ! 1451: (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] ! 1452: "" ! 1453: "fsub.sds %0,%1,%#r0" ! 1454: [(set_attr "type" "dpadd")]) ! 1455: ! 1456: ;; Conversions between floating point and integer ! 1457: ! 1458: (define_insn "floatsidf2" ! 1459: [(set (match_operand:DF 0 "register_operand" "=r") ! 1460: (float:DF (match_operand:SI 1 "register_operand" "r")))] ! 1461: "" ! 1462: "flt.ds %0,%1" ! 1463: [(set_attr "type" "spadd")]) ! 1464: ! 1465: (define_insn "floatsisf2" ! 1466: [(set (match_operand:SF 0 "register_operand" "=r") ! 1467: (float:SF (match_operand:SI 1 "register_operand" "r")))] ! 1468: "" ! 1469: "flt.ss %0,%1" ! 1470: [(set_attr "type" "spadd")]) ! 1471: ! 1472: (define_insn "fix_truncdfsi2" ! 1473: [(set (match_operand:SI 0 "register_operand" "=r") ! 1474: (fix:SI (match_operand:DF 1 "register_operand" "r")))] ! 1475: "" ! 1476: "trnc.sd %0,%1" ! 1477: [(set_attr "type" "dpadd")]) ! 1478: ! 1479: (define_insn "fix_truncsfsi2" ! 1480: [(set (match_operand:SI 0 "register_operand" "=r") ! 1481: (fix:SI (match_operand:SF 1 "register_operand" "r")))] ! 1482: "" ! 1483: "trnc.ss %0,%1" ! 1484: [(set_attr "type" "spadd")]) ! 1485: ! 1486: ! 1487: ;;- arithmetic instructions ! 1488: ;;- add instructions ! 1489: ! 1490: (define_insn "addsi3" ! 1491: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 1492: (plus:SI (match_operand:SI 1 "add_operand" "%r,r") ! 1493: (match_operand:SI 2 "add_operand" "rI,J")))] ! 1494: "" ! 1495: "@ ! 1496: addu %0,%1,%2 ! 1497: subu %0,%1,%n2") ! 1498: ! 1499: ;; In unusual contexts, an add of a large value is generated (case statements ! 1500: ;; for example). In these contexts, it is sufficient to accept only those ! 1501: ;; cases where the two registers are different. ! 1502: ! 1503: (define_insn "" ! 1504: [(set (match_operand:SI 0 "register_operand" "=r,&r") ! 1505: (plus:SI (match_operand:SI 1 "arith32_operand" "%r,r") ! 1506: (match_operand:SI 2 "arith32_operand" "r,!n")))] ! 1507: "" ! 1508: "* ! 1509: { ! 1510: rtx xoperands[10]; ! 1511: ! 1512: if (which_alternative == 0) ! 1513: return \"addu %0,%1,%2\"; ! 1514: ! 1515: xoperands[0] = operands[0]; ! 1516: xoperands[1] = operands[2]; ! 1517: output_asm_insn (output_load_const_int (SImode, xoperands), ! 1518: xoperands); ! 1519: ! 1520: return \"addu %0,%1,%0\"; ! 1521: }" ! 1522: [(set_attr "type" "arith,marith") ! 1523: (set_attr "length" "1,3")]) ; may be 2 or 3. ! 1524: ! 1525: ;; patterns for mixed mode floating point. ! 1526: ;; Do not define patterns that utilize mixed mode arithmetic that result ! 1527: ;; in narrowing the precision, because it loses accuracy, since the standard ! 1528: ;; requires double rounding, whereas the 88000 instruction only rounds once. ! 1529: ! 1530: (define_expand "adddf3" ! 1531: [(set (match_operand:DF 0 "register_operand" "=r") ! 1532: (plus:DF (match_operand:DF 1 "general_operand" "%r") ! 1533: (match_operand:DF 2 "general_operand" "r")))] ! 1534: "" ! 1535: " ! 1536: { ! 1537: operands[1] = legitimize_operand (operands[1], DFmode); ! 1538: operands[2] = legitimize_operand (operands[2], DFmode); ! 1539: }") ! 1540: ! 1541: (define_insn "" ! 1542: [(set (match_operand:DF 0 "register_operand" "=r") ! 1543: (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1544: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1545: "" ! 1546: "fadd.dss %0,%1,%2" ! 1547: [(set_attr "type" "spadd")]) ! 1548: ! 1549: (define_insn "" ! 1550: [(set (match_operand:DF 0 "register_operand" "=r") ! 1551: (plus:DF (match_operand:DF 1 "register_operand" "r") ! 1552: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1553: "" ! 1554: "fadd.dds %0,%1,%2" ! 1555: [(set_attr "type" "dpadd")]) ! 1556: ! 1557: (define_insn "" ! 1558: [(set (match_operand:DF 0 "register_operand" "=r") ! 1559: (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1560: (match_operand:DF 2 "register_operand" "r")))] ! 1561: "" ! 1562: "fadd.dsd %0,%1,%2" ! 1563: [(set_attr "type" "dpadd")]) ! 1564: ! 1565: (define_insn "" ! 1566: [(set (match_operand:DF 0 "register_operand" "=r") ! 1567: (plus:DF (match_operand:DF 1 "register_operand" "%r") ! 1568: (match_operand:DF 2 "register_operand" "r")))] ! 1569: "" ! 1570: "fadd.ddd %0,%1,%2" ! 1571: [(set_attr "type" "dpadd")]) ! 1572: ! 1573: (define_insn "addsf3" ! 1574: [(set (match_operand:SF 0 "register_operand" "=r") ! 1575: (plus:SF (match_operand:SF 1 "register_operand" "%r") ! 1576: (match_operand:SF 2 "register_operand" "r")))] ! 1577: "" ! 1578: "fadd.sss %0,%1,%2" ! 1579: [(set_attr "type" "spadd")]) ! 1580: ! 1581: (define_insn "" ! 1582: [(set (match_operand:DI 0 "register_operand" "=r") ! 1583: (plus:DI (match_operand:DI 1 "register_operand" "r") ! 1584: (zero_extend:DI ! 1585: (match_operand:SI 2 "register_operand" "r"))))] ! 1586: "" ! 1587: "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0" ! 1588: [(set_attr "type" "marith")]) ! 1589: ! 1590: (define_insn "" ! 1591: [(set (match_operand:DI 0 "register_operand" "=r") ! 1592: (plus:DI (zero_extend:DI ! 1593: (match_operand:SI 1 "register_operand" "r")) ! 1594: (match_operand:DI 2 "register_operand" "r")))] ! 1595: "" ! 1596: "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2" ! 1597: [(set_attr "type" "marith")]) ! 1598: ! 1599: (define_insn "adddi3" ! 1600: [(set (match_operand:DI 0 "register_operand" "=r") ! 1601: (plus:DI (match_operand:DI 1 "register_operand" "%r") ! 1602: (match_operand:DI 2 "register_operand" "r")))] ! 1603: "" ! 1604: "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2" ! 1605: [(set_attr "type" "marith")]) ! 1606: ! 1607: ;;- subtract instructions ! 1608: ! 1609: (define_insn "subsi3" ! 1610: [(set (match_operand:SI 0 "register_operand" "=r") ! 1611: (minus:SI (match_operand:SI 1 "register_operand" "r") ! 1612: (match_operand:SI 2 "arith32_operand" "rI")))] ! 1613: "" ! 1614: "subu %0,%1,%2") ! 1615: ! 1616: ;; patterns for mixed mode floating point ! 1617: ;; Do not define patterns that utilize mixed mode arithmetic that result ! 1618: ;; in narrowing the precision, because it loses accuracy, since the standard ! 1619: ;; requires double rounding, whereas the 88000 instruction only rounds once. ! 1620: ! 1621: (define_expand "subdf3" ! 1622: [(set (match_operand:DF 0 "register_operand" "=r") ! 1623: (minus:DF (match_operand:DF 1 "general_operand" "r") ! 1624: (match_operand:DF 2 "general_operand" "r")))] ! 1625: "" ! 1626: " ! 1627: { ! 1628: operands[1] = legitimize_operand (operands[1], DFmode); ! 1629: operands[2] = legitimize_operand (operands[2], DFmode); ! 1630: }") ! 1631: ! 1632: (define_insn "" ! 1633: [(set (match_operand:DF 0 "register_operand" "=r") ! 1634: (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1635: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1636: "" ! 1637: "fsub.dss %0,%1,%2" ! 1638: [(set_attr "type" "spadd")]) ! 1639: ! 1640: (define_insn "" ! 1641: [(set (match_operand:DF 0 "register_operand" "=r") ! 1642: (minus:DF (match_operand:DF 1 "register_operand" "r") ! 1643: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1644: "" ! 1645: "fsub.dds %0,%1,%2" ! 1646: [(set_attr "type" "dpadd")]) ! 1647: ! 1648: (define_insn "" ! 1649: [(set (match_operand:DF 0 "register_operand" "=r") ! 1650: (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1651: (match_operand:DF 2 "register_operand" "r")))] ! 1652: "" ! 1653: "fsub.dsd %0,%1,%2" ! 1654: [(set_attr "type" "dpadd")]) ! 1655: ! 1656: (define_insn "" ! 1657: [(set (match_operand:DF 0 "register_operand" "=r") ! 1658: (minus:DF (match_operand:DF 1 "register_operand" "r") ! 1659: (match_operand:DF 2 "register_operand" "r")))] ! 1660: "" ! 1661: "fsub.ddd %0,%1,%2" ! 1662: [(set_attr "type" "dpadd")]) ! 1663: ! 1664: (define_insn "subsf3" ! 1665: [(set (match_operand:SF 0 "register_operand" "=r") ! 1666: (minus:SF (match_operand:SF 1 "register_operand" "r") ! 1667: (match_operand:SF 2 "register_operand" "r")))] ! 1668: "" ! 1669: "fsub.sss %0,%1,%2" ! 1670: [(set_attr "type" "spadd")]) ! 1671: ! 1672: (define_insn "" ! 1673: [(set (match_operand:DI 0 "register_operand" "=r") ! 1674: (minus:DI (match_operand:DI 1 "register_operand" "r") ! 1675: (zero_extend:DI ! 1676: (match_operand:SI 2 "register_operand" "r"))))] ! 1677: "" ! 1678: "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0" ! 1679: [(set_attr "type" "marith")]) ! 1680: ! 1681: (define_insn "" ! 1682: [(set (match_operand:DI 0 "register_operand" "=r") ! 1683: (minus:DI (zero_extend:DI ! 1684: (match_operand:SI 1 "register_operand" "r")) ! 1685: (match_operand:DI 2 "register_operand" "r")))] ! 1686: "" ! 1687: "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2" ! 1688: [(set_attr "type" "marith")]) ! 1689: ! 1690: (define_insn "subdi3" ! 1691: [(set (match_operand:DI 0 "register_operand" "=r") ! 1692: (minus:DI (match_operand:DI 1 "register_operand" "r") ! 1693: (match_operand:DI 2 "register_operand" "r")))] ! 1694: "" ! 1695: "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2" ! 1696: [(set_attr "type" "marith")]) ! 1697: ! 1698: ;;- multiply instructions ! 1699: ;; ! 1700: ;; There is an unfounded silicon eratta for E.1 requiring that an ! 1701: ;; immediate constant value in div/divu/mul instructions be less than ! 1702: ;; 0x800. This is no longer provided for. ! 1703: ! 1704: (define_insn "mulsi3" ! 1705: [(set (match_operand:SI 0 "register_operand" "=r") ! 1706: (mult:SI (match_operand:SI 1 "arith32_operand" "%r") ! 1707: (match_operand:SI 2 "arith32_operand" "rI")))] ! 1708: "" ! 1709: "mul %0,%1,%2" ! 1710: [(set_attr "type" "imul")]) ! 1711: ! 1712: ;; patterns for mixed mode floating point ! 1713: ;; Do not define patterns that utilize mixed mode arithmetic that result ! 1714: ;; in narrowing the precision, because it loses accuracy, since the standard ! 1715: ;; requires double rounding, whereas the 88000 instruction only rounds once. ! 1716: ! 1717: (define_expand "muldf3" ! 1718: [(set (match_operand:DF 0 "register_operand" "=r") ! 1719: (mult:DF (match_operand:DF 1 "general_operand" "%r") ! 1720: (match_operand:DF 2 "general_operand" "r")))] ! 1721: "" ! 1722: " ! 1723: { ! 1724: operands[1] = legitimize_operand (operands[1], DFmode); ! 1725: operands[2] = legitimize_operand (operands[2], DFmode); ! 1726: }") ! 1727: ! 1728: (define_insn "" ! 1729: [(set (match_operand:DF 0 "register_operand" "=r") ! 1730: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1731: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1732: "" ! 1733: "fmul.dss %0,%1,%2" ! 1734: [(set_attr "type" "spmul")]) ! 1735: ! 1736: (define_insn "" ! 1737: [(set (match_operand:DF 0 "register_operand" "=r") ! 1738: (mult:DF (match_operand:DF 1 "register_operand" "r") ! 1739: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 1740: "" ! 1741: "fmul.dds %0,%1,%2" ! 1742: [(set_attr "type" "spmul")]) ! 1743: ! 1744: (define_insn "" ! 1745: [(set (match_operand:DF 0 "register_operand" "=r") ! 1746: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 1747: (match_operand:DF 2 "register_operand" "r")))] ! 1748: "" ! 1749: "fmul.dsd %0,%1,%2" ! 1750: [(set_attr "type" "spmul")]) ! 1751: ! 1752: (define_insn "" ! 1753: [(set (match_operand:DF 0 "register_operand" "=r") ! 1754: (mult:DF (match_operand:DF 1 "register_operand" "%r") ! 1755: (match_operand:DF 2 "register_operand" "r")))] ! 1756: "" ! 1757: "fmul.ddd %0,%1,%2" ! 1758: [(set_attr "type" "dpmul")]) ! 1759: ! 1760: (define_insn "mulsf3" ! 1761: [(set (match_operand:SF 0 "register_operand" "=r") ! 1762: (mult:SF (match_operand:SF 1 "register_operand" "%r") ! 1763: (match_operand:SF 2 "register_operand" "r")))] ! 1764: "" ! 1765: "fmul.sss %0,%1,%2" ! 1766: [(set_attr "type" "spmul")]) ! 1767: ! 1768: ;;- divide instructions ! 1769: ;; ! 1770: ;; The 88k div and divu instructions don't reliably trap on ! 1771: ;; divide-by-zero. A trap to vector 503 asserts divide-by-zero. The ! 1772: ;; general scheme for doing divide is to do a 4-way split based on the ! 1773: ;; sign of the two operand and do the appropriate negates. ! 1774: ;; ! 1775: ;; The conditional trap instruction is not used as this serializes the ! 1776: ;; processor. Instead a conditional branch and an unconditional trap ! 1777: ;; are used, but after the divu. Since the divu takes up to 38 cycles, ! 1778: ;; the conditional branch is essentially free. ! 1779: ;; ! 1780: ;; Two target options control how divide is done. One options selects ! 1781: ;; whether to do the branch and negate scheme instead of using the div ! 1782: ;; instruction; the other option selects whether to explicitly check ! 1783: ;; for divide-by-zero or take your chances. If the div instruction is ! 1784: ;; used, the O/S must complete the operation if the operands are ! 1785: ;; negative. The O/S will signal an overflow condition if the most ! 1786: ;; negative number (-214783648) is divided by negative 1. ! 1787: ;; ! 1788: ;; There is an unfounded silicon eratta for E.1 requiring that an ! 1789: ;; immediate constant value in div/divu/mul instructions be less than ! 1790: ;; 0x800. This is no longer provided for. ! 1791: ! 1792: ;; Division by 0 trap ! 1793: (define_insn "trap_divide_by_zero" ! 1794: [(trap_if (const_int 1) 503)] ! 1795: "" ! 1796: "tb0 0,%#r0,503" ! 1797: [(set_attr "type" "weird")]) ! 1798: ! 1799: ;; Conditional division by 0 trap. ! 1800: (define_expand "tcnd_divide_by_zero" ! 1801: [(set (pc) ! 1802: (if_then_else (eq (match_operand:SI 0 "register_operand" "") ! 1803: (const_int 0)) ! 1804: (pc) ! 1805: (match_operand 1 "" ""))) ! 1806: (trap_if (const_int 1) 503)] ! 1807: "" ! 1808: " ! 1809: { ! 1810: emit_insn (gen_cmpsi (operands[0], const0_rtx)); ! 1811: emit_jump_insn (gen_bne (operands[1])); ! 1812: emit_insn (gen_trap_divide_by_zero ()); ! 1813: emit_barrier (); ! 1814: DONE; ! 1815: }") ! 1816: ! 1817: (define_expand "divsi3" ! 1818: [(set (match_operand:SI 0 "register_operand" "") ! 1819: (div:SI (match_operand:SI 1 "arith32_operand" "") ! 1820: (match_operand:SI 2 "arith32_operand" "")))] ! 1821: "" ! 1822: " ! 1823: { ! 1824: rtx op0 = operands[0]; ! 1825: rtx op1 = operands[1]; ! 1826: rtx op2 = operands[2]; ! 1827: rtx join_label; ! 1828: ! 1829: /* @@ This needs to be reworked. Torbjorn Granlund has suggested making ! 1830: it a runtime (perhaps quite special). */ ! 1831: ! 1832: if (GET_CODE (op1) == CONST_INT) ! 1833: op1 = force_reg (SImode, op1); ! 1834: ! 1835: else if (GET_CODE (op2) == CONST_INT ! 1836: && ! SMALL_INT (operands[2])) ! 1837: op2 = force_reg (SImode, op2); ! 1838: ! 1839: if (op2 == const0_rtx) ! 1840: { ! 1841: emit_insn (gen_trap_divide_by_zero ()); ! 1842: emit_barrier (); ! 1843: emit_insn (gen_dummy (op0)); ! 1844: DONE; ! 1845: } ! 1846: ! 1847: if (TARGET_USE_DIV) ! 1848: { ! 1849: emit_move_insn (op0, gen_rtx (DIV, SImode, op1, op2)); ! 1850: if (TARGET_CHECK_ZERO_DIV && GET_CODE (op2) != CONST_INT) ! 1851: { ! 1852: rtx label = gen_label_rtx (); ! 1853: emit_insn (gen_tcnd_divide_by_zero (op2, label)); ! 1854: emit_label (label); ! 1855: emit_insn (gen_dummy (op0)); ! 1856: } ! 1857: DONE; ! 1858: } ! 1859: ! 1860: join_label = gen_label_rtx (); ! 1861: if (GET_CODE (op1) == CONST_INT) ! 1862: { ! 1863: int neg = FALSE; ! 1864: rtx neg_op2 = gen_reg_rtx (SImode); ! 1865: rtx label1 = gen_label_rtx (); ! 1866: ! 1867: if (INTVAL (op1) < 0) ! 1868: { ! 1869: neg = TRUE; ! 1870: op1 = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op1)); ! 1871: } ! 1872: op1 = force_reg (SImode, op1); ! 1873: ! 1874: emit_insn (gen_negsi2 (neg_op2, op2)); ! 1875: emit_insn (gen_cmpsi (op2, const0_rtx)); ! 1876: emit_jump_insn (gen_bgt (label1)); ! 1877: /* constant / 0-or-negative */ ! 1878: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2)); ! 1879: if (!neg) ! 1880: emit_insn (gen_negsi2 (op0, op0)); ! 1881: ! 1882: if (TARGET_CHECK_ZERO_DIV) ! 1883: emit_insn (gen_tcnd_divide_by_zero (op2, join_label)); ! 1884: else ! 1885: { ! 1886: emit_jump_insn (gen_jump (join_label)); ! 1887: emit_barrier (); ! 1888: } ! 1889: ! 1890: emit_label (label1); /* constant / positive */ ! 1891: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); ! 1892: if (neg) ! 1893: emit_insn (gen_negsi2 (op0, op0)); ! 1894: } ! 1895: ! 1896: else if (GET_CODE (op2) == CONST_INT) ! 1897: { ! 1898: int neg = FALSE; ! 1899: rtx neg_op1 = gen_reg_rtx (SImode); ! 1900: rtx label1 = gen_label_rtx (); ! 1901: ! 1902: if (INTVAL (op2) < 0) ! 1903: { ! 1904: neg = TRUE; ! 1905: op2 = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op2)); ! 1906: } ! 1907: else if (! SMALL_INT (operands[2])) ! 1908: op2 = force_reg (SImode, op2); ! 1909: ! 1910: emit_insn (gen_negsi2 (neg_op1, op1)); ! 1911: emit_insn (gen_cmpsi (op1, const0_rtx)); ! 1912: emit_jump_insn (gen_bge (label1)); ! 1913: /* 0-or-negative / constant */ ! 1914: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2)); ! 1915: if (!neg) ! 1916: emit_insn (gen_negsi2 (op0, op0)); ! 1917: ! 1918: emit_jump_insn (gen_jump (join_label)); ! 1919: emit_barrier (); ! 1920: ! 1921: emit_label (label1); /* positive / constant */ ! 1922: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); ! 1923: if (neg) ! 1924: emit_insn (gen_negsi2 (op0, op0)); ! 1925: } ! 1926: ! 1927: else ! 1928: { ! 1929: rtx neg_op1 = gen_reg_rtx (SImode); ! 1930: rtx neg_op2 = gen_reg_rtx (SImode); ! 1931: rtx label1 = gen_label_rtx (); ! 1932: rtx label2 = gen_label_rtx (); ! 1933: rtx label3 = gen_label_rtx (); ! 1934: rtx label4; ! 1935: ! 1936: emit_insn (gen_negsi2 (neg_op2, op2)); ! 1937: emit_insn (gen_cmpsi (op2, const0_rtx)); ! 1938: emit_jump_insn (gen_bgt (label1)); ! 1939: ! 1940: emit_insn (gen_negsi2 (neg_op1, op1)); ! 1941: emit_insn (gen_cmpsi (op1, const0_rtx)); ! 1942: emit_jump_insn (gen_bge (label2)); ! 1943: /* negative / negative-or-0 */ ! 1944: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, neg_op2)); ! 1945: ! 1946: if (TARGET_CHECK_ZERO_DIV) ! 1947: { ! 1948: label4 = gen_label_rtx (); ! 1949: emit_insn (gen_cmpsi (op2, const0_rtx)); ! 1950: emit_jump_insn (gen_bne (join_label)); ! 1951: emit_label (label4); ! 1952: emit_insn (gen_trap_divide_by_zero ()); ! 1953: emit_barrier (); ! 1954: } ! 1955: else ! 1956: { ! 1957: emit_jump_insn (gen_jump (join_label)); ! 1958: emit_barrier (); ! 1959: } ! 1960: ! 1961: emit_label (label2); /* pos.-or-0 / neg.-or-0 */ ! 1962: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2)); ! 1963: ! 1964: if (TARGET_CHECK_ZERO_DIV) ! 1965: { ! 1966: emit_insn (gen_cmpsi (op2, const0_rtx)); ! 1967: emit_jump_insn (gen_beq (label4)); ! 1968: } ! 1969: ! 1970: emit_insn (gen_negsi2 (op0, op0)); ! 1971: emit_jump_insn (gen_jump (join_label)); ! 1972: emit_barrier (); ! 1973: ! 1974: emit_label (label1); ! 1975: emit_insn (gen_negsi2 (neg_op1, op1)); ! 1976: emit_insn (gen_cmpsi (op1, const0_rtx)); ! 1977: emit_jump_insn (gen_bge (label3)); ! 1978: /* negative / positive */ ! 1979: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2)); ! 1980: emit_insn (gen_negsi2 (op0, op0)); ! 1981: emit_jump_insn (gen_jump (join_label)); ! 1982: emit_barrier (); ! 1983: ! 1984: emit_label (label3); /* positive-or-0 / positive */ ! 1985: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2)); ! 1986: } ! 1987: ! 1988: emit_label (join_label); ! 1989: ! 1990: emit_insn (gen_dummy (op0)); ! 1991: DONE; ! 1992: }") ! 1993: ! 1994: (define_insn "" ! 1995: [(set (match_operand:SI 0 "register_operand" "=r") ! 1996: (div:SI (match_operand:SI 1 "register_operand" "r") ! 1997: (match_operand:SI 2 "arith_operand" "rI")))] ! 1998: "" ! 1999: "div %0,%1,%2" ! 2000: [(set_attr "type" "idiv")]) ! 2001: ! 2002: (define_expand "udivsi3" ! 2003: [(set (match_operand:SI 0 "register_operand" "") ! 2004: (udiv:SI (match_operand:SI 1 "register_operand" "") ! 2005: (match_operand:SI 2 "arith32_operand" "")))] ! 2006: "" ! 2007: " ! 2008: { ! 2009: rtx op2 = operands[2]; ! 2010: ! 2011: if (op2 == const0_rtx) ! 2012: { ! 2013: emit_insn (gen_trap_divide_by_zero ()); ! 2014: emit_barrier (); ! 2015: emit_insn (gen_dummy (operands[0])); ! 2016: DONE; ! 2017: } ! 2018: else if (GET_CODE (op2) != CONST_INT && TARGET_CHECK_ZERO_DIV) ! 2019: { ! 2020: rtx label = gen_label_rtx (); ! 2021: emit_insn (gen_rtx (SET, VOIDmode, operands[0], ! 2022: gen_rtx (UDIV, SImode, operands[1], op2))); ! 2023: emit_insn (gen_tcnd_divide_by_zero (op2, label)); ! 2024: emit_label (label); ! 2025: emit_insn (gen_dummy (operands[0])); ! 2026: DONE; ! 2027: } ! 2028: }") ! 2029: ! 2030: (define_insn "" ! 2031: [(set (match_operand:SI 0 "register_operand" "=r") ! 2032: (udiv:SI (match_operand:SI 1 "register_operand" "r") ! 2033: (match_operand:SI 2 "arith32_operand" "rI")))] ! 2034: "operands[2] != const0_rtx" ! 2035: "divu %0,%1,%2" ! 2036: [(set_attr "type" "idiv")]) ! 2037: ! 2038: (define_insn "" ! 2039: [(set (match_operand:SI 0 "register_operand" "=r") ! 2040: (udiv:SI (match_operand:SI 1 "register_operand" "r") ! 2041: (const_int 0)))] ! 2042: "" ! 2043: "tb0 0,%#r0,503" ! 2044: [(set_attr "type" "weird")]) ! 2045: ! 2046: ;; patterns for mixed mode floating point. ! 2047: ;; Do not define patterns that utilize mixed mode arithmetic that result ! 2048: ;; in narrowing the precision, because it loses accuracy, since the standard ! 2049: ;; requires double rounding, whereas the 88000 instruction only rounds once. ! 2050: ! 2051: (define_expand "divdf3" ! 2052: [(set (match_operand:DF 0 "register_operand" "=r") ! 2053: (div:DF (match_operand:DF 1 "general_operand" "r") ! 2054: (match_operand:DF 2 "general_operand" "r")))] ! 2055: "" ! 2056: " ! 2057: { ! 2058: operands[1] = legitimize_operand (operands[1], DFmode); ! 2059: if (real_power_of_2_operand (operands[2])) ! 2060: { ! 2061: union real_extract u; ! 2062: bcopy (&CONST_DOUBLE_LOW (operands[2]), &u, sizeof u); ! 2063: emit_insn (gen_muldf3 (operands[0], operands[1], ! 2064: CONST_DOUBLE_FROM_REAL_VALUE (1.0/u.d, DFmode))); ! 2065: DONE; ! 2066: } ! 2067: else if (! register_operand (operands[2], DFmode)) ! 2068: operands[2] = force_reg (DFmode, operands[2]); ! 2069: }") ! 2070: ! 2071: (define_insn "" ! 2072: [(set (match_operand:DF 0 "register_operand" "=r") ! 2073: (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 2074: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 2075: "" ! 2076: "fdiv.dss %0,%1,%2" ! 2077: [(set_attr "type" "dpdiv")]) ! 2078: ! 2079: (define_insn "" ! 2080: [(set (match_operand:DF 0 "register_operand" "=r") ! 2081: (div:DF (match_operand:DF 1 "register_operand" "r") ! 2082: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))] ! 2083: "" ! 2084: "fdiv.dds %0,%1,%2" ! 2085: [(set_attr "type" "dpdiv")]) ! 2086: ! 2087: (define_insn "" ! 2088: [(set (match_operand:DF 0 "register_operand" "=r") ! 2089: (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r")) ! 2090: (match_operand:DF 2 "register_operand" "r")))] ! 2091: "" ! 2092: "fdiv.dsd %0,%1,%2" ! 2093: [(set_attr "type" "dpdiv")]) ! 2094: ! 2095: (define_insn "divsf3" ! 2096: [(set (match_operand:SF 0 "register_operand" "=r") ! 2097: (div:SF (match_operand:SF 1 "register_operand" "r") ! 2098: (match_operand:SF 2 "register_operand" "r")))] ! 2099: "" ! 2100: "fdiv.sss %0,%1,%2" ! 2101: [(set_attr "type" "spdiv")]) ! 2102: ! 2103: (define_insn "" ! 2104: [(set (match_operand:DF 0 "register_operand" "=r") ! 2105: (div:DF (match_operand:DF 1 "register_operand" "r") ! 2106: (match_operand:DF 2 "register_operand" "r")))] ! 2107: "" ! 2108: "fdiv.ddd %0,%1,%2" ! 2109: [(set_attr "type" "dpdiv")]) ! 2110: ! 2111: ;; - remainder instructions, don't define, since the hardware doesn't have any ! 2112: ;; direct support, and GNU can synthesis them out of div/mul just fine. ! 2113: ! 2114: ;;- load effective address, must come after add, so that we favor using ! 2115: ;; addu reg,reg,reg instead of: lda reg,reg,reg (addu doesn't require ! 2116: ;; the data unit), and also future 88k chips might not support unscaled ! 2117: ;; lda instructions. ! 2118: ! 2119: (define_insn "" ! 2120: [(set (match_operand:SI 0 "register_operand" "=r") ! 2121: (match_operand:SI 1 "address_operand" "p"))] ! 2122: "m88k_gp_threshold > 0 && symbolic_address_p (operands[1])" ! 2123: "addu %0,%a1") ! 2124: ! 2125: (define_insn "" ! 2126: [(set (match_operand:SI 0 "register_operand" "=r") ! 2127: (match_operand:HI 1 "address_operand" "p"))] ! 2128: "" ! 2129: "lda.h %0,%a1" ! 2130: [(set_attr "type" "loada")]) ! 2131: ! 2132: (define_insn "" ! 2133: [(set (match_operand:SI 0 "register_operand" "=r") ! 2134: (match_operand:SI 1 "address_operand" "p"))] ! 2135: "" ! 2136: "lda %0,%a1" ! 2137: [(set_attr "type" "loada")]) ! 2138: ! 2139: (define_insn "" ! 2140: [(set (match_operand:SI 0 "register_operand" "=r") ! 2141: (match_operand:DI 1 "address_operand" "p"))] ! 2142: "" ! 2143: "lda.d %0,%a1" ! 2144: [(set_attr "type" "loada")]) ! 2145: ! 2146: (define_insn "" ! 2147: [(set (match_operand:SI 0 "register_operand" "=r") ! 2148: (match_operand:SF 1 "address_operand" "p"))] ! 2149: "" ! 2150: "lda %0,%a1" ! 2151: [(set_attr "type" "loada")]) ! 2152: ! 2153: (define_insn "" ! 2154: [(set (match_operand:SI 0 "register_operand" "=r") ! 2155: (match_operand:DF 1 "address_operand" "p"))] ! 2156: "" ! 2157: "lda.d %0,%a1" ! 2158: [(set_attr "type" "loada")]) ! 2159: ! 2160: ;;- and instructions (with complement also) ! 2161: (define_insn "" ! 2162: [(set (match_operand:SI 0 "register_operand" "=r") ! 2163: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) ! 2164: (match_operand:SI 2 "register_operand" "r")))] ! 2165: "" ! 2166: "and.c %0,%2,%1") ! 2167: ! 2168: ;; If the operation is being performed on a 32-bit constant such that ! 2169: ;; it cannot be done in one insn, do it in two. We may lose a bit on ! 2170: ;; CSE in pathological cases, but it seems better doing it this way. ! 2171: ! 2172: (define_expand "andsi3" ! 2173: [(set (match_operand:SI 0 "register_operand" "") ! 2174: (and:SI (match_operand:SI 1 "arith32_operand" "") ! 2175: (match_operand:SI 2 "arith32_operand" "")))] ! 2176: "" ! 2177: " ! 2178: { ! 2179: if (GET_CODE (operands[2]) == CONST_INT) ! 2180: { ! 2181: int value = INTVAL (operands[2]); ! 2182: ! 2183: if (! (SMALL_INTVAL (value) ! 2184: || (value & 0xffff0000) == 0xffff0000 ! 2185: || (value & 0xffff) == 0xffff ! 2186: || (value & 0xffff) == 0 ! 2187: || integer_ok_for_set (~value))) ! 2188: { ! 2189: emit_insn (gen_andsi3 (operands[0], operands[1], ! 2190: gen_rtx (CONST_INT, VOIDmode, ! 2191: value | 0xffff))); ! 2192: operands[1] = operands[0]; ! 2193: operands[2] = gen_rtx (CONST_INT, VOIDmode, value | 0xffff0000); ! 2194: } ! 2195: } ! 2196: }") ! 2197: ! 2198: (define_insn "" ! 2199: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 2200: (and:SI (match_operand:SI 1 "arith32_operand" "%r,r") ! 2201: (match_operand:SI 2 "arith32_operand" "rIJL,rn")))] ! 2202: "" ! 2203: "* return output_and (operands);" ! 2204: [(set_attr "type" "arith,marith")]) ! 2205: ! 2206: (define_insn "" ! 2207: [(set (match_operand:DI 0 "register_operand" "=r") ! 2208: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 2209: (match_operand:DI 2 "register_operand" "r")))] ! 2210: "" ! 2211: "and.c %d0,%d2,%d1\;and.c %0,%2,%1" ! 2212: [(set_attr "type" "marith")]) ! 2213: ! 2214: (define_insn "anddi3" ! 2215: [(set (match_operand:DI 0 "register_operand" "=r") ! 2216: (and:DI (match_operand:DI 1 "arith64_operand" "%r") ! 2217: (match_operand:DI 2 "arith64_operand" "rn")))] ! 2218: "" ! 2219: "* ! 2220: { ! 2221: rtx xoperands[10]; ! 2222: ! 2223: xoperands[0] = operand_subword (operands[0], 1, 0, DImode); ! 2224: xoperands[1] = operand_subword (operands[1], 1, 0, DImode); ! 2225: xoperands[2] = operand_subword (operands[2], 1, 0, DImode); ! 2226: ! 2227: output_asm_insn (output_and (xoperands), xoperands); ! 2228: ! 2229: operands[0] = operand_subword (operands[0], 0, 0, DImode); ! 2230: operands[1] = operand_subword (operands[1], 0, 0, DImode); ! 2231: operands[2] = operand_subword (operands[2], 0, 0, DImode); ! 2232: ! 2233: return output_and (operands); ! 2234: }" ! 2235: [(set_attr "type" "marith") ! 2236: (set_attr "length" "4")]) ; length is 2, 3, or 4. ! 2237: ! 2238: ;;- Bit set (inclusive or) instructions (with complement also) ! 2239: (define_insn "" ! 2240: [(set (match_operand:SI 0 "register_operand" "=r") ! 2241: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r")) ! 2242: (match_operand:SI 2 "register_operand" "r")))] ! 2243: "" ! 2244: "or.c %0,%2,%1") ! 2245: ! 2246: (define_expand "iorsi3" ! 2247: [(set (match_operand:SI 0 "register_operand" "") ! 2248: (ior:SI (match_operand:SI 1 "arith32_operand" "") ! 2249: (match_operand:SI 2 "arith32_operand" "")))] ! 2250: "" ! 2251: " ! 2252: { ! 2253: if (GET_CODE (operands[2]) == CONST_INT) ! 2254: { ! 2255: int value = INTVAL (operands[2]); ! 2256: ! 2257: if (! (SMALL_INTVAL (value) ! 2258: || (value & 0xffff) == 0 ! 2259: || integer_ok_for_set (value))) ! 2260: { ! 2261: emit_insn (gen_iorsi3 (operands[0], operands[1], ! 2262: gen_rtx (CONST_INT, VOIDmode, ! 2263: value & 0xffff0000))); ! 2264: operands[1] = operands[0]; ! 2265: operands[2] = gen_rtx (CONST_INT, VOIDmode, value & 0xffff); ! 2266: } ! 2267: } ! 2268: }") ! 2269: ! 2270: (define_insn "" ! 2271: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") ! 2272: (ior:SI (match_operand:SI 1 "arith32_operand" "%r,r,r,r") ! 2273: (match_operand:SI 2 "arith32_operand" "rI,L,M,n")))] ! 2274: "" ! 2275: "@ ! 2276: or %0,%1,%2 ! 2277: or.u %0,%1,%X2 ! 2278: set %0,%1,%s2 ! 2279: or.u %0,%1,%X2\;or %0,%0,%x2" ! 2280: [(set_attr "type" "arith,arith,arith,marith")]) ! 2281: ! 2282: (define_insn "" ! 2283: [(set (match_operand:DI 0 "register_operand" "=r") ! 2284: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r")) ! 2285: (match_operand:DI 2 "register_operand" "r")))] ! 2286: "" ! 2287: "or.c %d0,%d2,%d1\;or.c %0,%2,%1" ! 2288: [(set_attr "type" "marith")]) ! 2289: ! 2290: (define_insn "iordi3" ! 2291: [(set (match_operand:DI 0 "register_operand" "=r") ! 2292: (ior:DI (match_operand:DI 1 "arith64_operand" "%r") ! 2293: (match_operand:DI 2 "arith64_operand" "rn")))] ! 2294: "" ! 2295: "* ! 2296: { ! 2297: rtx xoperands[10]; ! 2298: ! 2299: xoperands[0] = operand_subword (operands[0], 1, 0, DImode); ! 2300: xoperands[1] = operand_subword (operands[1], 1, 0, DImode); ! 2301: xoperands[2] = operand_subword (operands[2], 1, 0, DImode); ! 2302: ! 2303: output_asm_insn (output_ior (xoperands), xoperands); ! 2304: ! 2305: operands[0] = operand_subword (operands[0], 0, 0, DImode); ! 2306: operands[1] = operand_subword (operands[1], 0, 0, DImode); ! 2307: operands[2] = operand_subword (operands[2], 0, 0, DImode); ! 2308: ! 2309: return output_ior (operands); ! 2310: }" ! 2311: [(set_attr "type" "marith") ! 2312: (set_attr "length" "4")]) ; length is 2, 3, or 4. ! 2313: ! 2314: ;;- xor instructions (with complement also) ! 2315: (define_insn "" ! 2316: [(set (match_operand:SI 0 "register_operand" "=r") ! 2317: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%r") ! 2318: (match_operand:SI 2 "register_operand" "r"))))] ! 2319: "" ! 2320: "xor.c %0,%1,%2") ! 2321: ! 2322: (define_expand "xorsi3" ! 2323: [(set (match_operand:SI 0 "register_operand" "") ! 2324: (xor:SI (match_operand:SI 1 "arith32_operand" "") ! 2325: (match_operand:SI 2 "arith32_operand" "")))] ! 2326: "" ! 2327: " ! 2328: { ! 2329: if (GET_CODE (operands[2]) == CONST_INT) ! 2330: { ! 2331: int value = INTVAL (operands[2]); ! 2332: ! 2333: if (! (SMALL_INTVAL (value) ! 2334: || (value & 0xffff) == 0)) ! 2335: { ! 2336: emit_insn (gen_xorsi3 (operands[0], operands[1], ! 2337: gen_rtx (CONST_INT, VOIDmode, ! 2338: value & 0xffff0000))); ! 2339: operands[1] = operands[0]; ! 2340: operands[2] = gen_rtx (CONST_INT, VOIDmode, value & 0xffff); ! 2341: } ! 2342: } ! 2343: }") ! 2344: ! 2345: (define_insn "" ! 2346: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 2347: (xor:SI (match_operand:SI 1 "arith32_operand" "%r,r,r") ! 2348: (match_operand:SI 2 "arith32_operand" "rI,L,n")))] ! 2349: "" ! 2350: "@ ! 2351: xor %0,%1,%2 ! 2352: xor.u %0,%1,%X2 ! 2353: xor.u %0,%1,%X2\;xor %0,%0,%x2" ! 2354: [(set_attr "type" "arith,arith,marith")]) ! 2355: ! 2356: (define_insn "" ! 2357: [(set (match_operand:DI 0 "register_operand" "=r") ! 2358: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r") ! 2359: (match_operand:DI 2 "register_operand" "r"))))] ! 2360: "" ! 2361: "xor.c %d0,%d1,%d2\;xor.c %0,%1,%2" ! 2362: [(set_attr "type" "marith")]) ! 2363: ! 2364: (define_insn "xordi3" ! 2365: [(set (match_operand:DI 0 "register_operand" "=r") ! 2366: (xor:DI (match_operand:DI 1 "arith64_operand" "%r") ! 2367: (match_operand:DI 2 "arith64_operand" "rn")))] ! 2368: "" ! 2369: "* ! 2370: { ! 2371: rtx xoperands[10]; ! 2372: ! 2373: xoperands[0] = operand_subword (operands[0], 1, 0, DImode); ! 2374: xoperands[1] = operand_subword (operands[1], 1, 0, DImode); ! 2375: xoperands[2] = operand_subword (operands[2], 1, 0, DImode); ! 2376: ! 2377: output_asm_insn (output_xor (xoperands), xoperands); ! 2378: ! 2379: operands[0] = operand_subword (operands[0], 0, 0, DImode); ! 2380: operands[1] = operand_subword (operands[1], 0, 0, DImode); ! 2381: operands[2] = operand_subword (operands[2], 0, 0, DImode); ! 2382: ! 2383: return output_xor (operands); ! 2384: }" ! 2385: [(set_attr "type" "marith") ! 2386: (set_attr "length" "4")]) ; length is 2, 3, or 4. ! 2387: ! 2388: ;;- ones complement instructions ! 2389: (define_insn "one_cmplsi2" ! 2390: [(set (match_operand:SI 0 "register_operand" "=r") ! 2391: (not:SI (match_operand:SI 1 "register_operand" "r")))] ! 2392: "" ! 2393: "xor.c %0,%1,%#r0") ! 2394: ! 2395: (define_insn "one_cmpldi2" ! 2396: [(set (match_operand:DI 0 "register_operand" "=r") ! 2397: (not:DI (match_operand:DI 1 "register_operand" "r")))] ! 2398: "" ! 2399: "xor.c %d0,%d1,%#r0\;xor.c %0,%1,%#r0" ! 2400: [(set_attr "type" "marith")]) ! 2401: ! 2402: ;; Optimized special cases of shifting. ! 2403: ;; Must precede the general case. ! 2404: ! 2405: ;; @@ What about HImode shifted by 8? ! 2406: ! 2407: (define_insn "" ! 2408: [(set (match_operand:SI 0 "register_operand" "=r") ! 2409: (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") ! 2410: (const_int 24)))] ! 2411: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! 2412: "ld.b %0,%1" ! 2413: [(set_attr "type" "load")]) ! 2414: ! 2415: (define_insn "" ! 2416: [(set (match_operand:SI 0 "register_operand" "=r") ! 2417: (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") ! 2418: (const_int 24)))] ! 2419: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! 2420: "ld.bu %0,%1" ! 2421: [(set_attr "type" "load")]) ! 2422: ! 2423: (define_insn "" ! 2424: [(set (match_operand:SI 0 "register_operand" "=r") ! 2425: (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m") ! 2426: (const_int 16)))] ! 2427: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! 2428: "ld.h %0,%1" ! 2429: [(set_attr "type" "load")]) ! 2430: ! 2431: (define_insn "" ! 2432: [(set (match_operand:SI 0 "register_operand" "=r") ! 2433: (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m") ! 2434: (const_int 16)))] ! 2435: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))" ! 2436: "ld.hu %0,%1" ! 2437: [(set_attr "type" "load")]) ! 2438: ! 2439: ;;- arithmetic shift instructions. ! 2440: ! 2441: ;; @@ Do the optimized patterns with -1 get used? Perhaps operand 1 should ! 2442: ;; be arith32_operand? ! 2443: ! 2444: ;; Use tbnd to support TARGET_TRAP_LARGE_SHIFT. ! 2445: (define_insn "tbnd" ! 2446: [(trap_if (gtu (match_operand:SI 0 "register_operand" "r") ! 2447: (match_operand:SI 1 "arith_operand" "rI")) ! 2448: 7)] ! 2449: "" ! 2450: "tbnd %r0,%1" ! 2451: [(set_attr "type" "weird")]) ! 2452: ! 2453: ;; Just in case the optimizer decides to fold away the test. ! 2454: (define_insn "" ! 2455: [(trap_if (const_int 1) 7)] ! 2456: "" ! 2457: "tbnd %#r31,0" ! 2458: [(set_attr "type" "weird")]) ! 2459: ! 2460: (define_expand "ashlsi3" ! 2461: [(set (match_operand:SI 0 "register_operand" "") ! 2462: (ashift:SI (match_operand:SI 1 "register_operand" "") ! 2463: (match_operand:SI 2 "arith32_operand" "")))] ! 2464: "" ! 2465: " ! 2466: { ! 2467: if (GET_CODE (operands[2]) == CONST_INT) ! 2468: { ! 2469: if ((unsigned) INTVAL (operands[2]) > 31) ! 2470: { ! 2471: if (TARGET_TRAP_LARGE_SHIFT) ! 2472: emit_insn (gen_tbnd (force_reg (SImode, operands[2]), ! 2473: gen_rtx (CONST_INT, VOIDmode, 31))); ! 2474: else ! 2475: emit_move_insn (operands[0], const0_rtx); ! 2476: DONE; ! 2477: } ! 2478: } ! 2479: ! 2480: else if (TARGET_TRAP_LARGE_SHIFT) ! 2481: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2482: ! 2483: else if (TARGET_HANDLE_LARGE_SHIFT) ! 2484: { ! 2485: rtx reg = gen_reg_rtx (SImode); ! 2486: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2487: emit_insn (gen_sleu (reg)); ! 2488: emit_insn (gen_andsi3 (reg, operands[1], reg)); ! 2489: operands[1] = reg; ! 2490: } ! 2491: }") ! 2492: ! 2493: (define_insn "" ! 2494: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 2495: (ashift:SI (match_operand:SI 1 "register_operand" "r,r") ! 2496: (match_operand:SI 2 "arith5_operand" "r,n")))] ! 2497: "" ! 2498: "@ ! 2499: mak %0,%1,%2 ! 2500: mak %0,%1,0<%2>") ! 2501: ! 2502: (define_expand "ashrsi3" ! 2503: [(set (match_operand:SI 0 "register_operand" "") ! 2504: (ashiftrt:SI (match_operand:SI 1 "register_operand" "") ! 2505: (match_operand:SI 2 "arith32_operand" "")))] ! 2506: "" ! 2507: " ! 2508: { ! 2509: if (GET_CODE (operands[2]) == CONST_INT) ! 2510: { ! 2511: if ((unsigned) INTVAL (operands[2]) > 31) ! 2512: { ! 2513: if (TARGET_TRAP_LARGE_SHIFT) ! 2514: { ! 2515: emit_insn (gen_tbnd (force_reg (SImode, operands[2]), ! 2516: gen_rtx (CONST_INT, VOIDmode, 31))); ! 2517: DONE; ! 2518: } ! 2519: else ! 2520: operands[2] = gen_rtx (CONST_INT, VOIDmode, 31); ! 2521: } ! 2522: } ! 2523: ! 2524: else if (TARGET_TRAP_LARGE_SHIFT) ! 2525: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2526: ! 2527: else if (TARGET_HANDLE_LARGE_SHIFT) ! 2528: { ! 2529: rtx reg = gen_reg_rtx (SImode); ! 2530: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2531: emit_insn (gen_sgtu (reg)); ! 2532: emit_insn (gen_iorsi3 (reg, operands[2], reg)); ! 2533: operands[2] = reg; ! 2534: } ! 2535: }") ! 2536: ! 2537: (define_insn "" ! 2538: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 2539: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") ! 2540: (match_operand:SI 2 "arith5_operand" "r,n")))] ! 2541: "" ! 2542: "@ ! 2543: ext %0,%1,%2 ! 2544: ext %0,%1,0<%2>") ! 2545: ! 2546: ;;- logical shift instructions. Logical shift left becomes arithmetic ! 2547: ;; shift left. LSHIFT is not normally produced, but is supported. ! 2548: ! 2549: (define_expand "lshlsi3" ! 2550: [(set (match_operand:SI 0 "register_operand" "") ! 2551: (lshift:SI (match_operand:SI 1 "register_operand" "") ! 2552: (match_operand:SI 2 "arith32_operand" "")))] ! 2553: "" ! 2554: " ! 2555: { ! 2556: emit_insn (gen_ashlsi3 (operands[0], operands[1], operands[2])); ! 2557: DONE; ! 2558: }") ! 2559: ! 2560: (define_insn "" ! 2561: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 2562: (lshift:SI (match_operand:SI 1 "register_operand" "r,r") ! 2563: (match_operand:SI 2 "arith5_operand" "r,n")))] ! 2564: "" ! 2565: "@ ! 2566: mak %0,%1,%2 ! 2567: mak %0,%1,0<%2>") ! 2568: ! 2569: (define_expand "lshrsi3" ! 2570: [(set (match_operand:SI 0 "register_operand" "") ! 2571: (lshiftrt:SI (match_operand:SI 1 "register_operand" "") ! 2572: (match_operand:SI 2 "arith32_operand" "")))] ! 2573: "" ! 2574: " ! 2575: { ! 2576: if (GET_CODE (operands[2]) == CONST_INT) ! 2577: { ! 2578: if ((unsigned) INTVAL (operands[2]) > 31) ! 2579: { ! 2580: if (TARGET_TRAP_LARGE_SHIFT) ! 2581: emit_insn (gen_tbnd (force_reg (SImode, operands[2]), ! 2582: gen_rtx (CONST_INT, VOIDmode, 31))); ! 2583: else ! 2584: emit_move_insn (operands[0], const0_rtx); ! 2585: DONE; ! 2586: } ! 2587: } ! 2588: ! 2589: else if (TARGET_TRAP_LARGE_SHIFT) ! 2590: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2591: ! 2592: else if (TARGET_HANDLE_LARGE_SHIFT) ! 2593: { ! 2594: rtx reg = gen_reg_rtx (SImode); ! 2595: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31))); ! 2596: emit_insn (gen_sleu (reg)); ! 2597: emit_insn (gen_andsi3 (reg, operands[1], reg)); ! 2598: operands[1] = reg; ! 2599: } ! 2600: }") ! 2601: ! 2602: (define_insn "" ! 2603: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 2604: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") ! 2605: (match_operand:SI 2 "arith5_operand" "r,n")))] ! 2606: "" ! 2607: "@ ! 2608: extu %0,%1,%2 ! 2609: extu %0,%1,0<%2>") ! 2610: ! 2611: ;;- rotate instructions ! 2612: ! 2613: (define_expand "rotlsi3" ! 2614: [(set (match_operand:SI 0 "register_operand" "") ! 2615: (rotatert:SI (match_operand:SI 1 "register_operand" "") ! 2616: (match_operand:SI 2 "arith32_operand" "")))] ! 2617: "" ! 2618: " ! 2619: { ! 2620: if (GET_CODE (operands[2]) == CONST_INT ! 2621: && (unsigned) INTVAL (operands[2]) >= 32) ! 2622: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 2623: (32 - INTVAL (operands[2])) % 32); ! 2624: else ! 2625: { ! 2626: rtx op = gen_reg_rtx (SImode); ! 2627: emit_insn (gen_negsi2 (op, operands[2])); ! 2628: operands[2] = op; ! 2629: } ! 2630: }") ! 2631: ! 2632: (define_insn "rotrsi3" ! 2633: [(set (match_operand:SI 0 "register_operand" "=r") ! 2634: (rotatert:SI (match_operand:SI 1 "register_operand" "r") ! 2635: (match_operand:SI 2 "arith_operand" "rI")))] ! 2636: "" ! 2637: "rot %0,%1,%2") ! 2638: ! 2639: ;; Bit field instructions. ! 2640: ! 2641: (define_insn "" ! 2642: [(set (match_operand:SI 0 "register_operand" "=r") ! 2643: (sign_extract:SI (match_operand:SI 1 "register_operand" "r") ! 2644: (const_int 32) ! 2645: (const_int 0)))] ! 2646: "" ! 2647: "or %0,%#r0,%1") ! 2648: ! 2649: (define_insn "extv" ! 2650: [(set (match_operand:SI 0 "register_operand" "=r") ! 2651: (sign_extract:SI (match_operand:SI 1 "register_operand" "r") ! 2652: (match_operand:SI 2 "int5_operand" "") ! 2653: (match_operand:SI 3 "int5_operand" "")))] ! 2654: "" ! 2655: "ext %0,%1,%2<(32-%2-%3)>") ! 2656: ! 2657: (define_insn "" ! 2658: [(set (match_operand:SI 0 "register_operand" "=r") ! 2659: (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 2660: (const_int 32) ! 2661: (const_int 0)))] ! 2662: "" ! 2663: "or %0,%#r0,%1") ! 2664: ! 2665: (define_insn "extzv" ! 2666: [(set (match_operand:SI 0 "register_operand" "=r") ! 2667: (zero_extract:SI (match_operand:SI 1 "register_operand" "r") ! 2668: (match_operand:SI 2 "int5_operand" "") ! 2669: (match_operand:SI 3 "int5_operand" "")))] ! 2670: "" ! 2671: "extu %0,%1,%2<(32-%2-%3)>") ! 2672: ! 2673: (define_insn "" ! 2674: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r") ! 2675: (match_operand:SI 1 "int5_operand" "") ! 2676: (match_operand:SI 2 "int5_operand" "")) ! 2677: (const_int 0))] ! 2678: "" ! 2679: "clr %0,%0,%1<(32-%1-%2)>") ! 2680: ! 2681: (define_insn "" ! 2682: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r") ! 2683: (match_operand:SI 1 "int5_operand" "") ! 2684: (match_operand:SI 2 "int5_operand" "")) ! 2685: (const_int -1))] ! 2686: "" ! 2687: "set %0,%0,%1<(32-%1-%2)>") ! 2688: ! 2689: (define_insn "" ! 2690: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=r") ! 2691: (match_operand:SI 1 "int5_operand" "") ! 2692: (match_operand:SI 2 "int5_operand" "")) ! 2693: (match_operand:SI 3 "int32_operand" "n"))] ! 2694: "" ! 2695: "* ! 2696: { ! 2697: int value = INTVAL (operands[3]); ! 2698: ! 2699: if (INTVAL (operands[1]) < 32) ! 2700: value &= (1 << INTVAL (operands[1])) - 1; ! 2701: ! 2702: operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 2703: 32 - (INTVAL(operands[1]) + INTVAL(operands[2]))); ! 2704: ! 2705: value <<= INTVAL (operands[2]); ! 2706: operands[3] = gen_rtx (CONST_INT, VOIDmode, value); ! 2707: ! 2708: if (SMALL_INTVAL (value)) ! 2709: return \"clr %0,%0,%1<%2>\;or %0,%0,%3\"; ! 2710: else if ((value & 0x0000ffff) == 0) ! 2711: return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\"; ! 2712: else ! 2713: return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\;or %0,%0,%x3\"; ! 2714: }" ! 2715: [(set_attr "type" "marith") ! 2716: (set_attr "length" "3")]) ; may be 2 or 3. ! 2717: ! 2718: ;; negate insns ! 2719: (define_insn "negsi2" ! 2720: [(set (match_operand:SI 0 "register_operand" "=r") ! 2721: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))] ! 2722: "" ! 2723: "subu %0,%#r0,%1") ! 2724: ! 2725: (define_insn "" ! 2726: [(set (match_operand:SF 0 "register_operand" "=r") ! 2727: (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r"))))] ! 2728: "" ! 2729: "fsub.ssd %0,%#r0,%1" ! 2730: [(set_attr "type" "dpadd")]) ! 2731: ! 2732: (define_insn "" ! 2733: [(set (match_operand:DF 0 "register_operand" "+r") ! 2734: (neg:DF (match_dup 0)))] ! 2735: "" ! 2736: "xor.u %0,%0,0x8000") ! 2737: ! 2738: (define_insn "negdf2" ! 2739: [(set (match_operand:DF 0 "register_operand" "=&r") ! 2740: (neg:DF (match_operand:DF 1 "register_operand" "r")))] ! 2741: "" ! 2742: "xor.u %0,%1,0x8000\;or %d0,%#r0,%d1" ! 2743: [(set_attr "type" "marith")]) ! 2744: ! 2745: (define_insn "negsf2" ! 2746: [(set (match_operand:SF 0 "register_operand" "=r") ! 2747: (neg:SF (match_operand:SF 1 "register_operand" "r")))] ! 2748: "" ! 2749: "xor.u %0,%1,0x8000") ! 2750: ! 2751: ;; absolute value insns for floating-point (integer abs can be done using the ! 2752: ;; machine-independent sequence). ! 2753: ! 2754: (define_insn "" ! 2755: [(set (match_operand:DF 0 "register_operand" "+r") ! 2756: (abs:DF (match_dup 0)))] ! 2757: "" ! 2758: "and.u %0,%0,0x7fff") ! 2759: ! 2760: (define_insn "absdf2" ! 2761: [(set (match_operand:DF 0 "register_operand" "=&r") ! 2762: (abs:DF (match_operand:DF 1 "register_operand" "r")))] ! 2763: "" ! 2764: "and.u %0,%1,0x7fff\;or %d0,%#r0,%d1" ! 2765: [(set_attr "type" "marith")]) ! 2766: ! 2767: (define_insn "abssf2" ! 2768: [(set (match_operand:SF 0 "register_operand" "=r") ! 2769: (abs:SF (match_operand:SF 1 "register_operand" "r")))] ! 2770: "" ! 2771: "and.u %0,%1,0x7fff") ! 2772: ! 2773: ;; Subroutines of "casesi". ! 2774: ! 2775: ;; Operand 0 is index ! 2776: ;; operand 1 is the minimum bound ! 2777: ;; operand 2 is the maximum bound - minimum bound + 1 ! 2778: ;; operand 3 is CODE_LABEL for the table; ! 2779: ;; operand 4 is the CODE_LABEL to go to if index out of range. ! 2780: ! 2781: (define_expand "casesi" ! 2782: ;; We don't use these for generating the RTL, but we must describe ! 2783: ;; the operands here. ! 2784: [(match_operand:SI 0 "general_operand" "") ! 2785: (match_operand:SI 1 "immediate_operand" "") ! 2786: (match_operand:SI 2 "immediate_operand" "") ! 2787: (match_operand 3 "" "") ! 2788: (match_operand 4 "" "")] ! 2789: "" ! 2790: " ! 2791: { ! 2792: register rtx index_diff = gen_reg_rtx (SImode); ! 2793: register rtx low = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1])); ! 2794: ! 2795: /* Compute the index difference and handle the default case. */ ! 2796: emit_insn (gen_addsi3 (index_diff, ! 2797: force_reg (SImode, operands[0]), ! 2798: ADD_INT (low) ? low : force_reg (SImode, low))); ! 2799: emit_insn (gen_cmpsi (index_diff, operands[2])); ! 2800: emit_jump_insn (gen_bgtu (operands[4])); ! 2801: ! 2802: /* Call the jump that will branch to the appropriate case. */ ! 2803: emit_jump_insn (gen_casesi_enter (gen_rtx (LABEL_REF, VOIDmode, operands[3]), ! 2804: index_diff, ! 2805: operands[3])); ! 2806: /* Claim that flow drops into the table so it will be adjacent. */ ! 2807: DONE; ! 2808: }") ! 2809: ! 2810: ;; The bsr.n instruction is directed to the END of the table. See ! 2811: ;; ASM_OUTPUT_CASE_END. ! 2812: ! 2813: (define_insn "casesi_enter" ! 2814: [(set (pc) (match_operand 0 "" "")) ! 2815: (use (match_operand:SI 1 "register_operand" "r")) ! 2816: ;; The USE here is so that at least one jump-insn will refer to the label, ! 2817: ;; to keep it alive in jump_optimize. ! 2818: (use (label_ref (match_operand 2 "" ""))) ! 2819: (clobber (reg:SI 1))] ! 2820: "" ! 2821: "* ! 2822: { ! 2823: if (flag_delayed_branch) ! 2824: return \"bsr.n %0e\;lda %#r1,%#r1[%1]\"; ! 2825: m88k_case_index = REGNO (operands[1]); ! 2826: return \"bsr %0e\"; ! 2827: }" ! 2828: [(set_attr "type" "weird") ! 2829: (set_attr "length" "3")]) ; Including the "jmp r1". ! 2830: ! 2831: ;;- jump to subroutine ! 2832: (define_expand "call" ! 2833: [(parallel [(call (match_operand:SI 0 "" "") ! 2834: (match_operand 1 "" "")) ! 2835: (use (reg:SI 1))])] ! 2836: "" ! 2837: " ! 2838: { ! 2839: if (GET_CODE (operands[0]) == MEM ! 2840: && ! call_address_operand (XEXP (operands[0], 0), SImode)) ! 2841: operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), ! 2842: force_reg (Pmode, XEXP (operands[0], 0))); ! 2843: }") ! 2844: ! 2845: (define_insn "" ! 2846: [(parallel [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rQ")) ! 2847: (match_operand 1 "" "")) ! 2848: (use (reg:SI 1))])] ! 2849: "" ! 2850: "* return output_call (operands, operands[0]);" ! 2851: [(set_attr "type" "call")]) ! 2852: ! 2853: (define_expand "call_value" ! 2854: [(parallel [(set (match_operand 0 "register_operand" "") ! 2855: (call (match_operand:SI 1 "" "") ! 2856: (match_operand 2 "" ""))) ! 2857: (use (reg:SI 1))])] ! 2858: "" ! 2859: " ! 2860: { ! 2861: if (GET_CODE (operands[1]) == MEM ! 2862: && ! call_address_operand (XEXP (operands[1], 0), SImode)) ! 2863: operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), ! 2864: force_reg (Pmode, XEXP (operands[1], 0))); ! 2865: }") ! 2866: ! 2867: (define_insn "" ! 2868: [(parallel [(set (match_operand 0 "register_operand" "=r") ! 2869: (call (mem:SI ! 2870: (match_operand:SI 1 "call_address_operand" "rQ")) ! 2871: (match_operand 2 "" ""))) ! 2872: (use (reg:SI 1))])] ! 2873: "" ! 2874: "* return output_call (operands, operands[1]);" ! 2875: [(set_attr "type" "call")]) ! 2876: ! 2877: ;; Nop instruction and others ! 2878: ! 2879: (define_insn "nop" ! 2880: [(const_int 0)] ! 2881: "" ! 2882: "ff0 %#r0,%#r0") ! 2883: ! 2884: (define_insn "return" ! 2885: [(return)] ! 2886: "null_epilogue ()" ! 2887: "jmp%. %#r1" ! 2888: [(set_attr "type" "branch")]) ! 2889: ! 2890: (define_insn "indirect_jump" ! 2891: [(set (pc) (match_operand:SI 0 "register_operand" "r"))] ! 2892: "" ! 2893: "jmp%. %0" ! 2894: [(set_attr "type" "branch")]) ! 2895: ! 2896: (define_insn "jump" ! 2897: [(set (pc) ! 2898: (label_ref (match_operand 0 "" "")))] ! 2899: "" ! 2900: "br%. %l0" ! 2901: [(set_attr "type" "jump")]) ! 2902: ! 2903: ;; This insn is used for some loop tests, typically loops reversed when ! 2904: ;; strength reduction is used. It is actually created when the instruction ! 2905: ;; combination phase combines the special loop test. Since this insn ! 2906: ;; is both a jump insn and has an output, it must deal with it's own ! 2907: ;; reloads, hence the `m' constraints. The `!' constraints direct reload ! 2908: ;; to not choose the register alternatives in the event a reload is needed. ! 2909: ! 2910: (define_insn "decrement_and_branch_until_zero" ! 2911: [(set (pc) ! 2912: (if_then_else ! 2913: (match_operator 0 "relop_no_unsigned" ! 2914: [(match_operand:SI 1 "register_operand" "+!r,!r,m,m") ! 2915: (const_int 0)]) ! 2916: (label_ref (match_operand 2 "" "")) ! 2917: (pc))) ! 2918: (set (match_dup 1) ! 2919: (plus:SI (match_dup 1) ! 2920: (match_operand:SI 3 "add_operand" "rI,J,rI,J"))) ! 2921: (clobber (match_scratch:SI 4 "=X,X,&r,&r")) ! 2922: (clobber (match_scratch:SI 5 "=X,X,&r,&r"))] ! 2923: "find_reg_note (insn, REG_NONNEG, 0)" ! 2924: "@ ! 2925: bcnd.n %B0,%1,%2\;addu %1,%1,%3 ! 2926: bcnd.n %B0,%1,%2\;subu %1,%1,%n3 ! 2927: ld %4,%1\;addu %5,%4,%3\;bcnd.n %B0,%4,%2\;st %5,%1 ! 2928: ld %4,%1\;subu %5,%4,%n3\;bcnd.n %B0,%4,%2\;st %5,%1" ! 2929: [(set_attr "type" "weird") ! 2930: (set_attr "length" "2,2,4,4")]) ! 2931: ! 2932: ;; Special insn to serve as the last insn of a define_expand. This insn ! 2933: ;; will generate no code. ! 2934: ! 2935: (define_expand "dummy" ! 2936: [(set (match_operand 0 "" "") (match_dup 0))] ! 2937: "" ! 2938: "") ! 2939: ! 2940: ;;- Local variables: ! 2941: ;;- mode:emacs-lisp ! 2942: ;;- comment-start: ";;- " ! 2943: ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) ! 2944: ;;- eval: (modify-syntax-entry ?[ "(]") ! 2945: ;;- eval: (modify-syntax-entry ?] ")[") ! 2946: ;;- eval: (modify-syntax-entry ?{ "(}") ! 2947: ;;- eval: (modify-syntax-entry ?} "){") ! 2948: ;;- End:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.