1;; Machine description for OpenRISC 2;; Copyright (C) 2018-2020 Free Software Foundation, Inc. 3;; Contributed by Stafford Horne 4 5;; This file is part of GCC. 6 7;; GCC is free software; you can redistribute it and/or modify it 8;; under the terms of the GNU General Public License as published 9;; by the Free Software Foundation; either version 3, or (at your 10;; option) any later version. 11 12;; GCC is distributed in the hope that it will be useful, but WITHOUT 13;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15;; License for more details. 16 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21;; ------------------------------------------------------------------------- 22;; OpenRISC specific constraints, predicates and attributes 23;; ------------------------------------------------------------------------- 24 25(include "constraints.md") 26(include "predicates.md") 27 28;; Register numbers 29(define_constants 30 [(SP_REGNUM 1) 31 (HFP_REGNUM 2) 32 (LR_REGNUM 9) 33 (TLS_REGNUM 10) 34 (RV_REGNUM 11) 35 (PE_TMP_REGNUM 13) 36 (AP_REGNUM 32) 37 (SFP_REGNUM 33) 38 (SR_F_REGNUM 34)] 39) 40 41(define_c_enum "unspec" [ 42 UNSPEC_SET_GOT 43 UNSPEC_GOT 44 UNSPEC_GOTOFF 45 UNSPEC_TPOFF 46 UNSPEC_GOTTPOFF 47 UNSPEC_TLSGD 48 UNSPEC_MSYNC 49]) 50 51(define_c_enum "unspecv" [ 52 UNSPECV_SET_GOT 53 UNSPECV_LL 54 UNSPECV_SC 55]) 56 57;; Instruction scheduler 58 59; Most instructions are 4 bytes long. 60(define_attr "length" "" (const_int 4)) 61 62(define_attr "type" 63 "alu,st,ld,control,multi,fpu" 64 (const_string "alu")) 65 66(define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1")) 67 68(define_attr "enabled" "" 69 (cond [(eq_attr "insn_support" "class1") (const_int 1) 70 (and (eq_attr "insn_support" "sext") 71 (ne (symbol_ref "TARGET_SEXT") (const_int 0))) (const_int 1) 72 (and (eq_attr "insn_support" "sfimm") 73 (ne (symbol_ref "TARGET_SFIMM") (const_int 0))) (const_int 1) 74 (and (eq_attr "insn_support" "shftimm") 75 (ne (symbol_ref "TARGET_SHFTIMM") (const_int 0))) (const_int 1) 76 (and (eq_attr "insn_support" "ror") 77 (ne (symbol_ref "TARGET_ROR") (const_int 0))) (const_int 1) 78 (and (eq_attr "insn_support" "rori") 79 (ne (symbol_ref "TARGET_RORI") (const_int 0))) (const_int 1)] 80 (const_int 0))) 81 82;; Describe a user's asm statement. 83(define_asm_attributes 84 [(set_attr "type" "multi")]) 85 86(define_automaton "or1k") 87(define_cpu_unit "cpu" "or1k") 88(define_insn_reservation "alu" 1 89 (eq_attr "type" "alu") 90 "cpu") 91(define_insn_reservation "st" 1 92 (eq_attr "type" "st") 93 "cpu") 94(define_insn_reservation "ld" 3 95 (eq_attr "type" "st") 96 "cpu") 97(define_insn_reservation "control" 1 98 (eq_attr "type" "control") 99 "cpu") 100(define_insn_reservation "fpu" 2 101 (eq_attr "type" "fpu") 102 "cpu") 103 104 105; Define delay slots for any branch 106(define_delay (eq_attr "type" "control") 107 [(eq_attr "type" "alu,st,ld") (nil) (nil)]) 108 109;; ------------------------------------------------------------------------- 110;; nop instruction 111;; ------------------------------------------------------------------------- 112 113(define_insn "nop" 114 [(const_int 0)] 115 "" 116 "l.nop") 117 118;; ------------------------------------------------------------------------- 119;; Arithmetic instructions 120;; ------------------------------------------------------------------------- 121 122(define_insn "addsi3" 123 [(set (match_operand:SI 0 "register_operand" "=r,r") 124 (plus:SI 125 (match_operand:SI 1 "register_operand" "%r,r") 126 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))] 127 "" 128 "@ 129 l.add\t%0, %1, %2 130 l.addi\t%0, %1, %2") 131 132(define_insn "mulsi3" 133 [(set (match_operand:SI 0 "register_operand" "=r,r") 134 (mult:SI 135 (match_operand:SI 1 "register_operand" "%r,r") 136 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))] 137 "!TARGET_SOFT_MUL" 138 "@ 139 l.mul\t%0, %1, %2 140 l.muli\t%0, %1, %2") 141 142(define_insn "divsi3" 143 [(set (match_operand:SI 0 "register_operand" "=r") 144 (div:SI 145 (match_operand:SI 1 "register_operand" "r") 146 (match_operand:SI 2 "register_operand" "r")))] 147 "!TARGET_SOFT_DIV" 148 "l.div\t%0, %1, %2") 149 150(define_insn "udivsi3" 151 [(set (match_operand:SI 0 "register_operand" "=r") 152 (udiv:SI 153 (match_operand:SI 1 "register_operand" "r") 154 (match_operand:SI 2 "register_operand" "r")))] 155 "!TARGET_SOFT_DIV" 156 "l.divu\t%0, %1, %2") 157 158(define_insn "subsi3" 159 [(set (match_operand:SI 0 "register_operand" "=r") 160 (minus:SI 161 (match_operand:SI 1 "reg_or_0_operand" "rO") 162 (match_operand:SI 2 "register_operand" "r")))] 163 "" 164 "l.sub\t%0, %r1, %2") 165 166;; ------------------------------------------------------------------------- 167;; Floating Point Arithmetic instructions 168;; ------------------------------------------------------------------------- 169 170;; Mode iterator for single/double float 171(define_mode_iterator F [(SF "TARGET_HARD_FLOAT") 172 (DF "TARGET_DOUBLE_FLOAT")]) 173(define_mode_attr f [(SF "s") (DF "d")]) 174(define_mode_attr fr [(SF "r") (DF "d")]) 175(define_mode_attr fi [(SF "si") (DF "di")]) 176(define_mode_attr FI [(SF "SI") (DF "DI")]) 177 178;; Basic arithmetic instructions 179(define_code_iterator FOP [plus minus mult div]) 180(define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")]) 181 182(define_insn "<fop><F:mode>3" 183 [(set (match_operand:F 0 "register_operand" "=<fr>") 184 (FOP:F (match_operand:F 1 "register_operand" "<fr>") 185 (match_operand:F 2 "register_operand" "<fr>")))] 186 "TARGET_HARD_FLOAT" 187 "lf.<fop>.<f>\t%d0, %d1, %d2" 188 [(set_attr "type" "fpu")]) 189 190;; Basic float<->int conversion 191(define_insn "float<fi><F:mode>2" 192 [(set (match_operand:F 0 "register_operand" "=<fr>") 193 (float:F 194 (match_operand:<FI> 1 "register_operand" "<fr>")))] 195 "TARGET_HARD_FLOAT" 196 "lf.itof.<f>\t%d0, %d1" 197 [(set_attr "type" "fpu")]) 198 199(define_insn "fix_trunc<F:mode><fi>2" 200 [(set (match_operand:<FI> 0 "register_operand" "=<fr>") 201 (fix:<FI> 202 (match_operand:F 1 "register_operand" "<fr>")))] 203 "TARGET_HARD_FLOAT" 204 "lf.ftoi.<f>\t%d0, %d1" 205 [(set_attr "type" "fpu")]) 206 207;; ------------------------------------------------------------------------- 208;; Logical operators 209;; ------------------------------------------------------------------------- 210 211(define_code_iterator SHIFT [ashift ashiftrt lshiftrt]) 212(define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr") 213 (lshiftrt "lshr")]) 214(define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra") 215 (lshiftrt "srl")]) 216 217(define_insn "<shift_op>si3" 218 [(set (match_operand:SI 0 "register_operand" "=r,r") 219 (SHIFT:SI (match_operand:SI 1 "register_operand" "r,r") 220 (match_operand:SI 2 "reg_or_u6_operand" "r,n")))] 221 "" 222 "@ 223 l.<shift_asm>\t%0, %1, %2 224 l.<shift_asm>i\t%0, %1, %2" 225 [(set_attr "insn_support" "*,shftimm")]) 226 227(define_insn "rotrsi3" 228 [(set (match_operand:SI 0 "register_operand" "=r,r") 229 (rotatert:SI (match_operand:SI 1 "register_operand" "r,r") 230 (match_operand:SI 2 "ror_reg_or_u6_operand" "r,n")))] 231 "TARGET_ROR || TARGET_RORI" 232 "@ 233 l.ror\t%0, %1, %2 234 l.rori\t%0, %1, %2" 235 [(set_attr "insn_support" "ror,rori")]) 236 237(define_insn "andsi3" 238 [(set (match_operand:SI 0 "register_operand" "=r,r") 239 (and:SI 240 (match_operand:SI 1 "register_operand" "%r,r") 241 (match_operand:SI 2 "reg_or_u16_operand" " r,K")))] 242 "" 243 "@ 244 l.and\t%0, %1, %2 245 l.andi\t%0, %1, %2") 246 247(define_insn "xorsi3" 248 [(set (match_operand:SI 0 "register_operand" "=r,r") 249 (xor:SI 250 (match_operand:SI 1 "register_operand" "%r,r") 251 (match_operand:SI 2 "reg_or_s16_operand" " r,I")))] 252 "" 253 "@ 254 l.xor\t%0, %1, %2 255 l.xori\t%0, %1, %2") 256 257(define_insn "iorsi3" 258 [(set (match_operand:SI 0 "register_operand" "=r,r") 259 (ior:SI 260 (match_operand:SI 1 "register_operand" "%r,r") 261 (match_operand:SI 2 "reg_or_u16_operand" " r,K")))] 262 "" 263 "@ 264 l.or\t%0, %1, %2 265 l.ori\t%0, %1, %2") 266 267(define_expand "one_cmplsi2" 268 [(set (match_operand:SI 0 "register_operand" "") 269 (xor:SI (match_operand:SI 1 "register_operand" "") (const_int -1)))] 270 "" 271 "") 272 273;; ------------------------------------------------------------------------- 274;; Move instructions 275;; ------------------------------------------------------------------------- 276 277(define_mode_iterator I [QI HI SI]) 278(define_mode_iterator I12 [QI HI]) 279 280(define_mode_attr ldst [(QI "b") (HI "h") (SI "w")]) 281(define_mode_attr zext_andi [(QI "0xff") (HI "0xffff")]) 282 283(define_expand "mov<I:mode>" 284 [(set (match_operand:I 0 "nonimmediate_operand" "") 285 (match_operand:I 1 "general_operand" ""))] 286 "" 287{ 288 or1k_expand_move (<MODE>mode, operands[0], operands[1]); 289 DONE; 290}) 291 292;; 8-bit, 16-bit and 32-bit moves 293 294(define_insn "*mov<I:mode>_internal" 295 [(set (match_operand:I 0 "nonimmediate_operand" "=r,r,r,r, m,r") 296 (match_operand:I 1 "input_operand" " r,M,K,I,rO,m"))] 297 "register_operand (operands[0], <I:MODE>mode) 298 || reg_or_0_operand (operands[1], <I:MODE>mode)" 299 "@ 300 l.or\t%0, %1, %1 301 l.movhi\t%0, hi(%1) 302 l.ori\t%0, r0, %1 303 l.xori\t%0, r0, %1 304 l.s<I:ldst>\t%0, %r1 305 l.l<I:ldst>z\t%0, %1" 306 [(set_attr "type" "alu,alu,alu,alu,st,ld")]) 307 308;; Hi/Low moves for constant and symbol loading 309 310(define_insn "movsi_high" 311 [(set (match_operand:SI 0 "register_operand" "=r") 312 (high:SI (match_operand:SI 1 "high_operand" "")))] 313 "" 314 "l.movhi\t%0, %h1" 315 [(set_attr "type" "alu")]) 316 317(define_insn "*movsi_lo_sum_iori" 318 [(set (match_operand:SI 0 "register_operand" "=r") 319 (lo_sum:SI (match_operand:SI 1 "register_operand" "r") 320 (match_operand:SI 2 "losum_ior_operand" "")))] 321 "" 322 "l.ori\t%0, %1, %L2" 323 [(set_attr "type" "alu")]) 324 325(define_insn "*movsi_lo_sum_addi" 326 [(set (match_operand:SI 0 "register_operand" "=r") 327 (lo_sum:SI (match_operand:SI 1 "register_operand" "r") 328 (match_operand:SI 2 "losum_add_operand" "")))] 329 "" 330 "l.addi\t%0, %1, %L2" 331 [(set_attr "type" "alu")]) 332 333;; 64-bit moves 334;; ??? The clobber that emit_move_multi_word emits is arguably incorrect. 335;; Consider gcc.c-torture/execute/20030222-1.c, where a reg-reg DImode 336;; move gets register allocated to a no-op move. At which point the 337;; we actively clobber the input. 338 339(define_expand "movdi" 340 [(set (match_operand:DI 0 "nonimmediate_operand" "") 341 (match_operand:DI 1 "general_operand" ""))] 342 "" 343{ 344 if (MEM_P (operands[0]) && !const0_operand(operands[1], DImode)) 345 operands[1] = force_reg (DImode, operands[1]); 346}) 347 348(define_insn_and_split "*movdi" 349 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,o,r") 350 (match_operand:DI 1 "general_operand" " r,o,rO,n"))] 351 "register_operand (operands[0], DImode) 352 || reg_or_0_operand (operands[1], DImode)" 353 "#" 354 "" 355 [(const_int 0)] 356{ 357 rtx l0 = operand_subword (operands[0], 0, 0, DImode); 358 rtx l1 = operand_subword (operands[1], 0, 0, DImode); 359 rtx h0 = operand_subword (operands[0], 1, 0, DImode); 360 rtx h1 = operand_subword (operands[1], 1, 0, DImode); 361 362 if (reload_completed && reg_overlap_mentioned_p (l0, h1)) 363 { 364 gcc_assert (!reg_overlap_mentioned_p (h0, l1)); 365 emit_move_insn (h0, h1); 366 emit_move_insn (l0, l1); 367 } 368 else 369 { 370 emit_move_insn (l0, l1); 371 emit_move_insn (h0, h1); 372 } 373 DONE; 374}) 375 376;; ------------------------------------------------------------------------- 377;; Sign Extending 378;; ------------------------------------------------------------------------- 379 380;; Zero extension can always be done with AND or an extending load. 381 382(define_insn "zero_extend<mode>si2" 383 [(set (match_operand:SI 0 "register_operand" "=r,r") 384 (zero_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))] 385 "" 386 "@ 387 l.andi\t%0, %1, <zext_andi> 388 l.l<ldst>z\t%0, %1") 389 390;; Sign extension in registers is an optional extension, but the 391;; extending load is always available. If SEXT is not available, 392;; force the middle-end to do the expansion to shifts. 393 394(define_insn "extend<mode>si2" 395 [(set (match_operand:SI 0 "register_operand" "=r,r") 396 (sign_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))] 397 "TARGET_SEXT" 398 "@ 399 l.ext<ldst>s\t%0, %1 400 l.l<ldst>s\t%0, %1") 401 402(define_insn "*extend<mode>si2_mem" 403 [(set (match_operand:SI 0 "register_operand" "=r") 404 (sign_extend:SI (match_operand:I12 1 "memory_operand" "m")))] 405 "" 406 "l.l<ldst>s\t%0, %1") 407 408;; ------------------------------------------------------------------------- 409;; Compare instructions 410;; ------------------------------------------------------------------------- 411 412;; OpenRISC supports these integer comparisons: 413;; 414;; l.sfeq[i] - equality, r r or r i 415;; l.sfne[i] - not equal, r r or r i 416;; l.sflt{s,u}[i] - less than, signed or unsigned, r r or r i 417;; l.sfle{s,u}[i] - less than or equal, signed or unsigned, r r or r i 418;; l.sfgt{s,u}[i] - greater than, signed or unsigned, r r or r i 419;; l.sfge{s,u}[i] - greater than or equal, signed or unsigned, r r or r i 420;; 421;; EQ,NE,LT,LTU,LE,LEU,GT,GTU,GE,GEU 422;; We iterate through all of these 423;; 424 425(define_code_iterator intcmpcc [ne eq lt ltu gt gtu ge le geu leu]) 426(define_code_attr insn [(ne "ne") (eq "eq") (lt "lts") (ltu "ltu") 427 (gt "gts") (gtu "gtu") (ge "ges") (le "les") 428 (geu "geu") (leu "leu")]) 429 430(define_insn "*sf_insn" 431 [(set (reg:BI SR_F_REGNUM) 432 (intcmpcc:BI (match_operand:SI 0 "reg_or_0_operand" "rO,rO") 433 (match_operand:SI 1 "reg_or_s16_operand" "r,I")))] 434 "" 435 "@ 436 l.sf<insn>\t%r0, %1 437 l.sf<insn>i\t%r0, %1" 438 [(set_attr "insn_support" "*,sfimm")]) 439 440;; Support FP comparisons too 441 442;; The OpenRISC FPU supports these comparisons: 443;; 444;; lf.sfeq.{d,s} - equality, r r, double or single precision 445;; lf.sfge.{d,s} - greater than or equal, r r, double or single precision 446;; lf.sfgt.{d,s} - greater than, r r, double or single precision 447;; lf.sfle.{d,s} - less than or equal, r r, double or single precision 448;; lf.sflt.{d,s} - less than, r r, double or single precision 449;; lf.sfne.{d,s} - not equal, r r, double or single precision 450;; 451;; Double precision is only supported on some hardware. Only register/register 452;; comparisons are supported. All comparisons are signed. 453 454(define_code_iterator fpcmpcc [ne eq lt gt ge le uneq unle unlt ungt unge 455 unordered]) 456(define_code_attr fpcmpinsn [(ne "ne") (eq "eq") (lt "lt") (gt "gt") (ge "ge") 457 (le "le") (uneq "ueq") (unle "ule") (unlt "ult") 458 (ungt "ugt") (unge "uge") (unordered "un")]) 459 460 461(define_insn "*sf_fp_insn" 462 [(set (reg:BI SR_F_REGNUM) 463 (fpcmpcc:BI (match_operand:F 0 "register_operand" "<fr>") 464 (match_operand:F 1 "register_operand" "<fr>")))] 465 "TARGET_HARD_FLOAT" 466 "lf.sf<fpcmpinsn>.<f>\t%d0, %d1" 467 [(set_attr "type" "fpu")]) 468 469 470;; ------------------------------------------------------------------------- 471;; Conditional Store instructions 472;; ------------------------------------------------------------------------- 473 474(define_expand "cstoresi4" 475 [(set (match_operand:SI 0 "register_operand" "") 476 (if_then_else:SI 477 (match_operator 1 "comparison_operator" 478 [(match_operand:SI 2 "reg_or_0_operand" "") 479 (match_operand:SI 3 "reg_or_s16_operand" "")]) 480 (match_dup 0) 481 (const_int 0)))] 482 "" 483{ 484 or1k_expand_compare (operands + 1); 485 PUT_MODE (operands[1], SImode); 486 emit_insn (gen_rtx_SET (operands[0], operands[1])); 487 DONE; 488}) 489 490;; Support FP cstores too 491(define_expand "cstore<F:mode>4" 492 [(set (match_operand:SI 0 "register_operand" "") 493 (if_then_else:F 494 (match_operator 1 "fp_comparison_operator" 495 [(match_operand:F 2 "register_operand" "") 496 (match_operand:F 3 "register_operand" "")]) 497 (match_dup 0) 498 (const_int 0)))] 499 "TARGET_HARD_FLOAT" 500{ 501 or1k_expand_compare (operands + 1); 502 PUT_MODE (operands[1], SImode); 503 emit_insn (gen_rtx_SET (operands[0], operands[1])); 504 DONE; 505}) 506 507;; Being able to "copy" SR_F to a general register is helpful for 508;; the atomic insns, wherein the usual usage is to test the success 509;; of the compare-and-swap. Representing the operation in this way, 510;; rather than exposing the cmov immediately, allows the optimizers 511;; to propagate the use of SR_F directly into a branch. 512 513(define_expand "sne_sr_f" 514 [(set (match_operand:SI 0 "register_operand" "=r") 515 (ne:SI (reg:BI SR_F_REGNUM) (const_int 0)))] 516 "") 517 518(define_insn_and_split "*scc" 519 [(set (match_operand:SI 0 "register_operand" "=r") 520 (match_operator:SI 1 "equality_comparison_operator" 521 [(reg:BI SR_F_REGNUM) (const_int 0)]))] 522 "" 523 "#" 524 "reload_completed" 525 [(set (match_dup 0) (const_int 1)) 526 (set (match_dup 0) 527 (if_then_else:SI (match_dup 1) 528 (match_dup 0) 529 (const_int 0)))] 530 "") 531 532(define_expand "mov<I:mode>cc" 533 [(set (match_operand:I 0 "register_operand" "") 534 (if_then_else:I (match_operand 1 "comparison_operator" "") 535 (match_operand:I 2 "reg_or_0_operand" "") 536 (match_operand:I 3 "reg_or_0_operand" "")))] 537 "" 538{ 539 rtx xops[3] = { operands[1], XEXP (operands[1], 0), XEXP (operands[1], 1) }; 540 or1k_expand_compare (xops); 541 operands[1] = xops[0]; 542}) 543 544(define_insn_and_split "*cmov<I:mode>" 545 [(set (match_operand:I 0 "register_operand" "=r") 546 (if_then_else:I 547 (match_operator 3 "equality_comparison_operator" 548 [(reg:BI SR_F_REGNUM) (const_int 0)]) 549 (match_operand:I 1 "reg_or_0_operand" "rO") 550 (match_operand:I 2 "reg_or_0_operand" "rO")))] 551 "" 552{ 553 return (GET_CODE (operands[3]) == NE 554 ? "l.cmov\t%0, %r1, %r2" 555 : "l.cmov\t%0, %r2, %r1"); 556} 557 "!TARGET_CMOV" 558 [(const_int 0)] 559{ 560 rtx x; 561 rtx label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ()); 562 563 /* Generated a *cbranch pattern. */ 564 if (rtx_equal_p (operands[0], operands[2])) 565 { 566 PUT_CODE (operands[3], (GET_CODE (operands[3]) == NE) ? EQ : NE); 567 x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx); 568 emit_jump_insn (gen_rtx_SET (pc_rtx, x)); 569 emit_move_insn (operands[0], operands[1]); 570 } 571 else 572 { 573 x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx); 574 emit_move_insn (operands[0], operands[1]); 575 emit_jump_insn (gen_rtx_SET (pc_rtx, x)); 576 emit_move_insn (operands[0], operands[2]); 577 } 578 579 emit_label (XEXP (label, 0)); 580 DONE; 581}) 582 583;; ------------------------------------------------------------------------- 584;; Branch instructions 585;; ------------------------------------------------------------------------- 586 587(define_expand "cbranchsi4" 588 [(set (pc) 589 (if_then_else 590 (match_operator 0 "comparison_operator" 591 [(match_operand:SI 1 "reg_or_0_operand" "") 592 (match_operand:SI 2 "reg_or_s16_operand" "")]) 593 (label_ref (match_operand 3 "" "")) 594 (pc)))] 595 "" 596{ 597 or1k_expand_compare (operands); 598}) 599 600;; Support FP branching 601 602(define_expand "cbranch<F:mode>4" 603 [(set (pc) 604 (if_then_else 605 (match_operator 0 "fp_comparison_operator" 606 [(match_operand:F 1 "register_operand" "") 607 (match_operand:F 2 "register_operand" "")]) 608 (label_ref (match_operand 3 "" "")) 609 (pc)))] 610 "TARGET_HARD_FLOAT" 611{ 612 or1k_expand_compare (operands); 613}) 614 615(define_insn "*cbranch" 616 [(set (pc) 617 (if_then_else 618 (match_operator 1 "equality_comparison_operator" 619 [(reg:BI SR_F_REGNUM) (const_int 0)]) 620 (label_ref (match_operand 0 "" "")) 621 (pc)))] 622 "" 623{ 624 return (GET_CODE (operands[1]) == NE 625 ? "l.bf\t%0%#" 626 : "l.bnf\t%0%#"); 627} 628 [(set_attr "type" "control")]) 629 630;; ------------------------------------------------------------------------- 631;; Jump instructions 632;; ------------------------------------------------------------------------- 633 634(define_insn "jump" 635 [(set (pc) (label_ref (match_operand 0 "" "")))] 636 "" 637 "l.j\t%0%#" 638 [(set_attr "type" "control")]) 639 640(define_insn "indirect_jump" 641 [(set (pc) (match_operand:SI 0 "register_operand" "r"))] 642 "" 643 "l.jr\t%0%#" 644 [(set_attr "type" "control")]) 645 646;; ------------------------------------------------------------------------- 647;; Prologue & Epilogue 648;; ------------------------------------------------------------------------- 649 650(define_expand "prologue" 651 [(const_int 1)] 652 "" 653{ 654 or1k_expand_prologue (); 655 DONE; 656}) 657 658;; Expand epilogue as RTL 659(define_expand "epilogue" 660 [(return)] 661 "" 662{ 663 or1k_expand_epilogue (); 664 emit_jump_insn (gen_simple_return ()); 665 DONE; 666}) 667 668(define_expand "sibcall_epilogue" 669 [(return)] 670 "" 671{ 672 or1k_expand_epilogue (); 673 /* Placing a USE of LR here, rather than as a REG_USE on the 674 sibcall itself, means that LR is not unnecessarily live 675 within the function itself, which would force creation of 676 a stack frame. */ 677 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM))); 678 DONE; 679}) 680 681(define_expand "simple_return" 682 [(parallel [(simple_return) (use (match_dup 0))])] 683 "" 684{ 685 operands[0] = gen_rtx_REG (Pmode, LR_REGNUM); 686}) 687 688(define_insn "*simple_return" 689 [(simple_return) 690 (use (match_operand:SI 0 "register_operand" "r"))] 691 "" 692 "l.jr\t%0%#" 693 [(set_attr "type" "control")]) 694 695(define_expand "eh_return" 696 [(use (match_operand 0 "general_operand"))] 697 "" 698{ 699 or1k_expand_eh_return (operands[0]); 700 DONE; 701}) 702 703;; This is a placeholder, during RA, in order to create the PIC regiter. 704;; We do this so that we don't unconditionally mark the LR register as 705;; clobbered. It is replaced during prologue generation with the proper 706;; set_got pattern below. This works because the set_got_tmp insn is the 707;; first insn in the stream and that it isn't moved during RA. 708(define_insn "set_got_tmp" 709 [(set (match_operand:SI 0 "register_operand" "=t") 710 (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_GOT))] 711 "" 712{ 713 gcc_unreachable (); 714}) 715 716;; The insn to initialize the GOT. 717(define_insn "set_got" 718 [(set (match_operand:SI 0 "register_operand" "=t") 719 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) 720 (clobber (reg:SI LR_REGNUM))] 721 "" 722{ 723 return ("l.jal\t8\;" 724 " l.movhi\t%0, gotpchi(_GLOBAL_OFFSET_TABLE_-4)\;" 725 "l.ori\t%0, %0, gotpclo(_GLOBAL_OFFSET_TABLE_+0)\;" 726 "l.add\t%0, %0, r9"); 727} 728 [(set_attr "length" "16") 729 (set_attr "type" "multi")]) 730 731;; Block memory operations from being scheduled across frame (de)allocation. 732(define_insn "frame_addsi3" 733 [(set (match_operand:SI 0 "register_operand" "=r,r") 734 (plus:SI 735 (match_operand:SI 1 "register_operand" "%r,r") 736 (match_operand:SI 2 "reg_or_s16_operand" " r,I"))) 737 (clobber (mem:BLK (scratch)))] 738 "reload_completed" 739 "@ 740 l.add\t%0, %1, %2 741 l.addi\t%0, %1, %2") 742 743;; ------------------------------------------------------------------------- 744;; Atomic Operations 745;; ------------------------------------------------------------------------- 746 747;; Note that MULT stands in for the non-existant NAND rtx_code. 748(define_code_iterator FETCHOP [plus minus ior xor and mult]) 749 750(define_code_attr fetchop_name 751 [(plus "add") 752 (minus "sub") 753 (ior "or") 754 (xor "xor") 755 (and "and") 756 (mult "nand")]) 757 758(define_code_attr fetchop_pred 759 [(plus "reg_or_s16_operand") 760 (minus "register_operand") 761 (ior "reg_or_u16_operand") 762 (xor "reg_or_s16_operand") 763 (and "reg_or_u16_operand") 764 (mult "reg_or_u16_operand")]) 765 766(define_expand "mem_thread_fence" 767 [(match_operand:SI 0 "const_int_operand" "")] ;; model 768 "" 769{ 770 memmodel model = memmodel_base (INTVAL (operands[0])); 771 if (model != MEMMODEL_RELAXED) 772 emit_insn (gen_msync ()); 773 DONE; 774}) 775 776(define_expand "msync" 777 [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))] 778 "" 779{ 780 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 781 MEM_VOLATILE_P (operands[0]) = 1; 782}) 783 784(define_insn "*msync" 785 [(set (match_operand:BLK 0 "" "") 786 (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))] 787 "" 788 "l.msync") 789 790(define_insn "load_locked_si" 791 [(set (match_operand:SI 0 "register_operand" "=r") 792 (unspec_volatile:SI 793 [(match_operand:SI 1 "memory_operand" "m")] UNSPECV_LL))] 794 "" 795 "l.lwa\t%0,%1" 796 [(set_attr "type" "ld")]) 797 798(define_insn "store_conditional_si" 799 [(set (reg:BI SR_F_REGNUM) 800 (unspec_volatile:BI [(const_int 0)] UNSPECV_SC)) 801 (set (match_operand:SI 0 "memory_operand" "=m") 802 (match_operand:SI 1 "reg_or_0_operand" "rO"))] 803 "" 804 "l.swa\t%0,%r1" 805 [(set_attr "type" "st")]) 806 807(define_expand "atomic_compare_and_swapsi" 808 [(match_operand:SI 0 "register_operand") ;; bool output 809 (match_operand:SI 1 "register_operand") ;; val output 810 (match_operand:SI 2 "memory_operand") ;; memory 811 (match_operand:SI 3 "reg_or_s16_operand") ;; expected 812 (match_operand:SI 4 "reg_or_0_operand") ;; desired 813 (match_operand:SI 5 "const_int_operand") ;; is_weak 814 (match_operand:SI 6 "const_int_operand") ;; mod_s 815 (match_operand:SI 7 "const_int_operand")] ;; mod_f 816 "" 817{ 818 or1k_expand_atomic_compare_and_swap (operands); 819 DONE; 820}) 821 822(define_expand "atomic_compare_and_swap<mode>" 823 [(match_operand:SI 0 "register_operand") ;; bool output 824 (match_operand:I12 1 "register_operand") ;; val output 825 (match_operand:I12 2 "memory_operand") ;; memory 826 (match_operand:I12 3 "register_operand") ;; expected 827 (match_operand:I12 4 "reg_or_0_operand") ;; desired 828 (match_operand:SI 5 "const_int_operand") ;; is_weak 829 (match_operand:SI 6 "const_int_operand") ;; mod_s 830 (match_operand:SI 7 "const_int_operand")] ;; mod_f 831 "" 832{ 833 or1k_expand_atomic_compare_and_swap_qihi (operands); 834 DONE; 835}) 836 837(define_expand "atomic_exchangesi" 838 [(match_operand:SI 0 "register_operand") ;; output 839 (match_operand:SI 1 "memory_operand") ;; memory 840 (match_operand:SI 2 "reg_or_0_operand") ;; input 841 (match_operand:SI 3 "const_int_operand")] ;; model 842 "" 843{ 844 or1k_expand_atomic_exchange (operands); 845 DONE; 846}) 847 848(define_expand "atomic_exchange<mode>" 849 [(match_operand:I12 0 "register_operand") ;; output 850 (match_operand:I12 1 "memory_operand") ;; memory 851 (match_operand:I12 2 "reg_or_0_operand") ;; input 852 (match_operand:SI 3 "const_int_operand")] ;; model 853 "" 854{ 855 or1k_expand_atomic_exchange_qihi (operands); 856 DONE; 857}) 858 859(define_expand "atomic_<fetchop_name>si" 860 [(match_operand:SI 0 "memory_operand") ;; memory 861 (FETCHOP:SI (match_dup 0) 862 (match_operand:SI 1 "<fetchop_pred>")) ;; operand 863 (match_operand:SI 2 "const_int_operand")] ;; model 864 "" 865{ 866 or1k_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL); 867 DONE; 868}) 869 870(define_expand "atomic_<fetchop_name><mode>" 871 [(match_operand:I12 0 "memory_operand") ;; memory 872 (FETCHOP:I12 (match_dup 0) 873 (match_operand:I12 1 "register_operand")) ;; operand 874 (match_operand:SI 2 "const_int_operand")] ;; model 875 "" 876{ 877 or1k_expand_atomic_op_qihi (<CODE>, operands[0], operands[1], NULL, NULL); 878 DONE; 879}) 880 881(define_expand "atomic_fetch_<fetchop_name>si" 882 [(match_operand:SI 0 "register_operand" "") ;; output 883 (match_operand:SI 1 "memory_operand" "") ;; memory 884 (FETCHOP:SI (match_dup 1) 885 (match_operand:SI 2 "<fetchop_pred>" "")) ;; operand 886 (match_operand:SI 3 "const_int_operand" "")] ;; model 887 "" 888{ 889 or1k_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL); 890 DONE; 891}) 892 893(define_expand "atomic_fetch_<fetchop_name><mode>" 894 [(match_operand:I12 0 "register_operand" "") ;; output 895 (match_operand:I12 1 "memory_operand" "") ;; memory 896 (FETCHOP:I12 (match_dup 1) 897 (match_operand:I12 2 "<fetchop_pred>" "")) ;; operand 898 (match_operand:SI 3 "const_int_operand" "")] ;; model 899 "" 900{ 901 or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2], 902 operands[0], NULL); 903 DONE; 904}) 905 906(define_expand "atomic_<fetchop_name>_fetchsi" 907 [(match_operand:SI 0 "register_operand" "") ;; output 908 (match_operand:SI 1 "memory_operand" "") ;; memory 909 (FETCHOP:SI (match_dup 1) 910 (match_operand:SI 2 "<fetchop_pred>" "")) ;; operand 911 (match_operand:SI 3 "const_int_operand" "")] ;; model 912 "" 913{ 914 or1k_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]); 915 DONE; 916}) 917 918(define_expand "atomic_<fetchop_name>_fetch<mode>" 919 [(match_operand:I12 0 "register_operand" "") ;; output 920 (match_operand:I12 1 "memory_operand" "") ;; memory 921 (FETCHOP:I12 (match_dup 1) 922 (match_operand:I12 2 "<fetchop_pred>" "")) ;; operand 923 (match_operand:SI 3 "const_int_operand" "")] ;; model 924 "" 925{ 926 or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2], 927 NULL, operands[0]); 928 DONE; 929}) 930 931;; ------------------------------------------------------------------------- 932;; Call Instructions 933;; ------------------------------------------------------------------------- 934 935;; Leave these to last, as the modeless operand for call_value 936;; interferes with normal patterns. 937 938(define_expand "call" 939 [(call (match_operand 0) (match_operand 1))] 940 "" 941{ 942 or1k_expand_call (NULL, operands[0], operands[1], false); 943 DONE; 944}) 945 946(define_expand "sibcall" 947 [(call (match_operand 0) (match_operand 1))] 948 "" 949{ 950 or1k_expand_call (NULL, operands[0], operands[1], true); 951 DONE; 952}) 953 954(define_expand "call_value" 955 [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))] 956 "" 957{ 958 or1k_expand_call (operands[0], operands[1], operands[2], false); 959 DONE; 960}) 961 962(define_expand "sibcall_value" 963 [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))] 964 "" 965{ 966 or1k_expand_call (operands[0], operands[1], operands[2], true); 967 DONE; 968}) 969 970(define_insn "*call" 971 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "r,s")) 972 (match_operand 1)) 973 (clobber (reg:SI LR_REGNUM))] 974 "!SIBLING_CALL_P (insn)" 975 "@ 976 l.jalr\t%0%# 977 l.jal\t%P0%#" 978 [(set_attr "type" "control")]) 979 980(define_insn "*sibcall" 981 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "c,s")) 982 (match_operand 1))] 983 "SIBLING_CALL_P (insn)" 984 "@ 985 l.jr\t%0%# 986 l.j\t%P0%#" 987 [(set_attr "type" "control")]) 988 989(define_insn "*call_value" 990 [(set (match_operand 0) 991 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "r,s")) 992 (match_operand 2))) 993 (clobber (reg:SI LR_REGNUM))] 994 "!SIBLING_CALL_P (insn)" 995 "@ 996 l.jalr\t%1%# 997 l.jal\t%P1%#" 998 [(set_attr "type" "control")]) 999 1000(define_insn "*sibcall_value" 1001 [(set (match_operand 0) 1002 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "c,s")) 1003 (match_operand 2)))] 1004 "SIBLING_CALL_P (insn)" 1005 "@ 1006 l.jr\t%1%# 1007 l.j\t%P1%#" 1008 [(set_attr "type" "control")]) 1009