1;; microblaze.md -- Machine description for Xilinx MicroBlaze processors. 2;; Copyright (C) 2009-2019 Free Software Foundation, Inc. 3 4;; Contributed by Michael Eager <eager@eagercon.com>. 5 6;; This file is part of GCC. 7 8;; GCC 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 3, or (at your option) 11;; any later version. 12 13;; GCC 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 GCC; see the file COPYING3. If not see 20;; <http://www.gnu.org/licenses/>. */ 21 22(include "constraints.md") 23(include "predicates.md") 24 25;;---------------------------------------------------- 26;; Constants 27;;---------------------------------------------------- 28(define_constants [ 29 (R_SP 1) ;; Stack pointer reg 30 (R_SR 15) ;; Sub-routine return addr reg 31 (R_IR 14) ;; Interrupt return addr reg 32 (R_DR 16) ;; Debug trap return addr reg 33 (R_ER 17) ;; Exception return addr reg 34 (R_TMP 18) ;; Assembler temporary reg 35 (R_GOT 20) ;; GOT ptr reg 36 (MB_PIPE_3 0) ;; Microblaze 3-stage pipeline 37 (MB_PIPE_5 1) ;; Microblaze 5-stage pipeline 38 (UNSPEC_SET_GOT 101) ;; 39 (UNSPEC_GOTOFF 102) ;; GOT offset 40 (UNSPEC_PLT 103) ;; jump table 41 (UNSPEC_CMP 104) ;; signed compare 42 (UNSPEC_CMPU 105) ;; unsigned compare 43 (UNSPEC_TLS 106) ;; jump table 44 (UNSPEC_SET_TEXT 107) ;; set text start 45 (UNSPEC_TEXT 108) ;; data text relative 46]) 47 48(define_c_enum "unspec" [ 49 UNSPEC_IPREFETCH 50]) 51 52;;---------------------------------------------------- 53;; Instruction Attributes 54;;---------------------------------------------------- 55 56;; Classification of each insn. 57;; branch conditional branch 58;; jump unconditional jump 59;; call unconditional call 60;; load load instruction(s) 61;; store store instruction(s) 62;; move data movement within same register set 63;; arith integer arithmetic instruction 64;; darith double precision integer arithmetic instructions 65;; imul integer multiply 66;; idiv integer divide 67;; icmp integer compare 68;; Xfadd floating point add/subtract 69;; Xfmul floating point multiply 70;; Xfmadd floating point multiply-add 71;; Xfdiv floating point divide 72;; Xfabs floating point absolute value 73;; Xfneg floating point negation 74;; Xfcmp floating point compare 75;; Xfcvt floating point convert 76;; Xfsqrt floating point square root 77;; multi multiword sequence (or user asm statements) 78;; nop no operation 79;; bshift Shift operations 80 81(define_attr "type" 82 "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt,trap" 83 (const_string "unknown")) 84 85;; Main data type used by the insn 86(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown")) 87 88;; # instructions (4 bytes each) 89(define_attr "length" "" (const_int 4)) 90 91(define_code_iterator any_return [return simple_return]) 92 93;; <optab> expands to the name of the optab for a particular code. 94(define_code_attr optab [(return "return") 95 (simple_return "simple_return")]) 96 97 98;;---------------------------------------------------- 99;; Attribute describing the processor. 100;;---------------------------------------------------- 101 102;; Describe a user's asm statement. 103(define_asm_attributes 104 [(set_attr "type" "multi")]) 105 106;; whether or not generating calls to position independent functions 107(define_attr "abicalls" "no,yes" 108 (const (symbol_ref "microblaze_abicalls_attr"))) 109 110;;---------------------------------------------------------------- 111;; Microblaze DFA Pipeline description 112;;---------------------------------------------------------------- 113 114;;----------------------------------------------------------------- 115/* 116 This is description of pipeline hazards based on DFA. The 117 following constructions can be used for this: 118 119 o define_cpu_unit string [string]) describes a cpu functional unit 120 (separated by comma). 121 122 1st operand: Names of cpu function units. 123 2nd operand: Name of automaton (see comments for 124 DEFINE_AUTOMATON). 125 126 All define_reservations and define_cpu_units should have unique 127 names which cannot be "nothing". 128 129 o (exclusion_set string string) means that each CPU function unit 130 in the first string cannot be reserved simultaneously with each 131 unit whose name is in the second string and vise versa. CPU 132 units in the string are separated by commas. For example, it is 133 useful for description CPU with fully pipelined floating point 134 functional unit which can execute simultaneously only single 135 floating point insns or only double floating point insns. 136 137 o (presence_set string string) means that each CPU function unit in 138 the first string cannot be reserved unless at least one of units 139 whose names are in the second string is reserved. This is an 140 asymmetric relation. CPU units in the string are separated by 141 commas. For example, it is useful for description that slot1 is 142 reserved after slot0 reservation for a VLIW processor. 143 144 o (absence_set string string) means that each CPU function unit in 145 the first string cannot be reserved only if each unit whose name 146 is in the second string is not reserved. This is an asymmetric 147 relation (actually exclusion set is analogous to this one but it 148 is symmetric). CPU units in the string are separated by commas. 149 For example, it is useful for description that slot0 cannot be 150 reserved after slot1 or slot2 reservation for a VLIW processor. 151 152 o (define_bypass number out_insn_names in_insn_names) names bypass with 153 given latency (the first number) from insns given by the first 154 string (see define_insn_reservation) into insns given by the 155 second string. Insn names in the strings are separated by 156 commas. 157 158 o (define_automaton string) describes names of an automaton 159 generated and used for pipeline hazards recognition. The names 160 are separated by comma. Actually it is possibly to generate the 161 single automaton but unfortunately it can be very large. If we 162 use more one automata, the summary size of the automata usually 163 is less than the single one. The automaton name is used in 164 define_cpu_unit. All automata should have unique names. 165 166 o (define_reservation string string) names reservation (the first 167 string) of cpu functional units (the 2nd string). Sometimes unit 168 reservations for different insns contain common parts. In such 169 case, you describe common part and use one its name (the 1st 170 parameter) in regular expression in define_insn_reservation. All 171 define_reservations, define results and define_cpu_units should 172 have unique names which cannot be "nothing". 173 174 o (define_insn_reservation name default_latency condition regexpr) 175 describes reservation of cpu functional units (the 3nd operand) 176 for instruction which is selected by the condition (the 2nd 177 parameter). The first parameter is used for output of debugging 178 information. The reservations are described by a regular 179 expression according the following syntax: 180 181 regexp = regexp "," oneof 182 | oneof 183 184 oneof = oneof "|" allof 185 | allof 186 187 allof = allof "+" repeat 188 | repeat 189 190 repeat = element "*" number 191 | element 192 193 element = cpu_function_name 194 | reservation_name 195 | result_name 196 | "nothing" 197 | "(" regexp ")" 198 199 1. "," is used for describing start of the next cycle in 200 reservation. 201 202 2. "|" is used for describing the reservation described by the 203 first regular expression *or* the reservation described by 204 the second regular expression *or* etc. 205 206 3. "+" is used for describing the reservation described by the 207 first regular expression *and* the reservation described by 208 the second regular expression *and* etc. 209 210 4. "*" is used for convenience and simply means sequence in 211 which the regular expression are repeated NUMBER times with 212 cycle advancing (see ","). 213 214 5. cpu function unit name which means reservation. 215 216 6. reservation name -- see define_reservation. 217 218 7. string "nothing" means no units reservation. 219 220*/ 221;;----------------------------------------------------------------- 222 223 224;;---------------------------------------------------------------- 225;; Microblaze 5-stage pipeline description (v5.00.a and later) 226;;---------------------------------------------------------------- 227 228(define_automaton "mbpipe_5") 229(define_cpu_unit "mb_issue,mb_iu,mb_wb,mb_fpu,mb_fpu_2,mb_mul,mb_mul_2,mb_div,mb_div_2,mb_bs,mb_bs_2" "mbpipe_5") 230 231(define_insn_reservation "mb-integer" 1 232 (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith") 233 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 234 "mb_issue,mb_iu,mb_wb") 235 236(define_insn_reservation "mb-special-move" 2 237 (and (eq_attr "type" "move") 238 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 239 "mb_issue,mb_iu*2,mb_wb") 240 241(define_insn_reservation "mb-mem-load" 3 242 (and (eq_attr "type" "load,no_delay_load") 243 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 244 "mb_issue,mb_iu,mb_wb") 245 246(define_insn_reservation "mb-mem-store" 1 247 (and (eq_attr "type" "store,no_delay_store") 248 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 249 "mb_issue,mb_iu,mb_wb") 250 251(define_insn_reservation "mb-mul" 3 252 (and (eq_attr "type" "imul,no_delay_imul") 253 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 254 "mb_issue,mb_mul,mb_mul_2*2,mb_wb") 255 256(define_insn_reservation "mb-div" 34 257 (and (eq_attr "type" "idiv") 258 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 259 "mb_issue,mb_div,mb_div_2*33,mb_wb") 260 261(define_insn_reservation "mb-bs" 2 262 (and (eq_attr "type" "bshift") 263 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 264 "mb_issue,mb_bs,mb_bs_2,mb_wb") 265 266(define_insn_reservation "mb-fpu-add-sub-mul" 6 267 (and (eq_attr "type" "fadd,frsub,fmul") 268 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 269 "mb_issue,mb_fpu,mb_fpu_2*5,mb_wb") 270 271(define_insn_reservation "mb-fpu-fcmp" 3 272 (and (eq_attr "type" "fcmp") 273 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 274 "mb_issue,mb_fpu,mb_fpu*2,mb_wb") 275 276(define_insn_reservation "mb-fpu-div" 30 277 (and (eq_attr "type" "fdiv") 278 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 279 "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb") 280 281(define_insn_reservation "mb-fpu-sqrt" 30 282 (and (eq_attr "type" "fsqrt") 283 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 284 "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb") 285 286(define_insn_reservation "mb-fpu-fcvt" 4 287 (and (eq_attr "type" "fcvt") 288 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5))) 289 "mb_issue,mb_fpu,mb_fpu_2*3,mb_wb") 290 291;;---------------------------------------------------------------- 292;; Microblaze 3-stage pipeline description (for v4.00.a and earlier) 293;;---------------------------------------------------------------- 294 295(define_automaton "mbpipe_3") 296(define_cpu_unit "mb3_iu" "mbpipe_3") 297 298(define_insn_reservation "mb3-integer" 1 299 (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith") 300 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 301 "mb3_iu") 302 303(define_insn_reservation "mb3-special-move" 2 304 (and (eq_attr "type" "move") 305 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 306 "mb3_iu*2") 307 308(define_insn_reservation "mb3-mem-load" 2 309 (and (eq_attr "type" "load,no_delay_load") 310 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 311 "mb3_iu") 312 313(define_insn_reservation "mb3-mem-store" 1 314 (and (eq_attr "type" "store,no_delay_store") 315 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 316 "mb3_iu") 317 318(define_insn_reservation "mb3-mul" 3 319 (and (eq_attr "type" "imul,no_delay_imul") 320 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 321 "mb3_iu") 322 323(define_insn_reservation "mb3-div" 34 324 (and (eq_attr "type" "idiv") 325 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 326 "mb3_iu") 327 328(define_insn_reservation "mb3-bs" 2 329 (and (eq_attr "type" "bshift") 330 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 331 "mb3_iu") 332 333(define_insn_reservation "mb3-fpu-add-sub-mul" 6 334 (and (eq_attr "type" "fadd,frsub,fmul") 335 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 336 "mb3_iu") 337 338(define_insn_reservation "mb3-fpu-fcmp" 3 339 (and (eq_attr "type" "fcmp") 340 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 341 "mb3_iu") 342 343(define_insn_reservation "mb3-fpu-div" 30 344 (and (eq_attr "type" "fdiv") 345 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 346 "mb3_iu") 347 348(define_insn_reservation "mb3-fpu-sqrt" 30 349 (and (eq_attr "type" "fsqrt") 350 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 351 "mb3_iu") 352 353(define_insn_reservation "mb3-fpu-fcvt" 4 354 (and (eq_attr "type" "fcvt") 355 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3))) 356 "mb3_iu") 357 358(automata_option "v") 359(automata_option "time") 360(automata_option "progress") 361 362(define_insn "bswapsi2" 363 [(set (match_operand:SI 0 "register_operand" "=r") 364 (bswap:SI (match_operand:SI 1 "register_operand" "r")))] 365 "TARGET_REORDER" 366 "swapb %0, %1" 367) 368 369(define_insn "bswaphi2" 370 [(set (match_operand:HI 0 "register_operand" "=r") 371 (bswap:HI (match_operand:HI 1 "register_operand" "r")))] 372 "TARGET_REORDER" 373 "swapb %0, %1 374 swaph %0, %0" 375) 376 377;;---------------------------------------------------------------- 378;; Microblaze delay slot description 379;;---------------------------------------------------------------- 380(define_delay (eq_attr "type" "branch,call,jump") 381 [(and (eq_attr "type" "!branch,call,jump,icmp,multi,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,darith") 382 (ior (not (match_test "microblaze_no_unsafe_delay")) 383 (eq_attr "type" "!fadd,frsub,fmul,fdiv,fcmp,store,load") 384 )) 385 (nil) (nil)]) 386 387 388;;---------------------------------------------------------------- 389;; Microblaze FPU 390;;---------------------------------------------------------------- 391 392(define_insn "addsf3" 393 [(set (match_operand:SF 0 "register_operand" "=d") 394 (plus:SF (match_operand:SF 1 "register_operand" "d") 395 (match_operand:SF 2 "register_operand" "d")))] 396 "TARGET_HARD_FLOAT" 397 "fadd\t%0,%1,%2" 398 [(set_attr "type" "fadd") 399 (set_attr "mode" "SF") 400 (set_attr "length" "4")]) 401 402(define_insn "subsf3" 403 [(set (match_operand:SF 0 "register_operand" "=d") 404 (minus:SF (match_operand:SF 1 "register_operand" "d") 405 (match_operand:SF 2 "register_operand" "d")))] 406 "TARGET_HARD_FLOAT" 407 "frsub\t%0,%2,%1" 408 [(set_attr "type" "frsub") 409 (set_attr "mode" "SF") 410 (set_attr "length" "4")]) 411 412(define_insn "mulsf3" 413 [(set (match_operand:SF 0 "register_operand" "=d") 414 (mult:SF (match_operand:SF 1 "register_operand" "d") 415 (match_operand:SF 2 "register_operand" "d")))] 416 "TARGET_HARD_FLOAT" 417 "fmul\t%0,%1,%2" 418 [(set_attr "type" "fmul") 419 (set_attr "mode" "SF") 420 (set_attr "length" "4")]) 421 422 423(define_insn "divsf3" 424 [(set (match_operand:SF 0 "register_operand" "=d") 425 (div:SF (match_operand:SF 1 "register_operand" "d") 426 (match_operand:SF 2 "register_operand" "d")))] 427 "TARGET_HARD_FLOAT" 428 "fdiv\t%0,%2,%1" 429 [(set_attr "type" "fdiv") 430 (set_attr "mode" "SF") 431 (set_attr "length" "4")]) 432 433(define_insn "sqrtsf2" 434 [(set (match_operand:SF 0 "register_operand" "=d") 435 (sqrt:SF (match_operand:SF 1 "register_operand" "d")))] 436 "TARGET_HARD_FLOAT && TARGET_FLOAT_SQRT" 437 "fsqrt\t%0,%1" 438 [(set_attr "type" "fsqrt") 439 (set_attr "mode" "SF") 440 (set_attr "length" "4")]) 441 442(define_insn "floatsisf2" 443 [(set (match_operand:SF 0 "register_operand" "=d") 444 (float:SF (match_operand:SI 1 "register_operand" "d")))] 445 "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT" 446 "flt\t%0,%1" 447 [(set_attr "type" "fcvt") 448 (set_attr "mode" "SF") 449 (set_attr "length" "4")]) 450 451(define_insn "fix_truncsfsi2" 452 [(set (match_operand:SI 0 "register_operand" "=d") 453 (fix:SI (match_operand:SF 1 "register_operand" "d")))] 454 "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT" 455 "fint\t%0,%1" 456 [(set_attr "type" "fcvt") 457 (set_attr "mode" "SF") 458 (set_attr "length" "4")]) 459 460;;---------------------------------------------------------------- 461;; Add 462;;---------------------------------------------------------------- 463 464;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ] 465;; Leave carry as is 466(define_insn "addsi3" 467 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 468 (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ") 469 (match_operand:SI 2 "arith_plus_operand" "d,I,i")))] 470 "" 471 "@ 472 addk\t%0,%z1,%2 473 addik\t%0,%z1,%2 474 addik\t%0,%z1,%2" 475 [(set_attr "type" "arith,arith,no_delay_arith") 476 (set_attr "mode" "SI,SI,SI") 477 (set_attr "length" "4,4,8")]) 478 479;;---------------------------------------------------------------- 480;; Double Precision Additions 481;;---------------------------------------------------------------- 482 483;; reg_DI_dest = reg_DI_src1 + DI_src2 484 485;; Adding 2 DI operands in register or reg/imm 486 487(define_insn "adddi3" 488 [(set (match_operand:DI 0 "register_operand" "=d,d,d") 489 (plus:DI (match_operand:DI 1 "register_operand" "%d,d,d") 490 (match_operand:DI 2 "arith_operand32" "d,P,N")))] 491 "" 492 "@ 493 add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2 494 addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0 495 addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0\;addi\t%M0,%M0,-1" 496 [(set_attr "type" "darith") 497 (set_attr "mode" "DI") 498 (set_attr "length" "8,8,12")]) 499 500;;---------------------------------------------------------------- 501;; Subtraction 502;;---------------------------------------------------------------- 503 504(define_insn "subsi3" 505 [(set (match_operand:SI 0 "register_operand" "=d,d") 506 (minus:SI (match_operand:SI 1 "arith_operand" "d,d") 507 (match_operand:SI 2 "arith_operand" "d,n")))] 508 "" 509 "@ 510 rsubk\t%0,%2,%z1 511 addik\t%0,%z1,-%2" 512 [(set_attr "type" "arith,no_delay_arith") 513 (set_attr "mode" "SI") 514 (set_attr "length" "4,8")]) 515 516(define_insn "iprefetch" 517 [(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH) 518 (clobber (mem:BLK (scratch)))] 519 "TARGET_PREFETCH" 520 { 521 operands[2] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 522 return "mfs\t%2,rpc\n\twic\t%2,r0"; 523 } 524 [(set_attr "type" "arith") 525 (set_attr "mode" "SI") 526 (set_attr "length" "8")]) 527 528;;---------------------------------------------------------------- 529;; Double Precision Subtraction 530;;---------------------------------------------------------------- 531 532(define_insn "subdi3" 533 [(set (match_operand:DI 0 "register_operand" "=&d") 534 (minus:DI (match_operand:DI 1 "register_operand" "d") 535 (match_operand:DI 2 "arith_operand32" "d")))] 536 "" 537 "rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1" 538 [(set_attr "type" "darith") 539 (set_attr "mode" "DI") 540 (set_attr "length" "8")]) 541 542 543;;---------------------------------------------------------------- 544;; Multiplication 545;;---------------------------------------------------------------- 546 547(define_insn "mulsi3" 548 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 549 (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") 550 (match_operand:SI 2 "arith_operand" "d,I,i")))] 551 "!TARGET_SOFT_MUL" 552 "@ 553 mul\t%0,%1,%2 554 muli\t%0,%1,%2 555 muli\t%0,%1,%2" 556 [(set_attr "type" "imul,imul,no_delay_imul") 557 (set_attr "mode" "SI") 558 (set_attr "length" "4,4,8")]) 559 560(define_insn "mulsidi3" 561 [(set (match_operand:DI 0 "register_operand" "=&d") 562 (mult:DI 563 (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) 564 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 565 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 566 "mul\t%L0,%1,%2\;mulh\t%M0,%1,%2" 567 [(set_attr "type" "no_delay_arith") 568 (set_attr "mode" "DI") 569 (set_attr "length" "8")]) 570 571(define_insn "umulsidi3" 572 [(set (match_operand:DI 0 "register_operand" "=&d") 573 (mult:DI 574 (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 575 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 576 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 577 "mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2" 578 [(set_attr "type" "no_delay_arith") 579 (set_attr "mode" "DI") 580 (set_attr "length" "8")]) 581 582(define_insn "usmulsidi3" 583 [(set (match_operand:DI 0 "register_operand" "=&d") 584 (mult:DI 585 (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 586 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 587 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 588 "mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1" 589 [(set_attr "type" "no_delay_arith") 590 (set_attr "mode" "DI") 591 (set_attr "length" "8")]) 592 593(define_insn "*smulsi3_highpart" 594 [(set (match_operand:SI 0 "register_operand" "=d") 595 (truncate:SI 596 (lshiftrt:DI 597 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) 598 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))) 599 (const_int 32))))] 600 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 601 "mulh\t%0,%1,%2" 602 [(set_attr "type" "imul") 603 (set_attr "mode" "SI") 604 (set_attr "length" "4")]) 605 606(define_insn "*umulsi3_highpart" 607 [(set (match_operand:SI 0 "register_operand" "=d") 608 (truncate:SI 609 (lshiftrt:DI 610 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 611 (zero_extend:DI (match_operand:SI 2 "register_operand" "d")) 612) 613 (const_int 32))))] 614 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 615 "mulhu\t%0,%1,%2" 616 [(set_attr "type" "imul") 617 (set_attr "mode" "SI") 618 (set_attr "length" "4")]) 619 620(define_insn "*usmulsi3_highpart" 621 [(set (match_operand:SI 0 "register_operand" "=d") 622 (truncate:SI 623 (lshiftrt:DI 624 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 625 (sign_extend:DI (match_operand:SI 2 "register_operand" "d")) 626) 627 (const_int 32))))] 628 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 629 "mulhsu\t%0,%2,%1" 630 [(set_attr "type" "imul") 631 (set_attr "mode" "SI") 632 (set_attr "length" "4")]) 633 634 635;;---------------------------------------------------------------- 636;; Division and remainder 637;;---------------------------------------------------------------- 638(define_expand "divsi3" 639 [(set (match_operand:SI 0 "register_operand" "=d") 640 (div:SI (match_operand:SI 1 "register_operand" "d") 641 (match_operand:SI 2 "register_operand" "d"))) 642 ] 643 "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)" 644 { 645 if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES) 646 { 647 microblaze_expand_divide (operands); 648 DONE; 649 } 650 else if (!TARGET_SOFT_DIV) 651 { 652 emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2])); 653 DONE; 654 } 655 } 656) 657 658 659(define_insn "divsi3_internal" 660 [(set (match_operand:SI 0 "register_operand" "=d") 661 (div:SI (match_operand:SI 1 "register_operand" "d") 662 (match_operand:SI 2 "register_operand" "d"))) 663 ] 664 "!TARGET_SOFT_DIV" 665 "idiv\t%0,%2,%1" 666 [(set_attr "type" "idiv") 667 (set_attr "mode" "SI") 668 (set_attr "length" "4")] 669) 670 671(define_insn "udivsi3" 672 [(set (match_operand:SI 0 "register_operand" "=d") 673 (udiv:SI (match_operand:SI 1 "register_operand" "d") 674 (match_operand:SI 2 "register_operand" "d"))) 675 ] 676 "!TARGET_SOFT_DIV" 677 "idivu\t%0,%2,%1" 678 [(set_attr "type" "idiv") 679 (set_attr "mode" "SI") 680 (set_attr "length" "4")]) 681 682(define_peephole2 683 [(set (match_operand:SI 0 "register_operand") 684 (fix:SI (match_operand:SF 1 "register_operand"))) 685 (set (pc) 686 (if_then_else (match_operator 2 "ordered_comparison_operator" 687 [(match_operand:SI 3 "register_operand") 688 (match_operand:SI 4 "arith_operand")]) 689 (label_ref (match_operand 5)) 690 (pc)))] 691 "TARGET_HARD_FLOAT" 692 [(set (match_dup 1) (match_dup 3))] 693 694 { 695 rtx condition; 696 rtx cmp_op0 = operands[3]; 697 rtx cmp_op1 = operands[4]; 698 rtx comp_reg = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 699 700 emit_insn (gen_cstoresf4 (comp_reg, operands[2], 701 gen_rtx_REG (SFmode, REGNO (cmp_op0)), 702 gen_rtx_REG (SFmode, REGNO (cmp_op1)))); 703 condition = gen_rtx_NE (SImode, comp_reg, const0_rtx); 704 emit_jump_insn (gen_condjump (condition, operands[5])); 705 } 706) 707 708;;---------------------------------------------------------------- 709;; Negation and one's complement 710;;---------------------------------------------------------------- 711 712(define_insn "negsi2" 713 [(set (match_operand:SI 0 "register_operand" "=d") 714 (neg:SI (match_operand:SI 1 "register_operand" "d")))] 715 "" 716 "rsubk\t%0,%1,r0" 717 [(set_attr "type" "arith") 718 (set_attr "mode" "SI") 719 (set_attr "length" "4")]) 720 721(define_insn "negdi2" 722 [(set (match_operand:DI 0 "register_operand" "=d") 723 (neg:DI (match_operand:DI 1 "register_operand" "d")))] 724 "" 725 "rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0" 726 [(set_attr "type" "darith") 727 (set_attr "mode" "DI") 728 (set_attr "length" "8")]) 729 730 731(define_insn "one_cmplsi2" 732 [(set (match_operand:SI 0 "register_operand" "=d") 733 (not:SI (match_operand:SI 1 "register_operand" "d")))] 734 "" 735 "xori\t%0,%1,-1" 736 [(set_attr "type" "arith") 737 (set_attr "mode" "SI") 738 (set_attr "length" "4")]) 739 740(define_insn "*one_cmpldi2" 741 [(set (match_operand:DI 0 "register_operand" "=d") 742 (not:DI (match_operand:DI 1 "register_operand" "d")))] 743 "" 744 "nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1" 745 [(set_attr "type" "darith") 746 (set_attr "mode" "DI") 747 (set_attr "length" "8")] 748) 749 750(define_split 751 [(set (match_operand:DI 0 "register_operand" "") 752 (not:DI (match_operand:DI 1 "register_operand" "")))] 753 "reload_completed 754 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 755 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" 756 757 [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0))) 758 (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))] 759 "") 760 761 762;;---------------------------------------------------------------- 763;; Logical 764;;---------------------------------------------------------------- 765 766(define_insn "andsi3" 767 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") 768 (and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d") 769 (match_operand:SI 2 "arith_operand" "d,I,i,M")))] 770 "" 771 "@ 772 and\t%0,%1,%2 773 andi\t%0,%1,%2 #and1 774 andi\t%0,%1,%2 #and2 775 andi\t%0,%1,%2 #and3" 776 [(set_attr "type" "arith,arith,no_delay_arith,no_delay_arith") 777 (set_attr "mode" "SI,SI,SI,SI") 778 (set_attr "length" "4,8,8,8")]) 779 780 781(define_insn "iorsi3" 782 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") 783 (ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d") 784 (match_operand:SI 2 "arith_operand" "d,I,M,i")))] 785 "" 786 "@ 787 or\t%0,%1,%2 788 ori\t%0,%1,%2 789 ori\t%0,%1,%2 790 ori\t%0,%1,%2" 791 [(set_attr "type" "arith,no_delay_arith,no_delay_arith,no_delay_arith") 792 (set_attr "mode" "SI,SI,SI,SI") 793 (set_attr "length" "4,8,8,8")]) 794 795(define_insn "xorsi3" 796 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 797 (xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d") 798 (match_operand:SI 2 "arith_operand" "d,I,i")))] 799 "" 800 "@ 801 xor\t%0,%1,%2 802 xori\t%0,%1,%2 803 xori\t%0,%1,%2" 804 [(set_attr "type" "arith,arith,no_delay_arith") 805 (set_attr "mode" "SI,SI,SI") 806 (set_attr "length" "4,8,8")]) 807 808;;---------------------------------------------------------------- 809;; Zero extension 810;;---------------------------------------------------------------- 811 812(define_insn "zero_extendhisi2" 813 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 814 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] 815 "" 816 "@ 817 andi\t%0,%1,0xffff 818 lhu%i1\t%0,%1 819 lhu%i1\t%0,%1" 820 [(set_attr "type" "no_delay_arith,load,no_delay_load") 821 (set_attr "mode" "SI,SI,SI") 822 (set_attr "length" "8,4,8")]) 823 824(define_insn "zero_extendqihi2" 825 [(set (match_operand:HI 0 "register_operand" "=d,d,d") 826 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] 827 "" 828 "@ 829 andi\t%0,%1,0x00ff 830 lbu%i1\t%0,%1 831 lbu%i1\t%0,%1" 832 [(set_attr "type" "arith,load,no_delay_load") 833 (set_attr "mode" "HI") 834 (set_attr "length" "4,4,8")]) 835 836(define_insn "zero_extendqisi2" 837 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 838 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] 839 "" 840 "@ 841 andi\t%0,%1,0x00ff 842 lbu%i1\t%0,%1 843 lbu%i1\t%0,%1" 844 [(set_attr "type" "arith,load,no_delay_load") 845 (set_attr "mode" "SI,SI,SI") 846 (set_attr "length" "4,4,8")]) 847 848;;---------------------------------------------------------------- 849;; Sign extension 850;;---------------------------------------------------------------- 851 852;; basic Sign Extend Operations 853 854(define_insn "extendqisi2" 855 [(set (match_operand:SI 0 "register_operand" "=d") 856 (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))] 857 "" 858 "sext8\t%0,%1" 859 [(set_attr "type" "arith") 860 (set_attr "mode" "SI") 861 (set_attr "length" "4")]) 862 863(define_insn "extendhisi2" 864 [(set (match_operand:SI 0 "register_operand" "=d") 865 (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))] 866 "" 867 "sext16\t%0,%1" 868 [(set_attr "type" "arith") 869 (set_attr "mode" "SI") 870 (set_attr "length" "4")]) 871 872;; Those for integer source operand are ordered 873;; widest source type first. 874 875(define_insn "extendsidi2" 876 [(set (match_operand:DI 0 "register_operand" "=d,d,d") 877 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] 878 "" 879 { 880 if (which_alternative == 0) 881 output_asm_insn ("addk\t%L0,r0,%1", operands); 882 else 883 output_asm_insn ("lw%i1\t%L0,%1", operands); 884 885 output_asm_insn ("add\t%M0,%L0,%L0", operands); 886 output_asm_insn ("addc\t%M0,r0,r0", operands); 887 output_asm_insn ("beqi\t%M0,.+8", operands); 888 return "addi\t%M0,r0,0xffffffff"; 889 } 890 [(set_attr "type" "multi,multi,multi") 891 (set_attr "mode" "DI") 892 (set_attr "length" "20,20,20")]) 893 894;;---------------------------------------------------------------- 895;; Data movement 896;;---------------------------------------------------------------- 897 898;; 64-bit integer moves 899 900;; Unlike most other insns, the move insns can't be split with 901;; different predicates, because register spilling and other parts of 902;; the compiler, have memoized the insn number already. 903 904(define_expand "movdi" 905 [(set (match_operand:DI 0 "nonimmediate_operand" "") 906 (match_operand:DI 1 "general_operand" ""))] 907 "" 908 { 909 /* If operands[1] is a constant address illegal for pic, then we need to 910 handle it just like microblaze_legitimize_address does. */ 911 if (flag_pic && pic_address_needs_scratch (operands[1])) 912 { 913 rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0)); 914 rtx temp2 = XEXP (XEXP (operands[1], 0), 1); 915 emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2)); 916 DONE; 917 } 918 919 920 if ((reload_in_progress | reload_completed) == 0 921 && !register_operand (operands[0], DImode) 922 && !register_operand (operands[1], DImode) 923 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 924 && operands[1] != CONST0_RTX (DImode)))) 925 { 926 927 rtx temp = force_reg (DImode, operands[1]); 928 emit_move_insn (operands[0], temp); 929 DONE; 930 } 931 } 932) 933 934 935 936(define_insn "*movdi_internal" 937 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o") 938 (match_operand:DI 1 "general_operand" " d,i,J,R,o,d,d"))] 939 "" 940 { 941 switch (which_alternative) 942 { 943 case 0: 944 return "addk\t%0,%1\n\taddk\t%D0,%d1"; 945 case 1: 946 return "addik\t%M0,r0,%h1\n\taddik\t%L0,r0,%j1 #li => la"; 947 case 2: 948 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0"; 949 case 3: 950 case 4: 951 if (reg_mentioned_p (operands[0], operands[1])) 952 return "lwi\t%D0,%o1\n\tlwi\t%0,%1"; 953 else 954 return "lwi\t%0,%1\n\tlwi\t%D0,%o1"; 955 case 5: 956 case 6: 957 return "swi\t%1,%0\n\tswi\t%D1,%o0"; 958 } 959 return "unreachable"; 960 } 961 [(set_attr "type" "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store") 962 (set_attr "mode" "DI") 963 (set_attr "length" "8,8,8,8,12,8,12")]) 964 965(define_split 966 [(set (match_operand:DI 0 "register_operand" "") 967 (match_operand:DI 1 "register_operand" ""))] 968 "reload_completed 969 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 970 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 971 && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))" 972 973 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4)) 974 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))] 975 "") 976 977(define_split 978 [(set (match_operand:DI 0 "register_operand" "") 979 (match_operand:DI 1 "register_operand" ""))] 980 "reload_completed 981 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 982 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 983 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))" 984 985 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) 986 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] 987 "") 988 989;; Unlike most other insns, the move insns can't be split with 990;; different predicates, because register spilling and other parts of 991;; the compiler, have memoized the insn number already. 992 993(define_expand "movsi" 994 [(set (match_operand:SI 0 "nonimmediate_operand" "") 995 (match_operand:SI 1 "general_operand" ""))] 996 "" 997 { 998 if (microblaze_expand_move (SImode, operands)) DONE; 999 } 1000) 1001 1002;; Added for status registers 1003(define_insn "movsi_status" 1004 [(set (match_operand:SI 0 "register_operand" "=d,d,z") 1005 (match_operand:SI 1 "register_operand" "z,d,d"))] 1006 "microblaze_is_interrupt_variant ()" 1007 "@ 1008 mfs\t%0,%1 #mfs 1009 addk\t%0,%1,r0 #add movsi 1010 mts\t%0,%1 #mts" 1011 [(set_attr "type" "move") 1012 (set_attr "mode" "SI") 1013 (set_attr "length" "12")]) 1014 1015;; This move will be not be moved to delay slot. 1016(define_insn "*movsi_internal3" 1017 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d") 1018 (match_operand:SI 1 "immediate_operand" "J,I,Mnis"))] 1019 "(register_operand (operands[0], SImode) && 1020 (GET_CODE (operands[1]) == CONST_INT && 1021 (INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))" 1022 "@ 1023 addk\t%0,r0,r0 1024 addik\t%0,r0,%1\t# %X1 1025 addik\t%0,r0,%1\t# %X1" 1026 [(set_attr "type" "arith,arith,no_delay_arith") 1027 (set_attr "mode" "SI") 1028 (set_attr "length" "4")]) 1029 1030;; This move may be used for PLT label operand 1031(define_insn "*movsi_internal5_pltop" 1032 [(set (match_operand:SI 0 "register_operand" "=d,d") 1033 (match_operand:SI 1 "call_insn_operand" ""))] 1034 "(register_operand (operands[0], Pmode) && 1035 PLT_ADDR_P (operands[1]))" 1036 { 1037 gcc_unreachable (); 1038 } 1039 [(set_attr "type" "load") 1040 (set_attr "mode" "SI") 1041 (set_attr "length" "4")]) 1042 1043(define_insn "*movsi_internal2" 1044 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R,m") 1045 (match_operand:SI 1 "move_src_operand" " d,I,Mnis,R,m,dJ,dJ"))] 1046 "" 1047 "@ 1048 addk\t%0,%1,r0 1049 addik\t%0,r0,%1\t# %X1 1050 addik\t%0,%a1 1051 lw%i1\t%0,%1 1052 lw%i1\t%0,%1 1053 sw%i0\t%z1,%0 1054 sw%i0\t%z1,%0" 1055 [(set_attr "type" "load,load,no_delay_load,load,no_delay_load,store,no_delay_store") 1056 (set_attr "mode" "SI") 1057 (set_attr "length" "4,4,8,4,8,4,8")]) 1058 1059 1060;; 16-bit Integer moves 1061 1062;; Unlike most other insns, the move insns can't be split with 1063;; different predicates, because register spilling and other parts of 1064;; the compiler, have memoized the insn number already. 1065;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined 1066 1067(define_expand "movhi" 1068 [(set (match_operand:HI 0 "nonimmediate_operand" "") 1069 (match_operand:HI 1 "general_operand" ""))] 1070 "" 1071 { 1072 if ((reload_in_progress | reload_completed) == 0 1073 && !register_operand (operands[0], HImode) 1074 && !register_operand (operands[1], HImode) 1075 && ((GET_CODE (operands[1]) != CONST_INT 1076 || INTVAL (operands[1]) != 0))) 1077 { 1078 rtx temp = force_reg (HImode, operands[1]); 1079 emit_move_insn (operands[0], temp); 1080 DONE; 1081 } 1082 } 1083) 1084 1085(define_insn "*movhi_internal2" 1086 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m") 1087 (match_operand:HI 1 "general_operand" "I,d,R,m,dJ,dJ"))] 1088 "" 1089 "@ 1090 addik\t%0,r0,%1\t# %X1 1091 addk\t%0,%1,r0 1092 lhui\t%0,%1 1093 lhui\t%0,%1 1094 sh%i0\t%z1,%0 1095 sh%i0\t%z1,%0" 1096 [(set_attr "type" "arith,move,load,no_delay_load,store,no_delay_store") 1097 (set_attr "mode" "HI") 1098 (set_attr "length" "4,4,4,8,8,8")]) 1099 1100;; 8-bit Integer moves 1101 1102;; Unlike most other insns, the move insns can't be split with 1103;; different predicates, because register spilling and other parts of 1104;; the compiler, have memoized the insn number already. 1105;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined 1106 1107(define_expand "movqi" 1108 [(set (match_operand:QI 0 "nonimmediate_operand" "") 1109 (match_operand:QI 1 "general_operand" ""))] 1110 "" 1111 { 1112 if ((reload_in_progress | reload_completed) == 0 1113 && !register_operand (operands[0], QImode) 1114 && !register_operand (operands[1], QImode) 1115 && ((GET_CODE (operands[1]) != CONST_INT 1116 || INTVAL (operands[1]) != 0))) 1117 { 1118 rtx temp = force_reg (QImode, operands[1]); 1119 emit_move_insn (operands[0], temp); 1120 DONE; 1121 } 1122 } 1123) 1124 1125(define_insn "*movqi_internal2" 1126 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m") 1127 (match_operand:QI 1 "general_operand" "J,I,d,R,m,dJ,dJ"))] 1128 "" 1129 "@ 1130 addk\t%0,r0,%z1 1131 addik\t%0,r0,%1\t# %X1 1132 addk\t%0,%1,r0 1133 lbu%i1\t%0,%1 1134 lbu%i1\t%0,%1 1135 sb%i0\t%z1,%0 1136 sbi\t%z1,%0" 1137 [(set_attr "type" "arith,arith,move,load,no_delay_load,store,no_delay_store") 1138 (set_attr "mode" "QI") 1139 (set_attr "length" "4,4,8,4,8,4,8")]) 1140 1141;; Block moves, see microblaze.c for more details. 1142;; Argument 0 is the destination 1143;; Argument 1 is the source 1144;; Argument 2 is the length 1145;; Argument 3 is the alignment 1146 1147(define_expand "movmemsi" 1148 [(parallel [(set (match_operand:BLK 0 "general_operand") 1149 (match_operand:BLK 1 "general_operand")) 1150 (use (match_operand:SI 2 "")) 1151 (use (match_operand:SI 3 "const_int_operand"))])] 1152 "" 1153 { 1154 if (microblaze_expand_block_move (operands[0], operands[1], 1155 operands[2], operands[3])) 1156 DONE; 1157 else 1158 FAIL; 1159 } 1160) 1161 1162;;Load and store reverse 1163(define_insn "movsi4_rev" 1164 [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Q") 1165 (bswap:SI (match_operand:SF 1 "reg_or_mem_operand" "Q,r")))] 1166 "TARGET_REORDER" 1167 "@ 1168 lwr\t%0,%y1,r0 1169 swr\t%1,%y0,r0" 1170 [(set_attr "type" "load,store") 1171 (set_attr "mode" "SI") 1172 (set_attr "length" "4,4")]) 1173 1174;; 32-bit floating point moves 1175 1176(define_expand "movsf" 1177 [(set (match_operand:SF 0 "nonimmediate_operand" "") 1178 (match_operand:SF 1 "general_operand" ""))] 1179 "" 1180 { 1181 if ((reload_in_progress | reload_completed) == 0 1182 && !register_operand (operands[0], SFmode) 1183 && !register_operand (operands[1], SFmode) 1184 && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1185 && operands[1] != CONST0_RTX (SFmode)))) 1186 { 1187 rtx temp = force_reg (SFmode, operands[1]); 1188 emit_move_insn (operands[0], temp); 1189 DONE; 1190 } 1191 } 1192) 1193 1194;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1195;; 1196(define_insn "*movsf_internal" 1197 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m") 1198 (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))] 1199 "(register_operand (operands[0], SFmode) 1200 || register_operand (operands[1], SFmode) 1201 || operands[1] == CONST0_RTX (SFmode))" 1202 "@ 1203 addk\t%0,r0,r0 1204 addk\t%0,%1,r0 1205 lw%i1\t%0,%1 1206 addik\t%0,r0,%F1 1207 lw%i1\t%0,%1 1208 sw%i0\t%z1,%0 1209 swi\t%z1,%0" 1210 [(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store") 1211 (set_attr "mode" "SF") 1212 (set_attr "length" "4,4,4,4,4,4,4")]) 1213 1214;; 64-bit floating point moves 1215(define_expand "movdf" 1216 [(set (match_operand:DF 0 "nonimmediate_operand" "") 1217 (match_operand:DF 1 "general_operand" ""))] 1218 "" 1219 { 1220 if (flag_pic == 2) { 1221 if (GET_CODE (operands[1]) == MEM 1222 && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0)) 1223 { 1224 rtx ptr_reg; 1225 rtx result; 1226 ptr_reg = force_reg (Pmode, XEXP (operands[1],0)); 1227 result = gen_rtx_MEM (DFmode, ptr_reg); 1228 emit_move_insn (operands[0], result); 1229 DONE; 1230 } 1231 } 1232 if ((reload_in_progress | reload_completed) == 0 1233 && !register_operand (operands[0], DFmode) 1234 && !register_operand (operands[1], DFmode) 1235 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1236 && operands[1] != CONST0_RTX (DFmode)))) 1237 { 1238 rtx temp = force_reg (DFmode, operands[1]); 1239 emit_move_insn (operands[0], temp); 1240 DONE; 1241 } 1242 } 1243) 1244 1245;; movdf_internal 1246;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1247;; 1248(define_insn "*movdf_internal" 1249 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o") 1250 (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))] 1251 "" 1252 { 1253 switch (which_alternative) 1254 { 1255 case 0: 1256 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0"; 1257 case 1: 1258 case 3: 1259 if (reg_mentioned_p (operands[0], operands[1])) 1260 return "lwi\t%D0,%o1\n\tlwi\t%0,%1"; 1261 else 1262 return "lwi\t%0,%1\n\tlwi\t%D0,%o1"; 1263 case 2: 1264 { 1265 return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo"; 1266 } 1267 case 4: 1268 return "swi\t%1,%0\n\tswi\t%D1,%o0"; 1269 } 1270 gcc_unreachable (); 1271 } 1272 [(set_attr "type" "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store") 1273 (set_attr "mode" "DF") 1274 (set_attr "length" "4,8,8,16,8")]) 1275 1276(define_split 1277 [(set (match_operand:DF 0 "register_operand" "") 1278 (match_operand:DF 1 "register_operand" ""))] 1279 "reload_completed 1280 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 1281 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 1282 && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))" 1283 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4)) 1284 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))] 1285 "") 1286 1287(define_split 1288 [(set (match_operand:DF 0 "register_operand" "") 1289 (match_operand:DF 1 "register_operand" ""))] 1290 "reload_completed 1291 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 1292 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 1293 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))" 1294 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) 1295 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] 1296 "") 1297 1298;;---------------------------------------------------------------- 1299;; Shifts 1300;;---------------------------------------------------------------- 1301 1302;;---------------------------------------------------------------- 1303;; 32-bit left shifts 1304;;---------------------------------------------------------------- 1305(define_expand "ashlsi3" 1306 [(set (match_operand:SI 0 "register_operand" "=&d") 1307 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1308 (match_operand:SI 2 "arith_operand" "")))] 1309 "" 1310 { 1311 /* Avoid recursion for trivial cases. */ 1312 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1313 if (microblaze_expand_shift (operands)) 1314 DONE; 1315 } 1316) 1317 1318;; Irrespective of if we have a barrel-shifter or not, we want to match 1319;; shifts by 1 with a special pattern. When a barrel shifter is present, 1320;; saves a cycle. If not, allows us to annotate the instruction for delay 1321;; slot optimization 1322(define_insn "*ashlsi3_byone" 1323 [(set (match_operand:SI 0 "register_operand" "=d") 1324 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1325 (match_operand:SI 2 "arith_operand" "I")))] 1326 "(operands[2] == const1_rtx)" 1327 "addk\t%0,%1,%1" 1328 [(set_attr "type" "arith") 1329 (set_attr "mode" "SI") 1330 (set_attr "length" "4")] 1331) 1332 1333;; Barrel shift left 1334(define_insn "ashlsi3_bshift" 1335 [(set (match_operand:SI 0 "register_operand" "=d,d") 1336 (ashift:SI (match_operand:SI 1 "register_operand" "d,d") 1337 (match_operand:SI 2 "arith_operand" "I,d")))] 1338 "TARGET_BARREL_SHIFT" 1339 "@ 1340 bslli\t%0,%1,%2 1341 bsll\t%0,%1,%2" 1342 [(set_attr "type" "bshift,bshift") 1343 (set_attr "mode" "SI,SI") 1344 (set_attr "length" "4,4")] 1345) 1346 1347;; The following patterns apply when there is no barrel shifter present 1348 1349(define_insn "*ashlsi3_with_mul_delay" 1350 [(set (match_operand:SI 0 "register_operand" "=d") 1351 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1352 (match_operand:SI 2 "immediate_operand" "I")))] 1353 "!TARGET_SOFT_MUL 1354 && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)" 1355 "muli\t%0,%1,%m2" 1356 ;; This MUL will not generate an imm. Can go into a delay slot. 1357 [(set_attr "type" "arith") 1358 (set_attr "mode" "SI") 1359 (set_attr "length" "4")] 1360) 1361 1362(define_insn "*ashlsi3_with_mul_nodelay" 1363 [(set (match_operand:SI 0 "register_operand" "=d") 1364 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1365 (match_operand:SI 2 "immediate_operand" "I")))] 1366 "!TARGET_SOFT_MUL" 1367 "muli\t%0,%1,%m2" 1368 ;; This MUL will generate an IMM. Cannot go into a delay slot 1369 [(set_attr "type" "no_delay_arith") 1370 (set_attr "mode" "SI") 1371 (set_attr "length" "8")] 1372) 1373 1374(define_insn "*ashlsi3_with_size_opt" 1375 [(set (match_operand:SI 0 "register_operand" "=&d") 1376 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1377 (match_operand:SI 2 "immediate_operand" "I")))] 1378 "(INTVAL (operands[2]) > 5 && optimize_size)" 1379 { 1380 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1381 1382 output_asm_insn ("ori\t%3,r0,%2", operands); 1383 if (REGNO (operands[0]) != REGNO (operands[1])) 1384 output_asm_insn ("addk\t%0,%1,r0", operands); 1385 1386 output_asm_insn ("addik\t%3,%3,-1", operands); 1387 output_asm_insn ("bneid\t%3,.-4", operands); 1388 return "addk\t%0,%0,%0"; 1389 } 1390 [(set_attr "type" "multi") 1391 (set_attr "mode" "SI") 1392 (set_attr "length" "20")] 1393) 1394 1395(define_insn "*ashlsi3_with_rotate" 1396 [(set (match_operand:SI 0 "register_operand" "=&d") 1397 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1398 (match_operand:SI 2 "immediate_operand" "I")))] 1399 "(INTVAL (operands[2]) > 17 && !optimize_size)" 1400 { 1401 int i, nshift; 1402 1403 nshift = INTVAL (operands[2]); 1404 operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode); 1405 1406 /* We do one extra shift so that the first bit (carry) coming into the MSB 1407 will be masked out */ 1408 output_asm_insn ("src\t%0,%1", operands); 1409 for (i = 0; i < (32 - nshift); i++) 1410 output_asm_insn ("src\t%0,%0", operands); 1411 1412 return "andi\t%0,%0,%3"; 1413 } 1414 [(set_attr "type" "multi") 1415 (set_attr "mode" "SI") 1416 (set_attr "length" "80")] 1417) 1418 1419(define_insn "*ashlsi_inline" 1420 [(set (match_operand:SI 0 "register_operand" "=&d") 1421 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1422 (match_operand:SI 2 "immediate_operand" "I")))] 1423 "" 1424 { 1425 int i; 1426 int nshift = INTVAL (operands[2]); 1427 if (REGNO (operands[0]) != REGNO (operands[1])) 1428 output_asm_insn ("addk\t%0,r0,%1", operands); 1429 output_asm_insn ("addk\t%0,%1,%1", operands); 1430 for (i = 0; i < (nshift - 2); i++) 1431 output_asm_insn ("addk\t%0,%0,%0", operands); 1432 return "addk\t%0,%0,%0"; 1433 } 1434 [(set_attr "type" "multi") 1435 (set_attr "mode" "SI") 1436 (set_attr "length" "124")] 1437) 1438 1439(define_insn "*ashlsi_reg" 1440 [(set (match_operand:SI 0 "register_operand" "=&d") 1441 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1442 (match_operand:SI 2 "register_operand" "d")))] 1443 "" 1444 { 1445 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1446 output_asm_insn ("andi\t%3,%2,31", operands); 1447 if (REGNO (operands[0]) != REGNO (operands[1])) 1448 output_asm_insn ("addk\t%0,r0,%1", operands); 1449 /* Exit the loop if zero shift. */ 1450 output_asm_insn ("beqid\t%3,.+20", operands); 1451 /* Emit the loop. */ 1452 output_asm_insn ("addk\t%0,%0,r0", operands); 1453 output_asm_insn ("addik\t%3,%3,-1", operands); 1454 output_asm_insn ("bneid\t%3,.-4", operands); 1455 return "addk\t%0,%0,%0"; 1456 } 1457 [(set_attr "type" "multi") 1458 (set_attr "mode" "SI") 1459 (set_attr "length" "28")] 1460) 1461 1462 1463;;---------------------------------------------------------------- 1464;; 32-bit right shifts 1465;;---------------------------------------------------------------- 1466(define_expand "ashrsi3" 1467 [(set (match_operand:SI 0 "register_operand" "=&d") 1468 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1469 (match_operand:SI 2 "arith_operand" "")))] 1470 "" 1471 { 1472 /* Avoid recursion for trivial cases. */ 1473 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1474 if (microblaze_expand_shift (operands)) 1475 DONE; 1476 } 1477) 1478 1479;; Irrespective of if we have a barrel-shifter or not, we want to match 1480;; shifts by 1 with a special pattern. When a barrel shifter is present, 1481;; saves a cycle. If not, allows us to annotate the instruction for delay 1482;; slot optimization 1483(define_insn "*ashrsi3_byone" 1484 [(set (match_operand:SI 0 "register_operand" "=d") 1485 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1486 (match_operand:SI 2 "arith_operand" "I")))] 1487 "(operands[2] == const1_rtx)" 1488 "sra\t%0,%1" 1489 [(set_attr "type" "arith") 1490 (set_attr "mode" "SI") 1491 (set_attr "length" "4")] 1492) 1493 1494;; Barrel shift right logical 1495(define_insn "*ashrsi3_bshift" 1496 [(set (match_operand:SI 0 "register_operand" "=d,d") 1497 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1498 (match_operand:SI 2 "arith_operand" "I,d")))] 1499 "TARGET_BARREL_SHIFT" 1500 "@ 1501 bsrai\t%0,%1,%2 1502 bsra\t%0,%1,%2" 1503 [(set_attr "type" "bshift,bshift") 1504 (set_attr "mode" "SI,SI") 1505 (set_attr "length" "4,4")] 1506) 1507 1508(define_insn "*ashrsi_inline" 1509 [(set (match_operand:SI 0 "register_operand" "=&d") 1510 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1511 (match_operand:SI 2 "immediate_operand" "I")))] 1512 "" 1513 { 1514 int i; 1515 int nshift = INTVAL (operands[2]); 1516 if (REGNO (operands[0]) != REGNO (operands[1])) 1517 output_asm_insn ("addk\t%0,r0,%1", operands); 1518 output_asm_insn ("sra\t%0,%1", operands); 1519 for (i = 0; i < (nshift - 2); i++) 1520 output_asm_insn ("sra\t%0,%0", operands); 1521 return "sra\t%0,%0"; 1522 } 1523 [(set_attr "type" "multi") 1524 (set_attr "mode" "SI") 1525 (set_attr "length" "124")] 1526) 1527 1528(define_insn "*ashrsi_reg" 1529 [(set (match_operand:SI 0 "register_operand" "=&d") 1530 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1531 (match_operand:SI 2 "register_operand" "d")))] 1532 "" 1533 { 1534 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1535 output_asm_insn ("andi\t%3,%2,31", operands); 1536 if (REGNO (operands[0]) != REGNO (operands[1])) 1537 output_asm_insn ("addk\t%0,r0,%1", operands); 1538 /* Exit the loop if zero shift. */ 1539 output_asm_insn ("beqid\t%3,.+20", operands); 1540 /* Emit the loop. */ 1541 output_asm_insn ("addk\t%0,%0,r0", operands); 1542 output_asm_insn ("addik\t%3,%3,-1", operands); 1543 output_asm_insn ("bneid\t%3,.-4", operands); 1544 return "sra\t%0,%0"; 1545 } 1546 [(set_attr "type" "multi") 1547 (set_attr "mode" "SI") 1548 (set_attr "length" "28")] 1549) 1550 1551;;---------------------------------------------------------------- 1552;; 32-bit right shifts (logical) 1553;;---------------------------------------------------------------- 1554 1555(define_expand "lshrsi3" 1556 [(set (match_operand:SI 0 "register_operand" "=&d") 1557 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1558 (match_operand:SI 2 "arith_operand" "")))] 1559 "" 1560 { 1561 /* Avoid recursion for trivial cases. */ 1562 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1563 if (microblaze_expand_shift (operands)) 1564 DONE; 1565 } 1566) 1567 1568;; Irrespective of if we have a barrel-shifter or not, we want to match 1569;; shifts by 1 with a special pattern. When a barrel shifter is present, 1570;; saves a cycle. If not, allows us to annotate the instruction for delay 1571;; slot optimization 1572(define_insn "*lshrsi3_byone" 1573 [(set (match_operand:SI 0 "register_operand" "=d") 1574 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1575 (match_operand:SI 2 "arith_operand" "I")))] 1576 "(operands[2] == const1_rtx)" 1577 "srl\t%0,%1" 1578 [(set_attr "type" "arith") 1579 (set_attr "mode" "SI") 1580 (set_attr "length" "4")] 1581) 1582 1583;; Barrel shift right logical 1584(define_insn "*lshrsi3_bshift" 1585 [(set (match_operand:SI 0 "register_operand" "=d,d") 1586 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1587 (match_operand:SI 2 "arith_operand" "I,d")))] 1588 "TARGET_BARREL_SHIFT" 1589 "@ 1590 bsrli\t%0,%1,%2 1591 bsrl\t%0,%1,%2" 1592 [(set_attr "type" "bshift,bshift") 1593 (set_attr "mode" "SI,SI") 1594 (set_attr "length" "4,4")] 1595) 1596 1597(define_insn "*lshrsi_inline" 1598 [(set (match_operand:SI 0 "register_operand" "=&d") 1599 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1600 (match_operand:SI 2 "immediate_operand" "I")))] 1601 "" 1602 { 1603 int i; 1604 int nshift = INTVAL (operands[2]); 1605 if (REGNO (operands[0]) != REGNO (operands[1])) 1606 output_asm_insn ("addk\t%0,r0,%1", operands); 1607 output_asm_insn ("srl\t%0,%1", operands); 1608 for (i = 0; i < (nshift - 2); i++) 1609 output_asm_insn ("srl\t%0,%0", operands); 1610 return "srl\t%0,%0"; 1611 } 1612 [(set_attr "type" "multi") 1613 (set_attr "mode" "SI") 1614 (set_attr "length" "124")] 1615) 1616 1617(define_insn "*lshrsi_reg" 1618 [(set (match_operand:SI 0 "register_operand" "=&d") 1619 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1620 (match_operand:SI 2 "register_operand" "d")))] 1621 "" 1622 { 1623 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1624 output_asm_insn ("andi\t%3,%2,31", operands); 1625 if (REGNO (operands[0]) != REGNO (operands[1])) 1626 output_asm_insn ("addk\t%0,r0,%1", operands); 1627 /* Exit the loop if zero shift. */ 1628 output_asm_insn ("beqid\t%3,.+20", operands); 1629 /* Emit the loop. */ 1630 output_asm_insn ("addk\t%0,%0,r0", operands); 1631 output_asm_insn ("addik\t%3,%3,-1", operands); 1632 output_asm_insn ("bneid\t%3,.-4", operands); 1633 return "srl\t%0,%0"; 1634 } 1635 [(set_attr "type" "multi") 1636 (set_attr "mode" "SI") 1637 (set_attr "length" "28")] 1638) 1639 1640;;---------------------------------------------------------------- 1641;; Setting a register from an integer comparison. 1642;;---------------------------------------------------------------- 1643(define_expand "cstoresi4" 1644 [(set (match_operand:SI 0 "register_operand") 1645 (match_operator:SI 1 "ordered_comparison_operator" 1646 [(match_operand:SI 2 "register_operand") 1647 (match_operand:SI 3 "register_operand")]))] 1648 "TARGET_PATTERN_COMPARE" 1649 "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE) 1650 FAIL; 1651 " 1652) 1653 1654(define_insn "seq_internal_pat" 1655 [(set (match_operand:SI 0 "register_operand" "=d") 1656 (eq:SI 1657 (match_operand:SI 1 "register_operand" "d") 1658 (match_operand:SI 2 "register_operand" "d")))] 1659 "TARGET_PATTERN_COMPARE" 1660 "pcmpeq\t%0,%1,%2" 1661 [(set_attr "type" "arith") 1662 (set_attr "mode" "SI") 1663 (set_attr "length" "4")] 1664) 1665 1666(define_insn "sne_internal_pat" 1667 [(set (match_operand:SI 0 "register_operand" "=d") 1668 (ne:SI 1669 (match_operand:SI 1 "register_operand" "d") 1670 (match_operand:SI 2 "register_operand" "d")))] 1671 "TARGET_PATTERN_COMPARE" 1672 "pcmpne\t%0,%1,%2" 1673 [(set_attr "type" "arith") 1674 (set_attr "mode" "SI") 1675 (set_attr "length" "4")] 1676) 1677 1678;;---------------------------------------------------------------- 1679;; Setting a register from an floating point comparison. 1680;;---------------------------------------------------------------- 1681(define_insn "cstoresf4" 1682 [(set (match_operand:SI 0 "register_operand" "=r") 1683 (match_operator:SI 1 "ordered_comparison_operator" 1684 [(match_operand:SF 2 "register_operand" "r") 1685 (match_operand:SF 3 "register_operand" "r")]))] 1686 "TARGET_HARD_FLOAT" 1687 "fcmp.%C1\t%0,%3,%2" 1688 [(set_attr "type" "fcmp") 1689 (set_attr "mode" "SF") 1690 (set_attr "length" "4")] 1691) 1692 1693;;---------------------------------------------------------------- 1694;; Conditional branches 1695;;---------------------------------------------------------------- 1696 1697(define_expand "cbranchsi4" 1698 [(set (pc) 1699 (if_then_else (match_operator 0 "ordered_comparison_operator" 1700 [(match_operand:SI 1 "register_operand") 1701 (match_operand:SI 2 "arith_operand" "I,i")]) 1702 (label_ref (match_operand 3 "")) 1703 (pc)))] 1704 "" 1705{ 1706 microblaze_expand_conditional_branch (SImode, operands); 1707 DONE; 1708}) 1709 1710(define_expand "cbranchsi4_reg" 1711 [(set (pc) 1712 (if_then_else (match_operator 0 "ordered_comparison_operator" 1713 [(match_operand:SI 1 "register_operand") 1714 (match_operand:SI 2 "register_operand")]) 1715 (label_ref (match_operand 3 "")) 1716 (pc)))] 1717 "" 1718{ 1719 microblaze_expand_conditional_branch_reg (SImode, operands); 1720 DONE; 1721}) 1722 1723(define_expand "cbranchsf4" 1724 [(set (pc) 1725 (if_then_else (match_operator 0 "ordered_comparison_operator" 1726 [(match_operand:SF 1 "register_operand") 1727 (match_operand:SF 2 "register_operand")]) 1728 (label_ref (match_operand 3 "")) 1729 (pc)))] 1730 "TARGET_HARD_FLOAT" 1731{ 1732 microblaze_expand_conditional_branch_sf (operands); 1733 DONE; 1734 1735}) 1736 1737;; Used to implement comparison instructions 1738(define_expand "condjump" 1739 [(set (pc) 1740 (if_then_else (match_operand 0) 1741 (label_ref (match_operand 1)) 1742 (pc)))]) 1743 1744(define_insn "branch_zero" 1745 [(set (pc) 1746 (if_then_else (match_operator:SI 0 "ordered_comparison_operator" 1747 [(match_operand:SI 1 "register_operand" "d") 1748 (const_int 0)]) 1749 (match_operand:SI 2 "pc_or_label_operand" "") 1750 (match_operand:SI 3 "pc_or_label_operand" ""))) 1751 ] 1752 "" 1753 { 1754 if (operands[3] == pc_rtx) 1755 return "b%C0i%?\t%z1,%2"; 1756 else 1757 return "b%N0i%?\t%z1,%3"; 1758 } 1759 [(set_attr "type" "branch") 1760 (set_attr "mode" "none") 1761 (set_attr "length" "4")] 1762) 1763 1764(define_insn "branch_compare" 1765 [(set (pc) 1766 (if_then_else (match_operator:SI 0 "cmp_op" 1767 [(match_operand:SI 1 "register_operand" "d") 1768 (match_operand:SI 2 "register_operand" "d") 1769 ]) 1770 (label_ref (match_operand 3)) 1771 (pc))) 1772 (clobber(reg:SI R_TMP))] 1773 "" 1774 { 1775 operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1776 enum rtx_code code = GET_CODE (operands[0]); 1777 1778 if (code == GT || code == LE) 1779 { 1780 output_asm_insn ("cmp\tr18,%z1,%z2", operands); 1781 code = swap_condition (code); 1782 } 1783 else if (code == GTU || code == LEU) 1784 { 1785 output_asm_insn ("cmpu\tr18,%z1,%z2", operands); 1786 code = swap_condition (code); 1787 } 1788 else if (code == GE || code == LT) 1789 { 1790 output_asm_insn ("cmp\tr18,%z2,%z1", operands); 1791 } 1792 else if (code == GEU || code == LTU) 1793 { 1794 output_asm_insn ("cmpu\tr18,%z2,%z1", operands); 1795 } 1796 1797 operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); 1798 return "b%C0i%?\tr18,%3"; 1799 } 1800 [(set_attr "type" "branch") 1801 (set_attr "mode" "none") 1802 (set_attr "length" "12")] 1803) 1804 1805;;---------------------------------------------------------------- 1806;; Unconditional branches 1807;;---------------------------------------------------------------- 1808(define_insn "jump" 1809 [(set (pc) 1810 (label_ref (match_operand 0 "" "")))] 1811 "" 1812 { 1813 if (GET_CODE (operands[0]) == REG) 1814 return "br%?\t%0"; 1815 else 1816 return "bri%?\t%l0"; 1817 } 1818 [(set_attr "type" "jump") 1819 (set_attr "mode" "none") 1820 (set_attr "length" "4")]) 1821 1822(define_expand "indirect_jump" 1823 [(set (pc) (match_operand 0 "register_operand" "d"))] 1824 "" 1825 { 1826 rtx dest = operands[0]; 1827 if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) 1828 operands[0] = copy_to_mode_reg (Pmode, dest); 1829 1830 emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); 1831 DONE; 1832 } 1833) 1834 1835;; Indirect jumps. Jump to register values. Assuming absolute jumps 1836 1837(define_insn "indirect_jump_internal1" 1838 [(set (pc) (match_operand:SI 0 "register_operand" "d"))] 1839 "" 1840 "bra%?\t%0" 1841 [(set_attr "type" "jump") 1842 (set_attr "mode" "none") 1843 (set_attr "length" "4")]) 1844 1845(define_expand "tablejump" 1846 [(set (pc) 1847 (match_operand 0 "register_operand" "d")) 1848 (use (label_ref (match_operand 1 "" "")))] 1849 "" 1850 { 1851 gcc_assert (GET_MODE (operands[0]) == Pmode); 1852 1853 if (!flag_pic || TARGET_PIC_DATA_TEXT_REL) 1854 emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); 1855 else 1856 emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1])); 1857 DONE; 1858 } 1859) 1860 1861(define_insn "tablejump_internal1" 1862 [(set (pc) 1863 (match_operand:SI 0 "register_operand" "d")) 1864 (use (label_ref (match_operand 1 "" "")))] 1865 "" 1866 "bra%?\t%0 " 1867 [(set_attr "type" "jump") 1868 (set_attr "mode" "none") 1869 (set_attr "length" "4")]) 1870 1871(define_expand "tablejump_internal3" 1872 [(parallel [(set (pc) 1873 (plus:SI (match_operand:SI 0 "register_operand" "d") 1874 (label_ref:SI (match_operand:SI 1 "" "")))) 1875 (use (label_ref:SI (match_dup 1)))])] 1876 "" 1877 "" 1878) 1879 1880;; need to change for MicroBlaze PIC 1881(define_insn "" 1882 [(set (pc) 1883 (plus:SI (match_operand:SI 0 "register_operand" "d") 1884 (label_ref:SI (match_operand 1 "" "")))) 1885 (use (label_ref:SI (match_dup 1)))] 1886 "NEXT_INSN (as_a <rtx_insn *> (operands[1])) != 0 1887 && GET_CODE (PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[1])))) == ADDR_DIFF_VEC 1888 && flag_pic" 1889 { 1890 output_asm_insn ("addk\t%0,%0,r20",operands); 1891 return "bra%?\t%0"; 1892} 1893 [(set_attr "type" "jump") 1894 (set_attr "mode" "none") 1895 (set_attr "length" "4")]) 1896 1897(define_expand "tablejump_internal4" 1898 [(parallel [(set (pc) 1899 (plus:DI (match_operand:DI 0 "register_operand" "d") 1900 (label_ref:DI (match_operand:SI 1 "" "")))) 1901 (use (label_ref:DI (match_dup 1)))])] 1902 "" 1903 "" 1904) 1905 1906;;---------------------------------------------------------------- 1907;; Function prologue/epilogue and stack allocation 1908;;---------------------------------------------------------------- 1909(define_expand "prologue" 1910 [(const_int 1)] 1911 "" 1912 { 1913 microblaze_expand_prologue (); 1914 DONE; 1915 } 1916) 1917 1918(define_expand "epilogue" 1919 [(use (const_int 0))] 1920 "" 1921 { 1922 microblaze_expand_epilogue (); 1923 DONE; 1924 } 1925) 1926 1927;; An insn to allocate new stack space for dynamic use (e.g., alloca). 1928;; We copy the return address, decrement the stack pointer and save the 1929;; return address again at the new stack top 1930 1931(define_expand "allocate_stack" 1932 [(set (match_operand 0 "register_operand" "=r") 1933 (minus (reg 1) (match_operand 1 "register_operand" ""))) 1934 (set (reg 1) 1935 (minus (reg 1) (match_dup 1)))] 1936 "" 1937 { 1938 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1939 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1940 rtx neg_op0; 1941 1942 emit_move_insn (rtmp, retaddr); 1943 if (GET_CODE (operands[1]) != CONST_INT) 1944 { 1945 neg_op0 = gen_reg_rtx (Pmode); 1946 emit_insn (gen_negsi2 (neg_op0, operands[1])); 1947 } else 1948 neg_op0 = GEN_INT (- INTVAL (operands[1])); 1949 1950 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0)); 1951 emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp); 1952 emit_move_insn (operands[0], virtual_stack_dynamic_rtx); 1953 emit_insn (gen_rtx_CLOBBER (SImode, rtmp)); 1954 DONE; 1955 } 1956) 1957 1958(define_expand "save_stack_block" 1959 [(match_operand 0 "register_operand" "") 1960 (match_operand 1 "register_operand" "")] 1961 "" 1962 { 1963 emit_move_insn (operands[0], operands[1]); 1964 DONE; 1965 } 1966) 1967 1968(define_expand "restore_stack_block" 1969 [(match_operand 0 "register_operand" "") 1970 (match_operand 1 "register_operand" "")] 1971 "" 1972 { 1973 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1974 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1975 1976 /* Move the retaddr. */ 1977 emit_move_insn (rtmp, retaddr); 1978 emit_move_insn (operands[0], operands[1]); 1979 emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), rtmp); 1980 DONE; 1981 } 1982) 1983 1984;; Trivial return. Make it look like a normal return insn as that 1985;; allows jump optimizations to work better . 1986(define_expand "return" 1987 [(simple_return)] 1988 "microblaze_can_use_return_insn ()" 1989 {} 1990) 1991 1992(define_expand "simple_return" 1993 [(simple_return)] 1994 "" 1995 {} 1996) 1997 1998(define_insn "*<optab>" 1999 [(any_return)] 2000 "" 2001 { 2002 if (microblaze_is_break_handler ()) 2003 return "rtbd\tr16, 8\;%#"; 2004 else if (microblaze_is_interrupt_variant ()) 2005 return "rtid\tr14, 0\;%#"; 2006 else 2007 return "rtsd\tr15, 8\;%#"; 2008 } 2009 [(set_attr "type" "jump") 2010 (set_attr "mode" "none") 2011 (set_attr "length" "4")] 2012) 2013 2014;; Normal return. 2015 2016(define_insn "<optab>_internal" 2017 [(any_return) 2018 (use (match_operand:SI 0 "register_operand" ""))] 2019 "" 2020 { 2021 if (microblaze_is_break_handler ()) 2022 return "rtbd\tr16,8\;%#"; 2023 else if (microblaze_is_interrupt_variant ()) 2024 return "rtid\tr14,0 \;%#"; 2025 else 2026 return "rtsd\tr15,8 \;%#"; 2027 } 2028 [(set_attr "type" "jump") 2029 (set_attr "mode" "none") 2030 (set_attr "length" "4")]) 2031 2032 2033;; Block any insns from across this point 2034;; Useful to group sequences together. 2035(define_insn "blockage" 2036 [(unspec_volatile [(const_int 0)] 0)] 2037 "" 2038 "" 2039 [(set_attr "type" "unknown") 2040 (set_attr "mode" "none") 2041 (set_attr "length" "0")]) 2042 2043 2044;;---------------------------------------------------------------- 2045;; Function calls 2046;;---------------------------------------------------------------- 2047 2048(define_expand "call" 2049 [(parallel [(call (match_operand 0 "memory_operand" "m") 2050 (match_operand 1 "" "i")) 2051 (clobber (reg:SI R_SR)) 2052 (use (match_operand 2 "" "")) 2053 (use (match_operand 3 "" ""))])] 2054 "" 2055 { 2056 rtx addr = XEXP (operands[0], 0); 2057 2058 if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL 2059 && GET_CODE (addr) == SYMBOL_REF 2060 && !SYMBOL_REF_LOCAL_P (addr)) 2061 { 2062 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 2063 XEXP (operands[0], 0) = temp; 2064 } 2065 2066 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 2067 || !call_insn_operand (addr, VOIDmode)) 2068 XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); 2069 2070 if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC) 2071 emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1], 2072 gen_rtx_REG (SImode, 2073 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2074 pic_offset_table_rtx)); 2075 else 2076 emit_call_insn (gen_call_internal0 (operands[0], operands[1], 2077 gen_rtx_REG (SImode, 2078 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2079 2080 DONE; 2081 } 2082) 2083 2084(define_expand "call_internal0" 2085 [(parallel [(call (match_operand 0 "" "") 2086 (match_operand 1 "" "")) 2087 (clobber (match_operand:SI 2 "" ""))])] 2088 "" 2089 { 2090 } 2091) 2092 2093(define_expand "call_internal_plt0" 2094 [(parallel [(call (match_operand 0 "" "") 2095 (match_operand 1 "" "")) 2096 (clobber (match_operand:SI 2 "" "")) 2097 (use (match_operand:SI 3 "" ""))])] 2098 "" 2099 { 2100 } 2101) 2102 2103(define_insn "call_internal_plt" 2104 [(call (mem (match_operand:SI 0 "call_insn_plt_operand" "")) 2105 (match_operand:SI 1 "" "i")) 2106 (clobber (reg:SI R_SR)) 2107 (use (reg:SI R_GOT))] 2108 "flag_pic" 2109 { 2110 register rtx target2 = gen_rtx_REG (Pmode, 2111 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2112 gen_rtx_CLOBBER (VOIDmode, target2); 2113 return "brlid\tr15,%0\;%#"; 2114 } 2115 [(set_attr "type" "call") 2116 (set_attr "mode" "none") 2117 (set_attr "length" "4")]) 2118 2119(define_insn "call_internal1" 2120 [(call (mem (match_operand:VOID 0 "call_insn_simple_operand" "ri")) 2121 (match_operand:SI 1 "" "i")) 2122 (clobber (reg:SI R_SR))] 2123 "" 2124 { 2125 register rtx target = operands[0]; 2126 register rtx target2 = gen_rtx_REG (Pmode, 2127 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2128 if (GET_CODE (target) == SYMBOL_REF) { 2129 if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) { 2130 gen_rtx_CLOBBER (VOIDmode, target2); 2131 return "brki\tr16,%0\;%#"; 2132 } 2133 else { 2134 gen_rtx_CLOBBER (VOIDmode, target2); 2135 return "brlid\tr15,%0\;%#"; 2136 } 2137 } else if (GET_CODE (target) == CONST_INT) 2138 return "la\t%@,r0,%0\;brald\tr15,%@\;%#"; 2139 else if (GET_CODE (target) == REG) 2140 return "brald\tr15,%0\;%#"; 2141 else { 2142 fprintf (stderr,"Unsupported call insn\n"); 2143 return NULL; 2144 } 2145 } 2146 [(set_attr "type" "call") 2147 (set_attr "mode" "none") 2148 (set_attr "length" "4")]) 2149 2150;; calls.c now passes a fourth argument, make saber happy 2151 2152(define_expand "call_value" 2153 [(parallel [(set (match_operand 0 "register_operand" "=d") 2154 (call (match_operand 1 "memory_operand" "m") 2155 (match_operand 2 "" "i"))) 2156 (clobber (reg:SI R_SR)) 2157 (use (match_operand 3 "" ""))])] ;; next_arg_reg 2158 "" 2159 { 2160 rtx addr = XEXP (operands[1], 0); 2161 2162 if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL 2163 && GET_CODE (addr) == SYMBOL_REF 2164 && !SYMBOL_REF_LOCAL_P (addr)) 2165 { 2166 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 2167 XEXP (operands[1], 0) = temp; 2168 } 2169 2170 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 2171 || !call_insn_operand (addr, VOIDmode)) 2172 XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); 2173 2174 if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC) 2175 emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1], 2176 operands[2], 2177 gen_rtx_REG (SImode, 2178 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2179 pic_offset_table_rtx)); 2180 else 2181 emit_call_insn (gen_call_value_internal (operands[0], operands[1], 2182 operands[2], 2183 gen_rtx_REG (SImode, 2184 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2185 2186 DONE; 2187 } 2188) 2189 2190 2191(define_expand "call_value_internal" 2192 [(parallel [(set (match_operand 0 "" "") 2193 (call (match_operand 1 "" "") 2194 (match_operand 2 "" ""))) 2195 (clobber (match_operand:SI 3 "" "")) 2196 ])] 2197 "" 2198 {} 2199) 2200 2201(define_expand "call_value_intern_plt0" 2202 [(parallel[(set (match_operand 0 "" "") 2203 (call (match_operand 1 "" "") 2204 (match_operand 2 "" ""))) 2205 (clobber (match_operand:SI 3 "" "")) 2206 (use (match_operand:SI 4 "" ""))])] 2207 "flag_pic" 2208 {} 2209) 2210 2211(define_insn "call_value_intern_plt" 2212 [(set (match_operand:VOID 0 "register_operand" "=d") 2213 (call (mem (match_operand:SI 1 "call_insn_plt_operand" "")) 2214 (match_operand:SI 2 "" "i"))) 2215 (clobber (match_operand:SI 3 "register_operand" "=d")) 2216 (use (match_operand:SI 4 "register_operand"))] 2217 "flag_pic" 2218 { 2219 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2220 2221 gen_rtx_CLOBBER (VOIDmode,target2); 2222 return "brlid\tr15,%1\;%#"; 2223 } 2224 [(set_attr "type" "call") 2225 (set_attr "mode" "none") 2226 (set_attr "length" "4")]) 2227 2228(define_insn "call_value_intern" 2229 [(set (match_operand:VOID 0 "register_operand" "=d") 2230 (call (mem (match_operand:VOID 1 "call_insn_operand" "ri")) 2231 (match_operand:SI 2 "" "i"))) 2232 (clobber (match_operand:SI 3 "register_operand" "=d"))] 2233 "" 2234 { 2235 register rtx target = operands[1]; 2236 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2237 2238 if (GET_CODE (target) == SYMBOL_REF) 2239 { 2240 gen_rtx_CLOBBER (VOIDmode,target2); 2241 if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) 2242 return "brki\tr16,%1\;%#"; 2243 else if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION) 2244 { 2245 return "brlid\tr15,%1\;%#"; 2246 } 2247 else 2248 { 2249 return "bralid\tr15,%1\;%#"; 2250 } 2251 } 2252 else if (GET_CODE (target) == CONST_INT) 2253 return "la\t%@,r0,%1\;brald\tr15,%@\;%#"; 2254 else if (GET_CODE (target) == REG) 2255 return "brald\tr15,%1\;%#"; 2256 else 2257 return "Unsupported call insn\n"; 2258 } 2259 [(set_attr "type" "call") 2260 (set_attr "mode" "none") 2261 (set_attr "length" "4")]) 2262 2263 2264;; Call subroutine returning any type. 2265(define_expand "untyped_call" 2266 [(parallel [(call (match_operand 0 "" "") 2267 (const_int 0)) 2268 (match_operand 1 "" "") 2269 (match_operand 2 "" "")])] 2270 "" 2271 { 2272 if (operands[0]) /* silence statement not reached warnings */ 2273 { 2274 int i; 2275 2276 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); 2277 2278 for (i = 0; i < XVECLEN (operands[2], 0); i++) 2279 { 2280 rtx set = XVECEXP (operands[2], 0, i); 2281 emit_move_insn (SET_DEST (set), SET_SRC (set)); 2282 } 2283 2284 emit_insn (gen_blockage ()); 2285 DONE; 2286 } 2287 } 2288) 2289 2290;;---------------------------------------------------------------- 2291;; Misc. 2292;;---------------------------------------------------------------- 2293 2294(define_insn "nop" 2295 [(const_int 0)] 2296 "" 2297 "nop" 2298 [(set_attr "type" "nop") 2299 (set_attr "mode" "none") 2300 (set_attr "length" "4")]) 2301 2302;; Trap instruction pattern for __builtin_trap. Same as the glibc ABORT_INSTRUCTION 2303(define_insn "trap" 2304 [(trap_if (const_int 1) (const_int 0))] 2305 "" 2306 "brki\tr0,-1" 2307 [(set_attr "type" "trap")] 2308) 2309 2310;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference 2311;; between "mfs" and "addik" instructions. 2312(define_insn "set_got" 2313 [(set (match_operand:SI 0 "register_operand" "=r") 2314 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))] 2315 "" 2316 "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8" 2317 [(set_attr "type" "multi") 2318 (set_attr "length" "12")]) 2319 2320;; The insn to set TEXT. 2321;; The hardcoded number "8" accounts for $pc difference 2322;; between "mfs" and "addik" instructions. 2323(define_insn "set_text" 2324 [(set (match_operand:SI 0 "register_operand" "=r") 2325 (unspec:SI[(const_int 0)] UNSPEC_SET_TEXT))] 2326 "" 2327 "mfs\t%0,rpc\n\taddik\t%0,%0,8@TXTPCREL" 2328 [(set_attr "type" "multi") 2329 (set_attr "length" "12")]) 2330 2331 2332;; This insn gives the count of leading number of zeros for the second 2333;; operand and stores the result in first operand. 2334(define_insn "clzsi2" 2335 [(set (match_operand:SI 0 "register_operand" "=r") 2336 (clz:SI (match_operand:SI 1 "register_operand" "r")))] 2337 "TARGET_HAS_CLZ" 2338 "clz\t%0,%1" 2339 [(set_attr "type" "arith") 2340 (set_attr "mode" "SI") 2341 (set_attr "length" "4")]) 2342 2343; This is used in compiling the unwind routines. 2344(define_expand "eh_return" 2345 [(use (match_operand 0 "general_operand" ""))] 2346 "" 2347 " 2348{ 2349 microblaze_eh_return (operands[0]); 2350 DONE; 2351}") 2352 2353(include "sync.md") 2354