|
|
1.1 ! root 1: ;;- Machine description Acorn RISC Machine for GNU compiler ! 2: ;; Copyright (C) 1991 Free Software Foundation, Inc. ! 3: ;; Contributed by Pieter `Tiggr' Schoenmakers ([email protected]) ! 4: ;; and Martin Simmons (@harleqn.co.uk). ! 5: ! 6: ;; This file is part of GNU CC. ! 7: ! 8: ;; GNU CC is free software; you can redistribute it and/or modify ! 9: ;; it under the terms of the GNU General Public License as published by ! 10: ;; the Free Software Foundation; either version 2, or (at your option) ! 11: ;; any later version. ! 12: ! 13: ;; GNU CC is distributed in the hope that it will be useful, ! 14: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 16: ;; GNU General Public License for more details. ! 17: ! 18: ;; You should have received a copy of the GNU General Public License ! 19: ;; along with GNU CC; see the file COPYING. If not, write to ! 20: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 21: ! 22: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ! 23: ! 24: ;; Every template must be output by arm_output_asm_insn, since this keeps ! 25: ;; track of the offset of labels within the text segment. This is needed to ! 26: ;; to be able to (correctly) output instructions for loading a value from a ! 27: ;; function's constant pool, since different instructions are needed when the ! 28: ;; constant pool is more than 4095 bytes away from the PC. ! 29: ! 30: ;; Addition insns. ! 31: ! 32: (define_insn "adddi3" ! 33: [(set (match_operand:DI 0 "di_operand" "=r") ! 34: (plus:DI (match_operand:DI 1 "di_operand" "%r") ! 35: (match_operand:DI 2 "di_operand" "r")))] ! 36: "" ! 37: "* ! 38: arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands); ! 39: return (arm_output_asm_insn (\"adc\\t%R0, %R1, %R2\", operands)); ! 40: ") ! 41: ! 42: (define_insn "addsi3" ! 43: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 44: (plus:SI (match_operand:SI 1 "register_operand" "r,r") ! 45: (match_operand:SI 2 "general_operand" "r,n")))] ! 46: "" ! 47: "* ! 48: switch (which_alternative) ! 49: { ! 50: case 0: ! 51: return (arm_output_asm_insn (\"add\\t%0, %1, %2\", operands)); ! 52: case 1: ! 53: return (output_add_immediate (operands)); ! 54: } ! 55: ") ! 56: ! 57: (define_insn "addsf3" ! 58: [(set (match_operand:SF 0 "register_operand" "=f") ! 59: (plus:SF (match_operand:SF 1 "register_operand" "f") ! 60: (match_operand:SF 2 "fpu_rhs_operand" "fG")))] ! 61: "" ! 62: "* ! 63: return (arm_output_asm_insn (\"adfs\\t%0, %1, %2\", operands)); ! 64: ") ! 65: ! 66: (define_insn "adddf3" ! 67: [(set (match_operand:DF 0 "register_operand" "=f") ! 68: (plus:DF (match_operand:DF 1 "register_operand" "f") ! 69: (match_operand:DF 2 "fpu_rhs_operand" "fG")))] ! 70: "" ! 71: "* ! 72: return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands)); ! 73: ") ! 74: ! 75: (define_insn "subdi3" ! 76: [(set (match_operand:DI 0 "di_operand" "=r") ! 77: (minus:DI (match_operand:DI 1 "di_operand" "%r") ! 78: (match_operand:DI 2 "di_operand" "r")))] ! 79: "" ! 80: "* ! 81: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands); ! 82: return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %R2\", operands)); ! 83: ") ! 84: ! 85: (define_insn "subsi3" ! 86: [(set (match_operand:SI 0 "register_operand" "=r,r,r") ! 87: (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I") ! 88: (match_operand:SI 2 "general_operand" "r,n,r")))] ! 89: "" ! 90: "* ! 91: switch (which_alternative) ! 92: { ! 93: case 0: ! 94: return (arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands)); ! 95: case 1: ! 96: operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2])); ! 97: return (output_add_immediate (operands)); ! 98: case 2: ! 99: return (arm_output_asm_insn (\"rsb\\t%0, %2, %1\", operands)); ! 100: } ! 101: ") ! 102: ! 103: (define_insn "subsf3" ! 104: [(set (match_operand:SF 0 "register_operand" "=f,f") ! 105: (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! 106: (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] ! 107: "" ! 108: "* ! 109: switch (which_alternative) ! 110: { ! 111: case 0: ! 112: return (arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands)); ! 113: case 1: ! 114: return (arm_output_asm_insn (\"rsfs\\t%0, %2, %1\", operands)); ! 115: } ! 116: ") ! 117: ! 118: (define_insn "subdf3" ! 119: [(set (match_operand:DF 0 "register_operand" "=f,f") ! 120: (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") ! 121: (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] ! 122: "" ! 123: "* ! 124: switch (which_alternative) ! 125: { ! 126: case 0: ! 127: return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands)); ! 128: case 2: ! 129: return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands)); ! 130: } ! 131: ") ! 132: ! 133: ;; Multiplication insns ! 134: ! 135: ;; The `&' is too strict, but at least generates correct code. ! 136: (define_insn "mulsi3" ! 137: [(set (match_operand:SI 0 "register_operand" "=&r") ! 138: (mult:SI (match_operand:SI 1 "register_operand" "%r") ! 139: (match_operand:SI 2 "register_operand" "r")))] ! 140: "" ! 141: "* ! 142: if (REGNO (operands[0]) == REGNO (operands[1])) ! 143: return (arm_output_asm_insn (\"mul\\t%0, %2, %1\", operands)); ! 144: else ! 145: return (arm_output_asm_insn (\"mul\\t%0, %1, %2\", operands)); ! 146: ") ! 147: ! 148: ;; Unnamed templates to match MLA instruction. ! 149: ! 150: (define_insn "" ! 151: [(set (match_operand:SI 0 "register_operand" "=&r") ! 152: (plus:SI ! 153: (mult:SI (match_operand:SI 1 "register_operand" "%r") ! 154: (match_operand:SI 2 "register_operand" "r")) ! 155: (match_operand:SI 3 "register_operand" "r")))] ! 156: "" ! 157: "* ! 158: if (REGNO (operands[0]) == REGNO (operands[1])) ! 159: return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands)); ! 160: else ! 161: return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands)); ! 162: ") ! 163: ! 164: (define_insn "" ! 165: [(set (match_operand:SI 0 "register_operand" "=&r") ! 166: (plus:SI ! 167: (match_operand:SI 3 "register_operand" "r") ! 168: (mult:SI (match_operand:SI 1 "register_operand" "%r") ! 169: (match_operand:SI 2 "register_operand" "r"))))] ! 170: "" ! 171: "* ! 172: if (REGNO (operands[0]) == REGNO (operands[1])) ! 173: return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands)); ! 174: else ! 175: return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands)); ! 176: ") ! 177: ! 178: (define_insn "mulsf3" ! 179: [(set (match_operand:SF 0 "register_operand" "=f") ! 180: (mult:SF (match_operand:SF 1 "register_operand" "f") ! 181: (match_operand:SF 2 "fpu_rhs_operand" "fG")))] ! 182: "" ! 183: "*return (arm_output_asm_insn (\"mufs\\t%0, %1, %2\", operands));") ! 184: ! 185: (define_insn "muldf3" ! 186: [(set (match_operand:DF 0 "register_operand" "=f") ! 187: (mult:DF (match_operand:DF 1 "register_operand" "f") ! 188: (match_operand:DF 2 "fpu_rhs_operand" "fG")))] ! 189: "" ! 190: "* ! 191: return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands)); ! 192: ") ! 193: ! 194: ;; Division insns ! 195: ! 196: (define_insn "divsf3" ! 197: [(set (match_operand:SF 0 "register_operand" "=f,f") ! 198: (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G") ! 199: (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))] ! 200: "" ! 201: "* ! 202: switch (which_alternative) ! 203: { ! 204: case 0: ! 205: return (arm_output_asm_insn (\"dvfs\\t%0, %1, %2\", operands)); ! 206: case 1: ! 207: return (arm_output_asm_insn (\"rdfs\\t%0, %2, %1\", operands)); ! 208: } ! 209: ") ! 210: ! 211: (define_insn "divdf3" ! 212: [(set (match_operand:DF 0 "register_operand" "=f,f") ! 213: (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G") ! 214: (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))] ! 215: "" ! 216: "* ! 217: switch (which_alternative) ! 218: { ! 219: case 0: ! 220: return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands)); ! 221: case 1: ! 222: return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands)); ! 223: } ! 224: ") ! 225: ! 226: ;; Modulo insns ! 227: ! 228: (define_insn "modsf3" ! 229: [(set (match_operand:SF 0 "register_operand" "=f") ! 230: (mod:SF (match_operand:SF 1 "register_operand" "f") ! 231: (match_operand:SF 2 "fpu_rhs_operand" "fG")))] ! 232: "" ! 233: "* ! 234: return (arm_output_asm_insn (\"rmfs\\t%0, %1, %2\", operands)); ! 235: ") ! 236: ! 237: (define_insn "moddf3" ! 238: [(set (match_operand:DF 0 "register_operand" "=f") ! 239: (mod:DF (match_operand:DF 1 "register_operand" "f") ! 240: (match_operand:DF 2 "fpu_rhs_operand" "fG")))] ! 241: "" ! 242: "* ! 243: return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands)); ! 244: ") ! 245: ! 246: ;; Boolean and,ior,xor insns ! 247: ! 248: (define_insn "anddi3" ! 249: [(set (match_operand:DI 0 "di_operand" "=r") ! 250: (and:DI (match_operand:DI 1 "di_operand" "%r") ! 251: (match_operand:DI 2 "di_operand" "r")))] ! 252: "" ! 253: "* ! 254: arm_output_asm_insn (\"and\\t%0, %1, %2\", operands); ! 255: return (arm_output_asm_insn (\"and\\t%R0, %R1, %R2\", operands)); ! 256: ") ! 257: ! 258: (define_insn "andsi3" ! 259: [(set (match_operand:SI 0 "register_operand" "=r") ! 260: (and:SI (match_operand:SI 1 "register_operand" "r") ! 261: (match_operand:SI 2 "arm_rhs_operand" "rI")))] ! 262: "" ! 263: "* ! 264: return (arm_output_asm_insn (\"and\\t%0, %1, %2\", operands)); ! 265: ") ! 266: ! 267: (define_insn "andcbsi3" ! 268: [(set (match_operand:SI 0 "register_operand" "=r") ! 269: (and:SI (match_operand:SI 1 "register_operand" "r") ! 270: (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))))] ! 271: "" ! 272: "* ! 273: return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands)); ! 274: ") ! 275: ! 276: (define_insn "iordi3" ! 277: [(set (match_operand:DI 0 "di_operand" "=r") ! 278: (ior:DI (match_operand:DI 1 "di_operand" "%r") ! 279: (match_operand:DI 2 "di_operand" "r")))] ! 280: "" ! 281: "* ! 282: arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands); ! 283: return (arm_output_asm_insn (\"orr\\t%R0, %R1, %R2\", operands)); ! 284: ") ! 285: ! 286: (define_insn "iorsi3" ! 287: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 288: (ior:SI (match_operand:SI 1 "register_operand" "r,r") ! 289: (match_operand:SI 2 "nonmemory_operand" "r,n")))] ! 290: "" ! 291: "* ! 292: switch (which_alternative) ! 293: { ! 294: case 0: ! 295: return (arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands)); ! 296: case 1: ! 297: return (output_multi_immediate (operands, ! 298: \"orr\\t%0, %1, %2\", \"orr\\t%0, %0, %2\", ! 299: 2, INTVAL (operands[2]))); ! 300: } ! 301: ") ! 302: ! 303: (define_insn "xorsi3" ! 304: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 305: (xor:SI (match_operand:SI 1 "register_operand" "r,r") ! 306: (match_operand:SI 2 "nonmemory_operand" "r,n")))] ! 307: "" ! 308: "* ! 309: switch (which_alternative) ! 310: { ! 311: case 0: ! 312: return (arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands)); ! 313: case 1: ! 314: return (output_multi_immediate (operands, ! 315: \"eor\\t%0, %1, %2\", \"eor\\t%0, %0, %2\", ! 316: 2, INTVAL (operands[2]))); ! 317: } ! 318: ") ! 319: ! 320: ;; Shift and rotation insns ! 321: ! 322: (define_insn "ashlsi3" ! 323: [(set (match_operand:SI 0 "register_operand" "=r") ! 324: (ashift:SI (match_operand:SI 1 "register_operand" "r") ! 325: (match_operand:SI 2 "general_operand" "rn")))] ! 326: "" ! 327: "* ! 328: return (output_shifted_move (ASHIFT, operands)); ! 329: ") ! 330: ! 331: (define_insn "ashrsi3" ! 332: [(set (match_operand:SI 0 "register_operand" "=r") ! 333: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") ! 334: (match_operand:SI 2 "general_operand" "rn")))] ! 335: "" ! 336: "* ! 337: return (output_shifted_move (ASHIFTRT, operands)); ! 338: ") ! 339: ! 340: ;; lshlsi3 is not defined because shift counts cannot be negative ! 341: ;; An unnamed pattern is needed for expansion of zero_extend. ! 342: ! 343: (define_insn "" ! 344: [(set (match_operand:SI 0 "register_operand" "=r") ! 345: (lshift:SI (match_operand:SI 1 "register_operand" "r") ! 346: (match_operand:SI 2 "general_operand" "rn")))] ! 347: "" ! 348: "* ! 349: return (output_shifted_move (LSHIFT, operands)); ! 350: ") ! 351: ! 352: (define_insn "lshrsi3" ! 353: [(set (match_operand:SI 0 "register_operand" "=r") ! 354: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") ! 355: (match_operand:SI 2 "general_operand" "rn")))] ! 356: "" ! 357: "* ! 358: return (output_shifted_move (LSHIFTRT, operands)); ! 359: ") ! 360: ! 361: ;; rotlsi3 is not defined yet to see what happens ! 362: ! 363: (define_insn "rotrsi3" ! 364: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 365: (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") ! 366: (match_operand:SI 2 "general_operand" "r,n")))] ! 367: "" ! 368: "* ! 369: switch (which_alternative) ! 370: { ! 371: case 0: ! 372: return (arm_output_asm_insn (\"mov\\t%0, %1,ror %2\", operands)); ! 373: case 1: ! 374: if (INTVAL(operands[2]) > 31) ! 375: operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32); ! 376: return (arm_output_asm_insn (\"mov\\t%0, %1,ror%2\", operands)); ! 377: } ! 378: ") ! 379: ! 380: ;; Unary arithmetic insns ! 381: ! 382: (define_insn "negdi2" ! 383: [(set (match_operand:DI 0 "di_operand" "=r") ! 384: (neg:DI (match_operand:DI 1 "di_operand" "r")))] ! 385: "" ! 386: "* ! 387: arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands); ! 388: return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands)); ! 389: ") ! 390: ! 391: (define_insn "negsi2" ! 392: [(set (match_operand:SI 0 "register_operand" "=r") ! 393: (neg:SI (match_operand:SI 1 "register_operand" "r")))] ! 394: "" ! 395: "* ! 396: return (arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands)); ! 397: ") ! 398: ! 399: (define_insn "negsf2" ! 400: [(set (match_operand:SF 0 "register_operand" "=f") ! 401: (neg:SF (match_operand:SF 1 "register_operand" "f")))] ! 402: "" ! 403: "* ! 404: return (arm_output_asm_insn (\"mnfs\\t%0, %1\", operands)); ! 405: ") ! 406: ! 407: (define_insn "negdf2" ! 408: [(set (match_operand:DF 0 "register_operand" "=f") ! 409: (neg:DF (match_operand:DF 1 "register_operand" "f")))] ! 410: "" ! 411: "* ! 412: return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands)); ! 413: ") ! 414: ! 415: (define_insn "abssf2" ! 416: [(set (match_operand:SF 0 "register_operand" "=f") ! 417: (abs:SF (match_operand:SF 1 "register_operand" "f")))] ! 418: "" ! 419: "* ! 420: return (arm_output_asm_insn (\"abss\\t%0, %1\", operands)); ! 421: ") ! 422: ! 423: (define_insn "absdf2" ! 424: [(set (match_operand:DF 0 "register_operand" "=f") ! 425: (abs:DF (match_operand:DF 1 "register_operand" "f")))] ! 426: "" ! 427: "* ! 428: return (arm_output_asm_insn (\"absd\\t%0, %1\", operands)); ! 429: ") ! 430: ! 431: (define_insn "sqrtsf2" ! 432: [(set (match_operand:SF 0 "register_operand" "=f") ! 433: (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] ! 434: "" ! 435: "* ! 436: return (arm_output_asm_insn (\"sqts\\t%0, %1\", operands)); ! 437: ") ! 438: ! 439: (define_insn "sqrtdf2" ! 440: [(set (match_operand:DF 0 "register_operand" "=f") ! 441: (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] ! 442: "" ! 443: "* ! 444: return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands)); ! 445: ") ! 446: ! 447: (define_insn "one_cmplsi2" ! 448: [(set (match_operand:SI 0 "register_operand" "=r") ! 449: (not:SI (match_operand:SI 1 "register_operand" "r")))] ! 450: "" ! 451: "* ! 452: return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands)); ! 453: ") ! 454: ! 455: ;; Fixed <--> Floating conversion insns ! 456: ! 457: (define_insn "floatsisf2" ! 458: [(set (match_operand:SF 0 "register_operand" "=f") ! 459: (float:SF (match_operand:SI 1 "register_operand" "r")))] ! 460: "" ! 461: "* ! 462: return (arm_output_asm_insn (\"flts\\t%0, %1\", operands)); ! 463: ") ! 464: ! 465: (define_insn "floatsidf2" ! 466: [(set (match_operand:DF 0 "register_operand" "=f") ! 467: (float:DF (match_operand:SI 1 "register_operand" "r")))] ! 468: "" ! 469: "* ! 470: return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands)); ! 471: ") ! 472: ! 473: ;; Truncation insns ! 474: ! 475: (define_insn "truncsiqi2" ! 476: [(set (match_operand:QI 0 "general_operand" "=mr") ! 477: (truncate:QI (match_operand:SI 1 "register_operand" "r")))] ! 478: "" ! 479: "* ! 480: if (GET_CODE (operands[0]) == MEM) ! 481: return (arm_output_asm_insn (\"strb\\t%1, %0\\t@ truncsiqi2\", operands)); ! 482: else ! 483: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ truncsiqi2\", operands)); ! 484: ") ! 485: ! 486: (define_insn "trunchiqi2" ! 487: [(set (match_operand:QI 0 "general_operand" "=mr") ! 488: (truncate:QI (match_operand:HI 1 "register_operand" "r")))] ! 489: "" ! 490: "* ! 491: if (GET_CODE(operands[0]) == MEM) ! 492: return (arm_output_asm_insn (\"strb\\t%1, %0\\t@ trunchiqi2\", operands)); ! 493: else ! 494: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ trunchiqi2\", operands)); ! 495: ") ! 496: ! 497: ;; Mode is changed to SI below ! 498: ! 499: (define_expand "truncsihi2" ! 500: [(set (match_operand:SI 0 "register_operand" "") ! 501: (ashift:SI (match_operand:HI 1 "register_operand" "") ! 502: (const_int 16))) ! 503: (set (match_dup 0) ! 504: (ashiftrt:SI (match_dup 0) (const_int 16)))] ! 505: "" ! 506: " ! 507: if (GET_CODE (operands[1]) == SUBREG) ! 508: operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! 509: SUBREG_WORD (operands[1])); ! 510: else ! 511: operands[1] = gen_rtx(SUBREG, SImode, operands[1], 0); ! 512: ") ! 513: ! 514: (define_insn "truncdfsf2" ! 515: [(set (match_operand:SF 0 "register_operand" "=f") ! 516: (float_truncate:SF ! 517: (match_operand:DF 1 "register_operand" "f")))] ! 518: "" ! 519: "* ! 520: return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands)); ! 521: ") ! 522: ! 523: ;; Zero extention instructions. ! 524: ! 525: (define_expand "zero_extendhisi2" ! 526: [(set (match_operand:SI 0 "register_operand" "") ! 527: (ashift:SI (match_operand:HI 1 "register_operand" "") ! 528: (const_int 16))) ! 529: (set (match_dup 0) ! 530: (lshiftrt:SI (match_dup 0) (const_int 16)))] ! 531: "" ! 532: " ! 533: if (GET_CODE (operands[1]) == SUBREG) ! 534: operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! 535: SUBREG_WORD (operands[1])); ! 536: else ! 537: operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! 538: ") ! 539: ! 540: (define_insn "zero_extendqihi2" ! 541: [(set (match_operand:HI 0 "register_operand" "=r") ! 542: (zero_extend:HI ! 543: (match_operand:QI 1 "register_operand" "r")))] ! 544: "" ! 545: "* ! 546: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands)); ! 547: ") ! 548: ! 549: (define_insn "zero_extendqisi2" ! 550: [(set (match_operand:SI 0 "register_operand" "=r,r") ! 551: (zero_extend:SI ! 552: (match_operand:QI 1 "nonimmediate_operand" "r,m")))] ! 553: "" ! 554: "* ! 555: switch (which_alternative) ! 556: { ! 557: case 0: ! 558: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands)); ! 559: case 1: ! 560: return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands)); ! 561: } ! 562: ") ! 563: ! 564: ;; Note that the ones starting from HImode come before those for QImode so ! 565: ;; that a constant operand will match HImode, not QImode. ! 566: ! 567: (define_expand "extendhisi2" ! 568: [(set (match_operand:SI 0 "register_operand" "") ! 569: (ashift:SI (match_operand:HI 1 "register_operand" "") ! 570: (const_int 16))) ! 571: (set (match_dup 0) ! 572: (ashiftrt:SI (match_dup 0) (const_int 16)))] ! 573: "" ! 574: " ! 575: if (GET_CODE (operands[1]) == SUBREG) ! 576: operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! 577: SUBREG_WORD (operands[1])); ! 578: else ! 579: operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! 580: ") ! 581: ! 582: ;; XXX Is this ever used? ! 583: ! 584: (define_insn "extendqihi2" ! 585: [(set (match_operand:HI 0 "register_operand" "=r") ! 586: (sign_extend:SI ! 587: (match_operand:QI 1 "register_operand" "r")))] ! 588: "" ! 589: "* ! 590: arm_output_asm_insn (\"mov\\t%0, %1, lsl#24\\t@ extendqihi\", operands); ! 591: return (arm_output_asm_insn (\"mov\\t%0, %0, asr#24\", operands)); ! 592: ") ! 593: ! 594: ! 595: (define_expand "extendqisi2" ! 596: [(set (match_operand:SI 0 "register_operand" "") ! 597: (ashift:SI (match_operand:QI 1 "register_operand" "") ! 598: (const_int 24))) ! 599: (set (match_dup 0) ! 600: (ashiftrt:SI (match_dup 0) (const_int 24)))] ! 601: "" ! 602: " ! 603: if (GET_CODE (operands[1]) == SUBREG) ! 604: operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), ! 605: SUBREG_WORD(operands[1])); ! 606: else ! 607: operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); ! 608: ") ! 609: ! 610: (define_insn "extendsfdf2" ! 611: [(set (match_operand:DF 0 "register_operand" "=f") ! 612: (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] ! 613: "" ! 614: "* ! 615: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands)); ! 616: ") ! 617: ! 618: ;; Move insns (including loads and stores) ! 619: ! 620: ;; XXX Just some ideas about movti. ! 621: ! 622: ;;(define_expand "loadti" ! 623: ;; [(set (match_operand:TI 0 "register_operand" "") ! 624: ;; (mem:TI (match_operand:SI 1 "address_operand" "")))] ! 625: ;; "" "") ! 626: ! 627: ;;(define_expand "storeti" ! 628: ;; [(set (mem:TI (match_operand:TI 0 "address_operand" "")) ! 629: ;; (match_operand:TI 1 "register_operand" ""))] ! 630: ;; "" "") ! 631: ! 632: ;;(define_expand "movti" ! 633: ;; [(set (match_operand:TI 0 "general_operand" "") ! 634: ;; (match_operand:TI 1 "general_operand" ""))] ! 635: ;; "" ! 636: ;; " ! 637: ;;{ ! 638: ;; rtx insn; ! 639: ;; ! 640: ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) ! 641: ;; operands[1] = copy_to_reg (operands[1]); ! 642: ;; if (GET_CODE (operands[0]) == MEM) ! 643: ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]); ! 644: ;; else if (GET_CODE (operands[1]) == MEM) ! 645: ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0)); ! 646: ;; else ! 647: ;; FAIL; ! 648: ;; ! 649: ;; emit_insn (insn); ! 650: ;; DONE; ! 651: ;;}") ! 652: ! 653: ;; Recognise garbage generated above. ! 654: ! 655: ;;(define_insn "" ! 656: ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m") ! 657: ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))] ! 658: ;; "" ! 659: ;; "* ! 660: ;; { ! 661: ;; register mem = (which_alternative < 3); ! 662: ;; register char *template; ! 663: ;; ! 664: ;; operands[mem] = XEXP (operands[mem], 0); ! 665: ;; switch (which_alternative) ! 666: ;; { ! 667: ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break; ! 668: ;; case 1: template = \"ldmia\\t%1!, %M0\"; break; ! 669: ;; case 2: template = \"ldmia\\t%1, %M0\"; break; ! 670: ;; case 3: template = \"stmdb\\t%0!, %M1\"; break; ! 671: ;; case 4: template = \"stmia\\t%0!, %M1\"; break; ! 672: ;; case 5: template = \"stmia\\t%0, %M1\"; break; ! 673: ;; } ! 674: ;; return (arm_output_asm_insn (template, operands)); ! 675: ;; }") ! 676: ! 677: ! 678: (define_insn "movdi" ! 679: [(set (match_operand:DI 0 "di_operand" "=r,r,r,o,r") ! 680: (match_operand:DI 1 "di_operand" "r,n,o,r,F"))] ! 681: "" ! 682: "* ! 683: return (output_move_double (operands)); ! 684: ") ! 685: ! 686: (define_insn "movsi" ! 687: [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") ! 688: (match_operand:SI 1 "general_operand" "r,n,m,r"))] ! 689: "" ! 690: "* ! 691: switch (which_alternative) ! 692: { ! 693: case 0: ! 694: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); ! 695: case 1: ! 696: return (output_mov_immediate (operands)); ! 697: case 2: ! 698: if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF ! 699: && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))) ! 700: return (arm_output_llc (operands)); ! 701: else ! 702: return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands)); ! 703: case 3: ! 704: return (arm_output_asm_insn (\"str\\t%1, %0\", operands)); ! 705: } ! 706: ") ! 707: ! 708: ;; XXX The movhi stuff isn't as correct or as nice as it could be... ! 709: ! 710: ;; Subroutine to load a half word into a register from memory. ! 711: ;; Operand 0 is the destination register (HImode). ! 712: ;; Operand 1 is the source address (SImode). ! 713: ;; Operand 2 is a temporary (SImode). ! 714: ! 715: ;;(define_expand "loadhi" ! 716: ;; [;; load the whole word (ARM realigns it if not on word boundary) ! 717: ;; (set (match_operand:SI 2 "register_operand" "") ! 718: ;; (mem:SI (match_operand:SI 1 "address_operand" ""))) ! 719: ;; ;; quietly forget the upper 16 bits ! 720: ;; (set (match_operand:HI 0 "register_operand" "") ! 721: ;; (subreg:HI (match_dup 2) 0))] ! 722: ;; "" ! 723: ;; "" ! 724: ;;) ! 725: ! 726: ;; Load op0 from mem:op1. Subroutine in case we're reloading and the normal ! 727: ;; loadhi is not allowed. ! 728: ! 729: ;;(define_expand "reloadhi" ! 730: ;; [(set (reg:SI 10) ! 731: ;; (mem:SI (match_operand:SI 1 "address_operand" ""))) ! 732: ;; (set (match_operand:HI 0 "register_operand" "") ! 733: ;; (subreg:HI (reg:SI 10) 0))] ! 734: ;; "" "") ! 735: ! 736: ;; Store op0 into mem:op1. Subroutine in case we're reloading and the normal ! 737: ;; storehi is not allowed. ! 738: ! 739: (define_expand "restorehi" ! 740: [(set (mem:QI (match_operand:SI 1 "address_operand" "")) ! 741: (truncate:QI (match_operand:HI 0 "register_operand" ""))) ! 742: (set (reg:HI 10) ! 743: (ashiftrt:HI (match_dup 0) (const_int 8))) ! 744: (set (mem:QI (plus:SI (match_dup 1) (const_int 1))) ! 745: (truncate:QI (reg:HI 10)))] ! 746: "" "") ! 747: ! 748: ;; Subroutine to store a half word from a register into memory. ! 749: ;; Operand 0 is the source register (HImode) ! 750: ;; Operand 1 is the destination address (SImode) ! 751: ;; Operand 2 is a temporary (SImode). ! 752: ;; Operand 3 is a temporary (SImode). ! 753: ;; Operand 4 is a temporary (SImode). ! 754: ;; Operand 5 is a local temporary (SImode). ! 755: ! 756: (define_expand "storehi" ! 757: [;; compute the address into a register ! 758: (set (match_operand:SI 2 "register_operand" "") ! 759: (match_operand:SI 1 "address_operand" "")) ! 760: ;; get the half word into a full word register ! 761: (set (match_operand:SI 3 "register_operand" "") ! 762: (match_dup 5)) ! 763: ;; store the low byte ! 764: (set (mem:QI (match_dup 2)) ! 765: (truncate:QI (match_dup 3))) ! 766: ;; extract the high byte ! 767: (set (match_operand:SI 4 "register_operand" "") ! 768: (ashiftrt:SI (match_dup 3) (const_int 8))) ! 769: ;; store the high byte ! 770: (set (mem:QI (plus (match_dup 2) (const_int 1))) ! 771: (truncate:QI (match_dup 4)))] ! 772: "" ! 773: " ! 774: if (GET_CODE(operands[0]) == SUBREG) ! 775: operands[5] = gen_rtx(SUBREG, SImode, SUBREG_REG(operands[0]), ! 776: SUBREG_WORD(operands[0])); ! 777: else ! 778: operands[5] = gen_rtx(SUBREG, SImode, operands[0], 0); ! 779: ! 780: ") ! 781: ! 782: ;; Subroutine to store a half word integer constant into memory. ! 783: ;; Operand 0 is the constant ! 784: ;; Operand 1 is the destination address (SImode) ! 785: ;; Operand 2 is a temporary (SImode). ! 786: ;; Operand 3 is a temporary (QImode). ! 787: ;; Operand 4 is a temporary (QImode). ! 788: ;; Operand 5 is a local CONST_INT. ! 789: ;; Operand 6 is a local CONST_INT. ! 790: ! 791: (define_expand "storeinthi" ! 792: [;; compute the address into a register ! 793: (set (match_operand:SI 2 "register_operand" "") ! 794: (match_operand:SI 1 "address_operand" "")) ! 795: ;; load the low byte ! 796: (set (match_operand:QI 3 "register_operand" "") ! 797: (match_dup 5)) ! 798: ;; store the low byte ! 799: (set (mem:QI (match_dup 2)) ! 800: (match_dup 3)) ! 801: ;; load the high byte ! 802: (set (match_operand:QI 4 "register_operand" "") ! 803: (match_dup 6)) ! 804: ;; store the high byte ! 805: (set (mem:QI (plus (match_dup 2) (const_int 1))) ! 806: (match_dup 4))] ! 807: "" ! 808: " ! 809: { ! 810: int value = INTVAL(operands[0]); ! 811: ! 812: operands[5] = gen_rtx(CONST_INT, VOIDmode, value & 255); ! 813: operands[6] = gen_rtx(CONST_INT, VOIDmode,(value>>8) & 255); ! 814: } ! 815: ") ! 816: ! 817: (define_expand "movhi" ! 818: [(set (match_operand:HI 0 "general_operand" "") ! 819: (match_operand:HI 1 "general_operand" ""))] ! 820: "" ! 821: " ! 822: { ! 823: rtx insn; ! 824: ! 825: if (reload_in_progress || reload_completed) ! 826: { ! 827: if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == REG) ! 828: insn = gen_restorehi (operands[1], XEXP (operands[0], 0)); ! 829: else ! 830: insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]); ! 831: } ! 832: else ! 833: { ! 834: if (GET_CODE (operands[0]) == MEM) ! 835: { ! 836: if (GET_CODE (operands[1]) == MEM) ! 837: operands[1] = copy_to_reg (operands[1]); ! 838: ! 839: if (GET_CODE (operands[1]) == CONST_INT) ! 840: { ! 841: insn = gen_storeinthi (operands[1], XEXP (operands[0], 0), ! 842: gen_reg_rtx (SImode), ! 843: gen_reg_rtx (QImode), ! 844: gen_reg_rtx (QImode)); ! 845: } ! 846: else ! 847: { ! 848: insn = gen_storehi (operands[1], XEXP (operands[0], 0), ! 849: gen_reg_rtx (SImode), ! 850: gen_reg_rtx (SImode), ! 851: gen_reg_rtx (SImode)); ! 852: } ! 853: } ! 854: #if 0 ! 855: else if (GET_CODE (operands[1]) == MEM) ! 856: { ! 857: insn = gen_loadhi (operands[0], XEXP (operands[1], 0), ! 858: gen_reg_rtx (SImode)); ! 859: } ! 860: #endif ! 861: else ! 862: insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]); ! 863: } ! 864: ! 865: emit_insn (insn); ! 866: DONE; ! 867: }") ! 868: ! 869: ;; Pattern to recognise insn generated default case above ! 870: ! 871: (define_insn "" ! 872: [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") ! 873: (match_operand:HI 1 "general_operand" "r,n,m,r"))] ! 874: "" ! 875: "* ! 876: switch (which_alternative) ! 877: { ! 878: case 0: return (arm_output_asm_insn (\"mov\\t%0, %1\\t@movhi\", operands)); ! 879: case 1: return (output_mov_immediate (operands)); ! 880: case 2: return (arm_output_asm_insn (\"ldr\\t%0, %1\\t@movhi\", operands)); ! 881: case 3: return (arm_output_asm_insn (\"str\\t%1, %0\\t@movhi\", operands)); ! 882: } ! 883: ") ! 884: ! 885: (define_insn "movqi" ! 886: [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") ! 887: (match_operand:QI 1 "general_operand" "r,n,m,r"))] ! 888: "" ! 889: "* ! 890: switch (which_alternative) ! 891: { ! 892: case 0: ! 893: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); ! 894: case 1: ! 895: return (output_mov_immediate (operands)); ! 896: case 2: ! 897: return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands)); ! 898: case 3: ! 899: return (arm_output_asm_insn (\"strb\\t%1, %0\", operands)); ! 900: } ! 901: ! 902: ") ! 903: ! 904: (define_insn "movsf" ! 905: [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r") ! 906: (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))] ! 907: "" ! 908: "* ! 909: switch (which_alternative) ! 910: { ! 911: case 0: ! 912: return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands)); ! 913: case 1: ! 914: return (arm_output_asm_insn (\"ldfs\\t%0, %1\", operands)); ! 915: case 2: ! 916: return (arm_output_asm_insn (\"stfs\\t%1, %0\", operands)); ! 917: case 3: ! 918: arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands); ! 919: return (arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands)); ! 920: case 4: ! 921: arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands); ! 922: return (arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands)); ! 923: case 5: ! 924: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); ! 925: } ! 926: ") ! 927: ! 928: (define_insn "movdf" ! 929: [(set (match_operand:DF 0 "general_operand" "=f,f,m,f,r,r") ! 930: (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))] ! 931: "" ! 932: "* ! 933: switch (which_alternative) ! 934: { ! 935: case 0: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands)); ! 936: case 1: return (arm_output_asm_insn (\"ldfd\\t%0, %1\", operands)); ! 937: case 2: return (arm_output_asm_insn (\"stfd\\t%1, %0\", operands)); ! 938: case 3: return (output_mov_double_fpu_from_arm (operands)); ! 939: case 4: return (output_mov_double_arm_from_fpu (operands)); ! 940: case 5: return (output_move_double (operands)); ! 941: } ! 942: ") ! 943: ! 944: ;; Comparison and test insns ! 945: ! 946: (define_insn "cmpsi" ! 947: [(set (cc0) ! 948: (compare (match_operand:SI 0 "register_operand" "r") ! 949: (match_operand:SI 1 "arm_rhs_operand" "rI")))] ! 950: "" ! 951: "* ! 952: return (arm_output_asm_insn (\"cmp\\t%0, %1\", operands)); ! 953: ") ! 954: ! 955: (define_insn "tstsi" ! 956: [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] ! 957: "" ! 958: "* ! 959: return (arm_output_asm_insn (\"cmp\\t%0, #0\", operands)); ! 960: ") ! 961: ! 962: (define_insn "" ! 963: [(set (cc0) ! 964: (compare (match_operand:SI 0 "register_operand" "r") ! 965: (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))] ! 966: "" ! 967: "* ! 968: return (arm_output_asm_insn (\"cmn\\t%0, %1\", operands)); ! 969: ") ! 970: ! 971: (define_insn "cmpsf" ! 972: [(set (cc0) ! 973: (compare (match_operand:SF 0 "register_operand" "f") ! 974: (match_operand:SF 1 "fpu_rhs_operand" "fG")))] ! 975: "" ! 976: "* ! 977: return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands)); ! 978: ") ! 979: ! 980: (define_insn "cmpdf" ! 981: [(set (cc0) ! 982: (compare (match_operand:DF 0 "register_operand" "f") ! 983: (match_operand:DF 1 "fpu_rhs_operand" "fG")))] ! 984: "" ! 985: "* ! 986: return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands)); ! 987: ") ! 988: ! 989: ;; Conditional branch insns ! 990: ! 991: (define_insn "beq" ! 992: [(set (pc) ! 993: (if_then_else (eq (cc0) (const_int 0)) ! 994: (label_ref (match_operand 0 "" "")) ! 995: (pc)))] ! 996: "" ! 997: "* ! 998: return (arm_output_asm_insn (\"beq\\t%l0\", operands)); ! 999: ") ! 1000: ! 1001: (define_insn "bne" ! 1002: [(set (pc) ! 1003: (if_then_else (ne (cc0) (const_int 0)) ! 1004: (label_ref (match_operand 0 "" "")) ! 1005: (pc)))] ! 1006: "" ! 1007: "* ! 1008: return (arm_output_asm_insn (\"bne\\t%l0\", operands)); ! 1009: ") ! 1010: ! 1011: (define_insn "bgt" ! 1012: [(set (pc) ! 1013: (if_then_else (gt (cc0) (const_int 0)) ! 1014: (label_ref (match_operand 0 "" "")) ! 1015: (pc)))] ! 1016: "" ! 1017: "* ! 1018: return (arm_output_asm_insn (\"bgt\\t%l0\", operands)); ! 1019: ") ! 1020: ! 1021: (define_insn "ble" ! 1022: [(set (pc) ! 1023: (if_then_else (le (cc0) (const_int 0)) ! 1024: (label_ref (match_operand 0 "" "")) ! 1025: (pc)))] ! 1026: "" ! 1027: "* ! 1028: return (arm_output_asm_insn (\"ble\\t%l0\", operands)); ! 1029: ") ! 1030: ! 1031: (define_insn "bge" ! 1032: [(set (pc) ! 1033: (if_then_else (ge (cc0) (const_int 0)) ! 1034: (label_ref (match_operand 0 "" "")) ! 1035: (pc)))] ! 1036: "" ! 1037: "* ! 1038: return (arm_output_asm_insn (\"bge\\t%l0\", operands)); ! 1039: ") ! 1040: ! 1041: (define_insn "blt" ! 1042: [(set (pc) ! 1043: (if_then_else (lt (cc0) (const_int 0)) ! 1044: (label_ref (match_operand 0 "" "")) ! 1045: (pc)))] ! 1046: "" ! 1047: "* ! 1048: return (arm_output_asm_insn (\"blt\\t%l0\", operands)); ! 1049: ") ! 1050: ! 1051: (define_insn "bgtu" ! 1052: [(set (pc) ! 1053: (if_then_else (gtu (cc0) (const_int 0)) ! 1054: (label_ref (match_operand 0 "" "")) ! 1055: (pc)))] ! 1056: "" ! 1057: "* ! 1058: return (arm_output_asm_insn (\"bhi\\t%l0\", operands)); ! 1059: ") ! 1060: ! 1061: (define_insn "bleu" ! 1062: [(set (pc) ! 1063: (if_then_else (leu (cc0) (const_int 0)) ! 1064: (label_ref (match_operand 0 "" "")) ! 1065: (pc)))] ! 1066: "" ! 1067: "* ! 1068: return (arm_output_asm_insn (\"bls\\t%l0\", operands)); ! 1069: ") ! 1070: ! 1071: (define_insn "bgeu" ! 1072: [(set (pc) ! 1073: (if_then_else (geu (cc0) (const_int 0)) ! 1074: (label_ref (match_operand 0 "" "")) ! 1075: (pc)))] ! 1076: "" ! 1077: "* ! 1078: return (arm_output_asm_insn (\"bhs\\t%l0\", operands)); ! 1079: ") ! 1080: ! 1081: (define_insn "bltu" ! 1082: [(set (pc) ! 1083: (if_then_else (ltu (cc0) (const_int 0)) ! 1084: (label_ref (match_operand 0 "" "")) ! 1085: (pc)))] ! 1086: "" ! 1087: "* ! 1088: return (arm_output_asm_insn (\"blo\\t%l0\", operands)); ! 1089: ") ! 1090: ! 1091: ;; Inverted conditional branch insns ! 1092: ! 1093: (define_insn "" ! 1094: [(set (pc) ! 1095: (if_then_else (eq (cc0) (const_int 0)) ! 1096: (pc) ! 1097: (label_ref (match_operand 0 "" ""))))] ! 1098: "" ! 1099: "* ! 1100: return (arm_output_asm_insn (\"bne\\t%l0\", operands)); ! 1101: ") ! 1102: ! 1103: (define_insn "" ! 1104: [(set (pc) ! 1105: (if_then_else (ne (cc0) (const_int 0)) ! 1106: (pc) ! 1107: (label_ref (match_operand 0 "" ""))))] ! 1108: "" ! 1109: "* ! 1110: return (arm_output_asm_insn (\"beq\\t%l0\", operands)); ! 1111: ") ! 1112: ! 1113: (define_insn "" ! 1114: [(set (pc) ! 1115: (if_then_else (gt (cc0) (const_int 0)) ! 1116: (pc) ! 1117: (label_ref (match_operand 0 "" ""))))] ! 1118: "" ! 1119: "* ! 1120: return (arm_output_asm_insn (\"ble\\t%l0\", operands)); ! 1121: ") ! 1122: ! 1123: (define_insn "" ! 1124: [(set (pc) ! 1125: (if_then_else (le (cc0) (const_int 0)) ! 1126: (pc) ! 1127: (label_ref (match_operand 0 "" ""))))] ! 1128: "" ! 1129: "* ! 1130: return (arm_output_asm_insn (\"bgt\\t%l0\", operands)); ! 1131: ") ! 1132: ! 1133: (define_insn "" ! 1134: [(set (pc) ! 1135: (if_then_else (ge (cc0) (const_int 0)) ! 1136: (pc) ! 1137: (label_ref (match_operand 0 "" ""))))] ! 1138: "" ! 1139: "* ! 1140: return (arm_output_asm_insn (\"blt\\t%l0\", operands)); ! 1141: ") ! 1142: ! 1143: (define_insn "" ! 1144: [(set (pc) ! 1145: (if_then_else (lt (cc0) (const_int 0)) ! 1146: (pc) ! 1147: (label_ref (match_operand 0 "" ""))))] ! 1148: "" ! 1149: "* ! 1150: return (arm_output_asm_insn (\"bge\\t%l0\", operands)); ! 1151: ") ! 1152: ! 1153: (define_insn "" ! 1154: [(set (pc) ! 1155: (if_then_else (gtu (cc0) (const_int 0)) ! 1156: (pc) ! 1157: (label_ref (match_operand 0 "" ""))))] ! 1158: "" ! 1159: "* ! 1160: return (arm_output_asm_insn (\"bls\\t%l0\", operands)); ! 1161: ") ! 1162: ! 1163: (define_insn "" ! 1164: [(set (pc) ! 1165: (if_then_else (leu (cc0) (const_int 0)) ! 1166: (pc) ! 1167: (label_ref (match_operand 0 "" ""))))] ! 1168: "" ! 1169: "* ! 1170: return (arm_output_asm_insn (\"bhi\\t%l0\", operands)); ! 1171: ") ! 1172: ! 1173: (define_insn "" ! 1174: [(set (pc) ! 1175: (if_then_else (geu (cc0) (const_int 0)) ! 1176: (pc) ! 1177: (label_ref (match_operand 0 "" ""))))] ! 1178: "" ! 1179: "* ! 1180: return (arm_output_asm_insn (\"blo\\t%l0\", operands)); ! 1181: ") ! 1182: ! 1183: (define_insn "" ! 1184: [(set (pc) ! 1185: (if_then_else (ltu (cc0) (const_int 0)) ! 1186: (pc) ! 1187: (label_ref (match_operand 0 "" ""))))] ! 1188: "" ! 1189: "* ! 1190: return (arm_output_asm_insn (\"bhs\\t%l0\", operands)); ! 1191: ") ! 1192: ! 1193: ;; Jump and linkage insns ! 1194: ;; `return' is still a jump-to-epilogue... ! 1195: ! 1196: (define_insn "jump" ! 1197: [(set (pc) ! 1198: (label_ref (match_operand 0 "" "")))] ! 1199: "" ! 1200: "* ! 1201: return (arm_output_asm_insn (\"b\\t%l0\", operands)); ! 1202: ") ! 1203: ! 1204: (define_insn "call" ! 1205: [(call (match_operand 0 "memory_operand" "m") ! 1206: (match_operand 1 "general_operand" "g")) ! 1207: (clobber (reg:SI 14))] ! 1208: "" ! 1209: "* ! 1210: return (output_call (operands)); ! 1211: ") ! 1212: ! 1213: (define_insn "call_value" ! 1214: [(set (match_operand 0 "" "rf") ! 1215: (call (match_operand 1 "memory_operand" "m") ! 1216: (match_operand 2 "general_operand" "g"))) ! 1217: (clobber (reg:SI 14))] ! 1218: "" ! 1219: "* ! 1220: return (output_call (&operands[1])); ! 1221: ") ! 1222: ! 1223: ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses ! 1224: ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. ! 1225: ! 1226: (define_insn "" ! 1227: [(call (mem:SI (match_operand:SI 0 "" "i")) ! 1228: (match_operand:SI 1 "general_operand" "g")) ! 1229: (clobber (reg:SI 14))] ! 1230: "GET_CODE (operands[0]) == SYMBOL_REF" ! 1231: "* ! 1232: return (arm_output_asm_insn (\"bl\\t%a0\", operands)); ! 1233: ") ! 1234: ! 1235: (define_insn "" ! 1236: [(set (match_operand 0 "register_operand" "=rf") ! 1237: (call (mem:SI (match_operand:SI 1 "" "i")) ! 1238: (match_operand:SI 2 "general_operand" "g"))) ! 1239: (clobber (reg:SI 14))] ! 1240: "GET_CODE(operands[1]) == SYMBOL_REF" ! 1241: "* ! 1242: return (arm_output_asm_insn (\"bl\\t%a1\", operands)); ! 1243: ") ! 1244: ! 1245: (define_insn "tablejump" ! 1246: [(set (pc) ! 1247: (match_operand:SI 0 "register_operand" "r")) ! 1248: (use (label_ref (match_operand 1 "" "")))] ! 1249: "" ! 1250: "* ! 1251: return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ table jump, label %l1\", operands)); ! 1252: ") ! 1253: ! 1254: (define_insn "indirect_jump" ! 1255: [(set (pc) ! 1256: (match_operand:SI 0 "register_operand" "r"))] ! 1257: "" ! 1258: "* ! 1259: return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ indirect jump\", operands)); ! 1260: ") ! 1261: ! 1262: ;; Misc insns ! 1263: ! 1264: (define_insn "nop" ! 1265: [(const_int 0)] ! 1266: "" ! 1267: "* ! 1268: return (arm_output_asm_insn (\"mov\\tr0, r0\\t@ nop\", operands)); ! 1269: ") ! 1270: ! 1271: ;; Patterns to allow combination of arithmetic, cond code and shifts ! 1272: ! 1273: ;(define_insn "" ! 1274: ; [(set (match_operand:SI 0 "register_operand" "=r") ! 1275: ; (match_operator:SI 1 "shiftable_operator" ! 1276: ; [(match_operand:SI 2 "register_operand" "r") ! 1277: ; (match_operator:SI 3 "shift_operator" ! 1278: ; [(match_operand:SI 4 "register_operand" "r") ! 1279: ; (match_operand:SI 5 "nonmemory_operand" "rn")])]))] ! 1280: ; "" ! 1281: ; "* ! 1282: ; return (output_arithmetic_with_shift (operands, FALSE, FALSE)); ! 1283: ; " ! 1284: ;) ! 1285: ! 1286: ;(define_insn "" ! 1287: ; [(set (match_operand:SI 0 "register_operand" "=r") ! 1288: ; (match_operator:SI 1 "shiftable_operator" ! 1289: ; [(match_operator:SI 3 "shift_operator" ! 1290: ; [(match_operand:SI 4 "register_operand" "r") ! 1291: ; (match_operand:SI 5 "nonmemory_operand" "rI")]) ! 1292: ; (match_operand:SI 2 "register_operand" "r")]))] ! 1293: ; "" ! 1294: ; "* ! 1295: ; return (output_arithmetic_with_shift (operands, TRUE, FALSE)); ! 1296: ;") ! 1297: ! 1298: ;; Patterns to allow combination of arithmetic and multiplication ! 1299: ! 1300: ;(define_insn "" ! 1301: ; [(set (match_operand:SI 0 "register_operand" "=r") ! 1302: ; (match_operator:SI 1 "shiftable_operator" ! 1303: ; [(match_operand:SI 2 "register_operand" "r") ! 1304: ; (mult:SI ! 1305: ; (match_operand:SI 3 "register_operand" "r") ! 1306: ; (match_operand:SI 4 "power_of_two_operand" "n"))]))] ! 1307: ; "" ! 1308: ; "* ! 1309: ; return (output_arithmetic_with_immediate_multiply (operands, FALSE)); ! 1310: ;") ! 1311: ! 1312: ; Uncomment this to show combiner problem (see ../COMBINER-PROBLEM). ! 1313: ;(define_insn "" ! 1314: ; [(set (match_operand:SI 0 "register_operand" "=r") ! 1315: ; (match_operator:SI 1 "shiftable_operator" ! 1316: ; [(mult:SI ! 1317: ; (match_operand:SI 3 "register_operand" "r") ! 1318: ; (match_operand:SI 4 "power_of_two_operand" "n")) ! 1319: ; (match_operand:SI 2 "register_operand" "r")]))] ! 1320: ; "" ! 1321: ; "* ! 1322: ; return (output_arithmetic_with_immediate_multiply (operands, TRUE)); ! 1323: ;") ! 1324: ! 1325: ;; Peephole optimizations. ! 1326: ! 1327: ;; When testing a bitset smaller than 9 bits for (un)equality, a ! 1328: ;; shift/and/cmp/b{eq,ne} sequence can be replaced by one tst and the same ! 1329: ;; branch sequence. ! 1330: ! 1331: ;;(define_peephole ! 1332: ;; [(set (match_operand:SI 0 "register_operand" "=r") ! 1333: ;; (lshiftrt:SI (match_dup 0) ! 1334: ;; (match_operand 1 "immediate_operand" ""))) ! 1335: ;; (set (match_dup 0) ! 1336: ;; (and:SI (match_dup 0) ! 1337: ;; (match_operand 2 "immediate_operand" ""))) ! 1338: ;; (set (cc0) (match_dup 0)) ! 1339: ;; (set (pc) ! 1340: ;; (if_then_else (ne (cc0) (const_int 0)) ! 1341: ;; (label_ref (match_operand 3 "" "")) ! 1342: ;; (pc)))] ! 1343: ;; "dead_or_set_p (PREV_INSN (insn), operands[0]) ! 1344: ;; && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT ! 1345: ;; && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))" ! 1346: ;; "* ! 1347: ;; operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 1348: ;; INTVAL (operands[2]) << INTVAL (operands[1])); ! 1349: ;; arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands); ! 1350: ;; return (arm_output_asm_insn (\"bne\\t%l3\", operands)); ! 1351: ;;") ! 1352: ! 1353: ;;(define_peephole ! 1354: ;; [(set (match_operand:SI 0 "register_operand" "=r") ! 1355: ;; (lshiftrt:SI (match_dup 0) ! 1356: ;; (match_operand 1 "immediate_operand" ""))) ! 1357: ;; (set (match_dup 0) ! 1358: ;; (and:SI (match_dup 0) ! 1359: ;; (match_operand 2 "immediate_operand" ""))) ! 1360: ;; (set (cc0) (match_dup 0)) ! 1361: ;; (set (pc) ! 1362: ;; (if_then_else (ne (cc0) (const_int 0)) ! 1363: ;; (pc) ! 1364: ;; (label_ref (match_operand 3 "" ""))))] ! 1365: ;; "dead_or_set_p (prev_real_insn (insn), operands[0]) ! 1366: ;; && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT ! 1367: ;; && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))" ! 1368: ;; "* ! 1369: ;; operands[2] = gen_rtx (CONST_INT, VOIDmode, ! 1370: ;; INTVAL (operands[2]) << INTVAL (operands[1])); ! 1371: ;; arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands); ! 1372: ;; return (arm_output_asm_insn (\"beq\\t%l3\", operands)); ! 1373: ;;") ! 1374: ! 1375: ;; This allows negative constants to be compared since GCC appears not to try ! 1376: ;; converting them with a NEG. ! 1377: ! 1378: ;;(define_peephole ! 1379: ;; [(set (match_operand:SI 2 "register_operand" "=r") ! 1380: ;; (match_operand:SI 1 "immediate_operand" "n")) ! 1381: ;; (set (cc0) ! 1382: ;; (compare (match_operand:SI 0 "register_operand" "r") ! 1383: ;; (match_dup 1)))] ! 1384: ;; "const_ok_for_arm (-INTVAL (operands[1])) ! 1385: ;; && dead_or_set_p (prev_real_insn (insn), operands[0])" ! 1386: ;; "* ! 1387: ;; operands[1] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1])); ! 1388: ;; return (arm_output_asm_insn (\"cmn\\t%0, %1\\t\\t@ ph negate comparison\", operands)); ! 1389: ;;") ! 1390: ! 1391: ;; Local variables: ! 1392: ;; mode:emacs-lisp ! 1393: ;; eval: (setq comment-start ";; ") ! 1394: ;; eval: (setq comment-end "") ! 1395: ;; eval: (setq comment-start-skip ";;+ *") ! 1396: ;; eval: (set-syntax-table (copy-sequence (syntax-table))) ! 1397: ;; eval: (modify-syntax-entry ?[ "(]") ! 1398: ;; eval: (modify-syntax-entry ?] ")[") ! 1399: ;; eval: (modify-syntax-entry ?{ "(}") ! 1400: ;; eval: (modify-syntax-entry ?} "){") ! 1401: ;; End:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.