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