1;; microblaze.md -- Machine description for Xilinx MicroBlaze processors. 2;; Copyright (C) 2009-2013 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 "@ 522 rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1" 523 [(set_attr "type" "darith") 524 (set_attr "mode" "DI") 525 (set_attr "length" "8")]) 526 527 528;;---------------------------------------------------------------- 529;; Multiplication 530;;---------------------------------------------------------------- 531 532(define_insn "mulsi3" 533 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 534 (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") 535 (match_operand:SI 2 "arith_operand" "d,I,i")))] 536 "!TARGET_SOFT_MUL" 537 "@ 538 mul\t%0,%1,%2 539 muli\t%0,%1,%2 540 muli\t%0,%1,%2" 541 [(set_attr "type" "imul,imul,no_delay_imul") 542 (set_attr "mode" "SI") 543 (set_attr "length" "4,4,8")]) 544 545(define_insn "mulsidi3" 546 [(set (match_operand:DI 0 "register_operand" "=&d") 547 (mult:DI 548 (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) 549 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 550 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 551 "mul\t%L0,%1,%2\;mulh\t%M0,%1,%2" 552 [(set_attr "type" "no_delay_arith") 553 (set_attr "mode" "DI") 554 (set_attr "length" "8")]) 555 556(define_insn "umulsidi3" 557 [(set (match_operand:DI 0 "register_operand" "=&d") 558 (mult:DI 559 (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 560 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 561 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 562 "mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2" 563 [(set_attr "type" "no_delay_arith") 564 (set_attr "mode" "DI") 565 (set_attr "length" "8")]) 566 567(define_insn "usmulsidi3" 568 [(set (match_operand:DI 0 "register_operand" "=&d") 569 (mult:DI 570 (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 571 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] 572 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 573 "mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1" 574 [(set_attr "type" "no_delay_arith") 575 (set_attr "mode" "DI") 576 (set_attr "length" "8")]) 577 578(define_insn "*smulsi3_highpart" 579 [(set (match_operand:SI 0 "register_operand" "=d") 580 (truncate:SI 581 (lshiftrt:DI 582 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) 583 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))) 584 (const_int 32))))] 585 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 586 "mulh\t%0,%1,%2" 587 [(set_attr "type" "imul") 588 (set_attr "mode" "SI") 589 (set_attr "length" "4")]) 590 591(define_insn "*umulsi3_highpart" 592 [(set (match_operand:SI 0 "register_operand" "=d") 593 (truncate:SI 594 (lshiftrt:DI 595 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 596 (zero_extend:DI (match_operand:SI 2 "register_operand" "d")) 597) 598 (const_int 32))))] 599 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 600 "mulhu\t%0,%1,%2" 601 [(set_attr "type" "imul") 602 (set_attr "mode" "SI") 603 (set_attr "length" "4")]) 604 605(define_insn "*usmulsi3_highpart" 606 [(set (match_operand:SI 0 "register_operand" "=d") 607 (truncate:SI 608 (lshiftrt:DI 609 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) 610 (sign_extend:DI (match_operand:SI 2 "register_operand" "d")) 611) 612 (const_int 32))))] 613 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH" 614 "mulhsu\t%0,%2,%1" 615 [(set_attr "type" "imul") 616 (set_attr "mode" "SI") 617 (set_attr "length" "4")]) 618 619 620;;---------------------------------------------------------------- 621;; Division and remainder 622;;---------------------------------------------------------------- 623(define_expand "divsi3" 624 [(set (match_operand:SI 0 "register_operand" "=d") 625 (div:SI (match_operand:SI 1 "register_operand" "d") 626 (match_operand:SI 2 "register_operand" "d"))) 627 ] 628 "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)" 629 { 630 if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES) 631 { 632 microblaze_expand_divide (operands); 633 DONE; 634 } 635 else if (!TARGET_SOFT_DIV) 636 { 637 emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2])); 638 DONE; 639 } 640 } 641) 642 643 644(define_insn "divsi3_internal" 645 [(set (match_operand:SI 0 "register_operand" "=d") 646 (div:SI (match_operand:SI 1 "register_operand" "d") 647 (match_operand:SI 2 "register_operand" "d"))) 648 ] 649 "!TARGET_SOFT_DIV" 650 "idiv\t%0,%2,%1" 651 [(set_attr "type" "idiv") 652 (set_attr "mode" "SI") 653 (set_attr "length" "4")] 654) 655 656(define_insn "udivsi3" 657 [(set (match_operand:SI 0 "register_operand" "=d") 658 (udiv:SI (match_operand:SI 1 "register_operand" "d") 659 (match_operand:SI 2 "register_operand" "d"))) 660 ] 661 "!TARGET_SOFT_DIV" 662 "idivu\t%0,%2,%1" 663 [(set_attr "type" "idiv") 664 (set_attr "mode" "SI") 665 (set_attr "length" "4")]) 666 667 668;;---------------------------------------------------------------- 669;; Negation and one's complement 670;;---------------------------------------------------------------- 671 672(define_insn "negsi2" 673 [(set (match_operand:SI 0 "register_operand" "=d") 674 (neg:SI (match_operand:SI 1 "register_operand" "d")))] 675 "" 676 "rsubk\t%0,%1,r0" 677 [(set_attr "type" "arith") 678 (set_attr "mode" "SI") 679 (set_attr "length" "4")]) 680 681(define_insn "negdi2" 682 [(set (match_operand:DI 0 "register_operand" "=d") 683 (neg:DI (match_operand:DI 1 "register_operand" "d")))] 684 "" 685 "rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0" 686 [(set_attr "type" "darith") 687 (set_attr "mode" "DI") 688 (set_attr "length" "8")]) 689 690 691(define_insn "one_cmplsi2" 692 [(set (match_operand:SI 0 "register_operand" "=d") 693 (not:SI (match_operand:SI 1 "register_operand" "d")))] 694 "" 695 "xori\t%0,%1,-1" 696 [(set_attr "type" "arith") 697 (set_attr "mode" "SI") 698 (set_attr "length" "4")]) 699 700(define_insn "*one_cmpldi2" 701 [(set (match_operand:DI 0 "register_operand" "=d") 702 (not:DI (match_operand:DI 1 "register_operand" "d")))] 703 "" 704 "nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1" 705 [(set_attr "type" "darith") 706 (set_attr "mode" "DI") 707 (set_attr "length" "8")] 708) 709 710(define_split 711 [(set (match_operand:DI 0 "register_operand" "") 712 (not:DI (match_operand:DI 1 "register_operand" "")))] 713 "reload_completed 714 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 715 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" 716 717 [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0))) 718 (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))] 719 "") 720 721 722;;---------------------------------------------------------------- 723;; Logical 724;;---------------------------------------------------------------- 725 726(define_insn "andsi3" 727 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") 728 (and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d") 729 (match_operand:SI 2 "arith_operand" "d,I,i,M")))] 730 "" 731 "@ 732 and\t%0,%1,%2 733 andi\t%0,%1,%2 #and1 734 andi\t%0,%1,%2 #and2 735 andi\t%0,%1,%2 #and3" 736 [(set_attr "type" "arith,arith,no_delay_arith,no_delay_arith") 737 (set_attr "mode" "SI,SI,SI,SI") 738 (set_attr "length" "4,8,8,8")]) 739 740 741(define_insn "iorsi3" 742 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d") 743 (ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d") 744 (match_operand:SI 2 "arith_operand" "d,I,M,i")))] 745 "" 746 "@ 747 or\t%0,%1,%2 748 ori\t%0,%1,%2 749 ori\t%0,%1,%2 750 ori\t%0,%1,%2" 751 [(set_attr "type" "arith,no_delay_arith,no_delay_arith,no_delay_arith") 752 (set_attr "mode" "SI,SI,SI,SI") 753 (set_attr "length" "4,8,8,8")]) 754 755(define_insn "xorsi3" 756 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 757 (xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d") 758 (match_operand:SI 2 "arith_operand" "d,I,i")))] 759 "" 760 "@ 761 xor\t%0,%1,%2 762 xori\t%0,%1,%2 763 xori\t%0,%1,%2" 764 [(set_attr "type" "arith,arith,no_delay_arith") 765 (set_attr "mode" "SI,SI,SI") 766 (set_attr "length" "4,8,8")]) 767 768;;---------------------------------------------------------------- 769;; Zero extension 770;;---------------------------------------------------------------- 771 772(define_insn "zero_extendhisi2" 773 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 774 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))] 775 "" 776 "@ 777 andi\t%0,%1,0xffff 778 lhu%i1\t%0,%1 779 lhu%i1\t%0,%1" 780 [(set_attr "type" "no_delay_arith,load,no_delay_load") 781 (set_attr "mode" "SI,SI,SI") 782 (set_attr "length" "8,4,8")]) 783 784(define_insn "zero_extendqihi2" 785 [(set (match_operand:HI 0 "register_operand" "=d,d,d") 786 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] 787 "" 788 "@ 789 andi\t%0,%1,0x00ff 790 lbu%i1\t%0,%1 791 lbu%i1\t%0,%1" 792 [(set_attr "type" "arith,load,no_delay_load") 793 (set_attr "mode" "HI") 794 (set_attr "length" "4,4,8")]) 795 796(define_insn "zero_extendqisi2" 797 [(set (match_operand:SI 0 "register_operand" "=d,d,d") 798 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))] 799 "" 800 "@ 801 andi\t%0,%1,0x00ff 802 lbu%i1\t%0,%1 803 lbu%i1\t%0,%1" 804 [(set_attr "type" "arith,load,no_delay_load") 805 (set_attr "mode" "SI,SI,SI") 806 (set_attr "length" "4,4,8")]) 807 808;;---------------------------------------------------------------- 809;; Sign extension 810;;---------------------------------------------------------------- 811 812;; basic Sign Extend Operations 813 814(define_insn "extendqisi2" 815 [(set (match_operand:SI 0 "register_operand" "=d") 816 (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))] 817 "" 818 "sext8\t%0,%1" 819 [(set_attr "type" "arith") 820 (set_attr "mode" "SI") 821 (set_attr "length" "4")]) 822 823(define_insn "extendhisi2" 824 [(set (match_operand:SI 0 "register_operand" "=d") 825 (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))] 826 "" 827 "sext16\t%0,%1" 828 [(set_attr "type" "arith") 829 (set_attr "mode" "SI") 830 (set_attr "length" "4")]) 831 832;; Those for integer source operand are ordered 833;; widest source type first. 834 835(define_insn "extendsidi2" 836 [(set (match_operand:DI 0 "register_operand" "=d,d,d") 837 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] 838 "" 839 { 840 if (which_alternative == 0) 841 output_asm_insn ("addk\t%L0,r0,%1", operands); 842 else 843 output_asm_insn ("lw%i1\t%L0,%1", operands); 844 845 output_asm_insn ("add\t%M0,%L0,%L0", operands); 846 output_asm_insn ("addc\t%M0,r0,r0", operands); 847 output_asm_insn ("beqi\t%M0,.+8", operands); 848 return "addi\t%M0,r0,0xffffffff"; 849 } 850 [(set_attr "type" "multi,multi,multi") 851 (set_attr "mode" "DI") 852 (set_attr "length" "20,20,20")]) 853 854;;---------------------------------------------------------------- 855;; Data movement 856;;---------------------------------------------------------------- 857 858;; 64-bit integer moves 859 860;; Unlike most other insns, the move insns can't be split with 861;; different predicates, because register spilling and other parts of 862;; the compiler, have memoized the insn number already. 863 864(define_expand "movdi" 865 [(set (match_operand:DI 0 "nonimmediate_operand" "") 866 (match_operand:DI 1 "general_operand" ""))] 867 "" 868 { 869 /* If operands[1] is a constant address illegal for pic, then we need to 870 handle it just like microblaze_legitimize_address does. */ 871 if (flag_pic && pic_address_needs_scratch (operands[1])) 872 { 873 rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0)); 874 rtx temp2 = XEXP (XEXP (operands[1], 0), 1); 875 emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2)); 876 DONE; 877 } 878 879 880 if ((reload_in_progress | reload_completed) == 0 881 && !register_operand (operands[0], DImode) 882 && !register_operand (operands[1], DImode) 883 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 884 && operands[1] != CONST0_RTX (DImode)))) 885 { 886 887 rtx temp = force_reg (DImode, operands[1]); 888 emit_move_insn (operands[0], temp); 889 DONE; 890 } 891 } 892) 893 894 895 896(define_insn "*movdi_internal" 897 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o") 898 (match_operand:DI 1 "general_operand" " d,i,J,R,o,d,d"))] 899 "" 900 { 901 switch (which_alternative) 902 { 903 case 0: 904 return "addk\t%0,%1\n\taddk\t%D0,%d1"; 905 case 1: 906 return "addik\t%M0,r0,%h1\n\taddik\t%L0,r0,%j1 #li => la"; 907 case 2: 908 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0"; 909 case 3: 910 case 4: 911 if (reg_mentioned_p (operands[0], operands[1])) 912 return "lwi\t%D0,%o1\n\tlwi\t%0,%1"; 913 else 914 return "lwi\t%0,%1\n\tlwi\t%D0,%o1"; 915 case 5: 916 case 6: 917 return "swi\t%1,%0\n\tswi\t%D1,%o0"; 918 } 919 return "unreachable"; 920 } 921 [(set_attr "type" "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store") 922 (set_attr "mode" "DI") 923 (set_attr "length" "8,8,8,8,12,8,12")]) 924 925(define_split 926 [(set (match_operand:DI 0 "register_operand" "") 927 (match_operand:DI 1 "register_operand" ""))] 928 "reload_completed 929 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 930 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 931 && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))" 932 933 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4)) 934 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))] 935 "") 936 937(define_split 938 [(set (match_operand:DI 0 "register_operand" "") 939 (match_operand:DI 1 "register_operand" ""))] 940 "reload_completed 941 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 942 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 943 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))" 944 945 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) 946 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] 947 "") 948 949;; Unlike most other insns, the move insns can't be split with 950;; different predicates, because register spilling and other parts of 951;; the compiler, have memoized the insn number already. 952 953(define_expand "movsi" 954 [(set (match_operand:SI 0 "nonimmediate_operand" "") 955 (match_operand:SI 1 "general_operand" ""))] 956 "" 957 { 958 if (microblaze_expand_move (SImode, operands)) DONE; 959 } 960) 961 962;; Added for status registers 963(define_insn "movsi_status" 964 [(set (match_operand:SI 0 "register_operand" "=d,d,z") 965 (match_operand:SI 1 "register_operand" "z,d,d"))] 966 "microblaze_is_interrupt_variant ()" 967 "@ 968 mfs\t%0,%1 #mfs 969 addk\t%0,%1,r0 #add movsi 970 mts\t%0,%1 #mts" 971 [(set_attr "type" "move") 972 (set_attr "mode" "SI") 973 (set_attr "length" "12")]) 974 975;; This move will be not be moved to delay slot. 976(define_insn "*movsi_internal3" 977 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d") 978 (match_operand:SI 1 "immediate_operand" "J,I,Mnis"))] 979 "(register_operand (operands[0], SImode) && 980 (GET_CODE (operands[1]) == CONST_INT && 981 (INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))" 982 "@ 983 addk\t%0,r0,r0 984 addik\t%0,r0,%1\t# %X1 985 addik\t%0,r0,%1\t# %X1" 986 [(set_attr "type" "arith,arith,no_delay_arith") 987 (set_attr "mode" "SI") 988 (set_attr "length" "4")]) 989 990;; This move may be used for PLT label operand 991(define_insn "*movsi_internal5_pltop" 992 [(set (match_operand:SI 0 "register_operand" "=d,d") 993 (match_operand:SI 1 "call_insn_operand" ""))] 994 "(register_operand (operands[0], Pmode) && 995 PLT_ADDR_P (operands[1]))" 996 { 997 gcc_unreachable (); 998 } 999 [(set_attr "type" "load") 1000 (set_attr "mode" "SI") 1001 (set_attr "length" "4")]) 1002 1003(define_insn "*movsi_internal2" 1004 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R,m") 1005 (match_operand:SI 1 "move_src_operand" " d,I,Mnis,R,m,dJ,dJ"))] 1006 "" 1007 "@ 1008 addk\t%0,%1,r0 1009 addik\t%0,r0,%1\t# %X1 1010 addik\t%0,%a1 1011 lw%i1\t%0,%1 1012 lw%i1\t%0,%1 1013 sw%i0\t%z1,%0 1014 sw%i0\t%z1,%0" 1015 [(set_attr "type" "load,load,no_delay_load,load,no_delay_load,store,no_delay_store") 1016 (set_attr "mode" "SI") 1017 (set_attr "length" "4,4,8,4,8,4,8")]) 1018 1019 1020;; 16-bit Integer moves 1021 1022;; Unlike most other insns, the move insns can't be split with 1023;; different predicates, because register spilling and other parts of 1024;; the compiler, have memoized the insn number already. 1025;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined 1026 1027(define_expand "movhi" 1028 [(set (match_operand:HI 0 "nonimmediate_operand" "") 1029 (match_operand:HI 1 "general_operand" ""))] 1030 "" 1031 { 1032 if ((reload_in_progress | reload_completed) == 0 1033 && !register_operand (operands[0], HImode) 1034 && !register_operand (operands[1], HImode) 1035 && ((GET_CODE (operands[1]) != CONST_INT 1036 || INTVAL (operands[1]) != 0))) 1037 { 1038 rtx temp = force_reg (HImode, operands[1]); 1039 emit_move_insn (operands[0], temp); 1040 DONE; 1041 } 1042 } 1043) 1044 1045(define_insn "*movhi_internal2" 1046 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m") 1047 (match_operand:HI 1 "general_operand" "I,d,R,m,dJ,dJ"))] 1048 "" 1049 "@ 1050 addik\t%0,r0,%1\t# %X1 1051 addk\t%0,%1,r0 1052 lhui\t%0,%1 1053 lhui\t%0,%1 1054 sh%i0\t%z1,%0 1055 sh%i0\t%z1,%0" 1056 [(set_attr "type" "arith,move,load,no_delay_load,store,no_delay_store") 1057 (set_attr "mode" "HI") 1058 (set_attr "length" "4,4,4,8,8,8")]) 1059 1060;; 8-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 "movqi" 1068 [(set (match_operand:QI 0 "nonimmediate_operand" "") 1069 (match_operand:QI 1 "general_operand" ""))] 1070 "" 1071 { 1072 if ((reload_in_progress | reload_completed) == 0 1073 && !register_operand (operands[0], QImode) 1074 && !register_operand (operands[1], QImode) 1075 && ((GET_CODE (operands[1]) != CONST_INT 1076 || INTVAL (operands[1]) != 0))) 1077 { 1078 rtx temp = force_reg (QImode, operands[1]); 1079 emit_move_insn (operands[0], temp); 1080 DONE; 1081 } 1082 } 1083) 1084 1085(define_insn "*movqi_internal2" 1086 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m") 1087 (match_operand:QI 1 "general_operand" "J,I,d,R,m,dJ,dJ"))] 1088 "" 1089 "@ 1090 addk\t%0,r0,%z1 1091 addik\t%0,r0,%1\t# %X1 1092 addk\t%0,%1,r0 1093 lbu%i1\t%0,%1 1094 lbu%i1\t%0,%1 1095 sb%i0\t%z1,%0 1096 sbi\t%z1,%0" 1097 [(set_attr "type" "arith,arith,move,load,no_delay_load,store,no_delay_store") 1098 (set_attr "mode" "QI") 1099 (set_attr "length" "4,4,8,4,8,4,8")]) 1100 1101;; Block moves, see microblaze.c for more details. 1102;; Argument 0 is the destination 1103;; Argument 1 is the source 1104;; Argument 2 is the length 1105;; Argument 3 is the alignment 1106 1107(define_expand "movmemsi" 1108 [(parallel [(set (match_operand:BLK 0 "general_operand") 1109 (match_operand:BLK 1 "general_operand")) 1110 (use (match_operand:SI 2 "")) 1111 (use (match_operand:SI 3 "const_int_operand"))])] 1112 "" 1113 { 1114 if (microblaze_expand_block_move (operands[0], operands[1], 1115 operands[2], operands[3])) 1116 DONE; 1117 else 1118 FAIL; 1119 } 1120) 1121 1122;;Load and store reverse 1123(define_insn "movsi4_rev" 1124 [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Q") 1125 (bswap:SI (match_operand:SF 1 "reg_or_mem_operand" "Q,r")))] 1126 "TARGET_REORDER" 1127 "@ 1128 lwr\t%0,%y1,r0 1129 swr\t%1,%y0,r0" 1130 [(set_attr "type" "load,store") 1131 (set_attr "mode" "SI") 1132 (set_attr "length" "4,4")]) 1133 1134;; 32-bit floating point moves 1135 1136(define_expand "movsf" 1137 [(set (match_operand:SF 0 "nonimmediate_operand" "") 1138 (match_operand:SF 1 "general_operand" ""))] 1139 "" 1140 { 1141 if ((reload_in_progress | reload_completed) == 0 1142 && !register_operand (operands[0], SFmode) 1143 && !register_operand (operands[1], SFmode) 1144 && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1145 && operands[1] != CONST0_RTX (SFmode)))) 1146 { 1147 rtx temp = force_reg (SFmode, operands[1]); 1148 emit_move_insn (operands[0], temp); 1149 DONE; 1150 } 1151 } 1152) 1153 1154;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1155;; 1156(define_insn "*movsf_internal" 1157 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m") 1158 (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))] 1159 "(register_operand (operands[0], SFmode) 1160 || register_operand (operands[1], SFmode) 1161 || operands[1] == CONST0_RTX (SFmode))" 1162 "@ 1163 addk\t%0,r0,r0 1164 addk\t%0,%1,r0 1165 lw%i1\t%0,%1 1166 addik\t%0,r0,%F1 1167 lw%i1\t%0,%1 1168 sw%i0\t%z1,%0 1169 swi\t%z1,%0" 1170 [(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store") 1171 (set_attr "mode" "SF") 1172 (set_attr "length" "4,4,4,4,4,4,4")]) 1173 1174;; 64-bit floating point moves 1175(define_expand "movdf" 1176 [(set (match_operand:DF 0 "nonimmediate_operand" "") 1177 (match_operand:DF 1 "general_operand" ""))] 1178 "" 1179 { 1180 if (flag_pic == 2) { 1181 if (GET_CODE (operands[1]) == MEM 1182 && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0)) 1183 { 1184 rtx ptr_reg; 1185 rtx result; 1186 ptr_reg = force_reg (Pmode, XEXP (operands[1],0)); 1187 result = gen_rtx_MEM (DFmode, ptr_reg); 1188 emit_move_insn (operands[0], result); 1189 DONE; 1190 } 1191 } 1192 if ((reload_in_progress | reload_completed) == 0 1193 && !register_operand (operands[0], DFmode) 1194 && !register_operand (operands[1], DFmode) 1195 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1196 && operands[1] != CONST0_RTX (DFmode)))) 1197 { 1198 rtx temp = force_reg (DFmode, operands[1]); 1199 emit_move_insn (operands[0], temp); 1200 DONE; 1201 } 1202 } 1203) 1204 1205;; movdf_internal 1206;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1207;; 1208(define_insn "*movdf_internal" 1209 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o") 1210 (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))] 1211 "" 1212 { 1213 switch (which_alternative) 1214 { 1215 case 0: 1216 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0"; 1217 case 1: 1218 case 3: 1219 if (reg_mentioned_p (operands[0], operands[1])) 1220 return "lwi\t%D0,%o1\n\tlwi\t%0,%1"; 1221 else 1222 return "lwi\t%0,%1\n\tlwi\t%D0,%o1"; 1223 case 2: 1224 { 1225 return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo"; 1226 } 1227 case 4: 1228 return "swi\t%1,%0\n\tswi\t%D1,%o0"; 1229 } 1230 gcc_unreachable (); 1231 } 1232 [(set_attr "type" "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store") 1233 (set_attr "mode" "DF") 1234 (set_attr "length" "4,8,8,16,8")]) 1235 1236(define_split 1237 [(set (match_operand:DF 0 "register_operand" "") 1238 (match_operand:DF 1 "register_operand" ""))] 1239 "reload_completed 1240 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 1241 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 1242 && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))" 1243 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4)) 1244 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))] 1245 "") 1246 1247(define_split 1248 [(set (match_operand:DF 0 "register_operand" "") 1249 (match_operand:DF 1 "register_operand" ""))] 1250 "reload_completed 1251 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 1252 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 1253 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))" 1254 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0)) 1255 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] 1256 "") 1257 1258;;---------------------------------------------------------------- 1259;; Shifts 1260;;---------------------------------------------------------------- 1261 1262;;---------------------------------------------------------------- 1263;; 32-bit left shifts 1264;;---------------------------------------------------------------- 1265(define_expand "ashlsi3" 1266 [(set (match_operand:SI 0 "register_operand" "=&d") 1267 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1268 (match_operand:SI 2 "arith_operand" "")))] 1269 "" 1270 { 1271 /* Avoid recursion for trivial cases. */ 1272 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1273 if (microblaze_expand_shift (operands)) 1274 DONE; 1275 } 1276) 1277 1278;; Irrespective of if we have a barrel-shifter or not, we want to match 1279;; shifts by 1 with a special pattern. When a barrel shifter is present, 1280;; saves a cycle. If not, allows us to annotate the instruction for delay 1281;; slot optimization 1282(define_insn "*ashlsi3_byone" 1283 [(set (match_operand:SI 0 "register_operand" "=d") 1284 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1285 (match_operand:SI 2 "arith_operand" "I")))] 1286 "(INTVAL (operands[2]) == 1)" 1287 "addk\t%0,%1,%1" 1288 [(set_attr "type" "arith") 1289 (set_attr "mode" "SI") 1290 (set_attr "length" "4")] 1291) 1292 1293;; Barrel shift left 1294(define_insn "ashlsi3_bshift" 1295 [(set (match_operand:SI 0 "register_operand" "=d,d") 1296 (ashift:SI (match_operand:SI 1 "register_operand" "d,d") 1297 (match_operand:SI 2 "arith_operand" "I,d")))] 1298 "TARGET_BARREL_SHIFT" 1299 "@ 1300 bslli\t%0,%1,%2 1301 bsll\t%0,%1,%2" 1302 [(set_attr "type" "bshift,bshift") 1303 (set_attr "mode" "SI,SI") 1304 (set_attr "length" "4,4")] 1305) 1306 1307;; The following patterns apply when there is no barrel shifter present 1308 1309(define_insn "*ashlsi3_with_mul_delay" 1310 [(set (match_operand:SI 0 "register_operand" "=d") 1311 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1312 (match_operand:SI 2 "immediate_operand" "I")))] 1313 "!TARGET_SOFT_MUL 1314 && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)" 1315 "muli\t%0,%1,%m2" 1316 ;; This MUL will not generate an imm. Can go into a delay slot. 1317 [(set_attr "type" "arith") 1318 (set_attr "mode" "SI") 1319 (set_attr "length" "4")] 1320) 1321 1322(define_insn "*ashlsi3_with_mul_nodelay" 1323 [(set (match_operand:SI 0 "register_operand" "=d") 1324 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1325 (match_operand:SI 2 "immediate_operand" "I")))] 1326 "!TARGET_SOFT_MUL" 1327 "muli\t%0,%1,%m2" 1328 ;; This MUL will generate an IMM. Cannot go into a delay slot 1329 [(set_attr "type" "no_delay_arith") 1330 (set_attr "mode" "SI") 1331 (set_attr "length" "8")] 1332) 1333 1334(define_insn "*ashlsi3_with_size_opt" 1335 [(set (match_operand:SI 0 "register_operand" "=&d") 1336 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1337 (match_operand:SI 2 "immediate_operand" "I")))] 1338 "(INTVAL (operands[2]) > 5 && optimize_size)" 1339 { 1340 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1341 1342 output_asm_insn ("ori\t%3,r0,%2", operands); 1343 if (REGNO (operands[0]) != REGNO (operands[1])) 1344 output_asm_insn ("addk\t%0,%1,r0", operands); 1345 1346 output_asm_insn ("addik\t%3,%3,-1", operands); 1347 output_asm_insn ("bneid\t%3,.-4", operands); 1348 return "addk\t%0,%0,%0"; 1349 } 1350 [(set_attr "type" "multi") 1351 (set_attr "mode" "SI") 1352 (set_attr "length" "20")] 1353) 1354 1355(define_insn "*ashlsi3_with_rotate" 1356 [(set (match_operand:SI 0 "register_operand" "=&d") 1357 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1358 (match_operand:SI 2 "immediate_operand" "I")))] 1359 "(INTVAL (operands[2]) > 17 && !optimize_size)" 1360 { 1361 int i, nshift; 1362 1363 nshift = INTVAL (operands[2]); 1364 operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode); 1365 1366 /* We do one extra shift so that the first bit (carry) coming into the MSB 1367 will be masked out */ 1368 output_asm_insn ("src\t%0,%1", operands); 1369 for (i = 0; i < (32 - nshift); i++) 1370 output_asm_insn ("src\t%0,%0", operands); 1371 1372 return "andi\t%0,%0,%3"; 1373 } 1374 [(set_attr "type" "multi") 1375 (set_attr "mode" "SI") 1376 (set_attr "length" "80")] 1377) 1378 1379(define_insn "*ashlsi_inline" 1380 [(set (match_operand:SI 0 "register_operand" "=&d") 1381 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1382 (match_operand:SI 2 "immediate_operand" "I")))] 1383 "" 1384 { 1385 int i; 1386 int nshift = INTVAL (operands[2]); 1387 if (REGNO (operands[0]) != REGNO (operands[1])) 1388 output_asm_insn ("addk\t%0,r0,%1", operands); 1389 output_asm_insn ("addk\t%0,%1,%1", operands); 1390 for (i = 0; i < (nshift - 2); i++) 1391 output_asm_insn ("addk\t%0,%0,%0", operands); 1392 return "addk\t%0,%0,%0"; 1393 } 1394 [(set_attr "type" "multi") 1395 (set_attr "mode" "SI") 1396 (set_attr "length" "124")] 1397) 1398 1399(define_insn "*ashlsi_reg" 1400 [(set (match_operand:SI 0 "register_operand" "=&d") 1401 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1402 (match_operand:SI 2 "register_operand" "d")))] 1403 "" 1404 { 1405 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1406 output_asm_insn ("andi\t%3,%2,31", operands); 1407 if (REGNO (operands[0]) != REGNO (operands[1])) 1408 output_asm_insn ("addk\t%0,r0,%1", operands); 1409 /* Exit the loop if zero shift. */ 1410 output_asm_insn ("beqid\t%3,.+20", operands); 1411 /* Emit the loop. */ 1412 output_asm_insn ("addk\t%0,%0,r0", operands); 1413 output_asm_insn ("addik\t%3,%3,-1", operands); 1414 output_asm_insn ("bneid\t%3,.-4", operands); 1415 return "addk\t%0,%0,%0"; 1416 } 1417 [(set_attr "type" "multi") 1418 (set_attr "mode" "SI") 1419 (set_attr "length" "28")] 1420) 1421 1422 1423;;---------------------------------------------------------------- 1424;; 32-bit right shifts 1425;;---------------------------------------------------------------- 1426(define_expand "ashrsi3" 1427 [(set (match_operand:SI 0 "register_operand" "=&d") 1428 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1429 (match_operand:SI 2 "arith_operand" "")))] 1430 "" 1431 { 1432 /* Avoid recursion for trivial cases. */ 1433 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1434 if (microblaze_expand_shift (operands)) 1435 DONE; 1436 } 1437) 1438 1439;; Irrespective of if we have a barrel-shifter or not, we want to match 1440;; shifts by 1 with a special pattern. When a barrel shifter is present, 1441;; saves a cycle. If not, allows us to annotate the instruction for delay 1442;; slot optimization 1443(define_insn "*ashrsi3_byone" 1444 [(set (match_operand:SI 0 "register_operand" "=d") 1445 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1446 (match_operand:SI 2 "arith_operand" "I")))] 1447 "(INTVAL (operands[2]) == 1)" 1448 "sra\t%0,%1" 1449 [(set_attr "type" "arith") 1450 (set_attr "mode" "SI") 1451 (set_attr "length" "4")] 1452) 1453 1454;; Barrel shift right logical 1455(define_insn "*ashrsi3_bshift" 1456 [(set (match_operand:SI 0 "register_operand" "=d,d") 1457 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1458 (match_operand:SI 2 "arith_operand" "I,d")))] 1459 "TARGET_BARREL_SHIFT" 1460 "@ 1461 bsrai\t%0,%1,%2 1462 bsra\t%0,%1,%2" 1463 [(set_attr "type" "bshift,bshift") 1464 (set_attr "mode" "SI,SI") 1465 (set_attr "length" "4,4")] 1466) 1467 1468(define_insn "*ashrsi_inline" 1469 [(set (match_operand:SI 0 "register_operand" "=&d") 1470 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1471 (match_operand:SI 2 "immediate_operand" "I")))] 1472 "" 1473 { 1474 int i; 1475 int nshift = INTVAL (operands[2]); 1476 if (REGNO (operands[0]) != REGNO (operands[1])) 1477 output_asm_insn ("addk\t%0,r0,%1", operands); 1478 output_asm_insn ("sra\t%0,%1", operands); 1479 for (i = 0; i < (nshift - 2); i++) 1480 output_asm_insn ("sra\t%0,%0", operands); 1481 return "sra\t%0,%0"; 1482 } 1483 [(set_attr "type" "multi") 1484 (set_attr "mode" "SI") 1485 (set_attr "length" "124")] 1486) 1487 1488(define_insn "*ashrsi_reg" 1489 [(set (match_operand:SI 0 "register_operand" "=&d") 1490 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1491 (match_operand:SI 2 "register_operand" "d")))] 1492 "" 1493 { 1494 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1495 output_asm_insn ("andi\t%3,%2,31", operands); 1496 if (REGNO (operands[0]) != REGNO (operands[1])) 1497 output_asm_insn ("addk\t%0,r0,%1", operands); 1498 /* Exit the loop if zero shift. */ 1499 output_asm_insn ("beqid\t%3,.+20", operands); 1500 /* Emit the loop. */ 1501 output_asm_insn ("addk\t%0,%0,r0", operands); 1502 output_asm_insn ("addik\t%3,%3,-1", operands); 1503 output_asm_insn ("bneid\t%3,.-4", operands); 1504 return "sra\t%0,%0"; 1505 } 1506 [(set_attr "type" "multi") 1507 (set_attr "mode" "SI") 1508 (set_attr "length" "28")] 1509) 1510 1511;;---------------------------------------------------------------- 1512;; 32-bit right shifts (logical) 1513;;---------------------------------------------------------------- 1514 1515(define_expand "lshrsi3" 1516 [(set (match_operand:SI 0 "register_operand" "=&d") 1517 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1518 (match_operand:SI 2 "arith_operand" "")))] 1519 "" 1520 { 1521 /* Avoid recursion for trivial cases. */ 1522 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1523 if (microblaze_expand_shift (operands)) 1524 DONE; 1525 } 1526) 1527 1528;; Irrespective of if we have a barrel-shifter or not, we want to match 1529;; shifts by 1 with a special pattern. When a barrel shifter is present, 1530;; saves a cycle. If not, allows us to annotate the instruction for delay 1531;; slot optimization 1532(define_insn "*lshrsi3_byone" 1533 [(set (match_operand:SI 0 "register_operand" "=d") 1534 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1535 (match_operand:SI 2 "arith_operand" "I")))] 1536 "(INTVAL (operands[2]) == 1)" 1537 "srl\t%0,%1" 1538 [(set_attr "type" "arith") 1539 (set_attr "mode" "SI") 1540 (set_attr "length" "4")] 1541) 1542 1543;; Barrel shift right logical 1544(define_insn "*lshrsi3_bshift" 1545 [(set (match_operand:SI 0 "register_operand" "=d,d") 1546 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1547 (match_operand:SI 2 "arith_operand" "I,d")))] 1548 "TARGET_BARREL_SHIFT" 1549 "@ 1550 bsrli\t%0,%1,%2 1551 bsrl\t%0,%1,%2" 1552 [(set_attr "type" "bshift,bshift") 1553 (set_attr "mode" "SI,SI") 1554 (set_attr "length" "4,4")] 1555) 1556 1557(define_insn "*lshrsi_inline" 1558 [(set (match_operand:SI 0 "register_operand" "=&d") 1559 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1560 (match_operand:SI 2 "immediate_operand" "I")))] 1561 "" 1562 { 1563 int i; 1564 int nshift = INTVAL (operands[2]); 1565 if (REGNO (operands[0]) != REGNO (operands[1])) 1566 output_asm_insn ("addk\t%0,r0,%1", operands); 1567 output_asm_insn ("srl\t%0,%1", operands); 1568 for (i = 0; i < (nshift - 2); i++) 1569 output_asm_insn ("srl\t%0,%0", operands); 1570 return "srl\t%0,%0"; 1571 } 1572 [(set_attr "type" "multi") 1573 (set_attr "mode" "SI") 1574 (set_attr "length" "124")] 1575) 1576 1577(define_insn "*lshrsi_reg" 1578 [(set (match_operand:SI 0 "register_operand" "=&d") 1579 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1580 (match_operand:SI 2 "register_operand" "d")))] 1581 "" 1582 { 1583 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1584 output_asm_insn ("andi\t%3,%2,31", operands); 1585 if (REGNO (operands[0]) != REGNO (operands[1])) 1586 output_asm_insn ("addk\t%0,r0,%1", operands); 1587 /* Exit the loop if zero shift. */ 1588 output_asm_insn ("beqid\t%3,.+20", operands); 1589 /* Emit the loop. */ 1590 output_asm_insn ("addk\t%0,%0,r0", operands); 1591 output_asm_insn ("addik\t%3,%3,-1", operands); 1592 output_asm_insn ("bneid\t%3,.-4", operands); 1593 return "srl\t%0,%0"; 1594 } 1595 [(set_attr "type" "multi") 1596 (set_attr "mode" "SI") 1597 (set_attr "length" "28")] 1598) 1599 1600;;---------------------------------------------------------------- 1601;; Setting a register from an integer comparison. 1602;;---------------------------------------------------------------- 1603(define_expand "cstoresi4" 1604 [(set (match_operand:SI 0 "register_operand") 1605 (match_operator:SI 1 "ordered_comparison_operator" 1606 [(match_operand:SI 2 "register_operand") 1607 (match_operand:SI 3 "register_operand")]))] 1608 "TARGET_PATTERN_COMPARE" 1609 "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE) 1610 FAIL; 1611 " 1612) 1613 1614(define_insn "seq_internal_pat" 1615 [(set (match_operand:SI 0 "register_operand" "=d") 1616 (eq:SI 1617 (match_operand:SI 1 "register_operand" "d") 1618 (match_operand:SI 2 "register_operand" "d")))] 1619 "TARGET_PATTERN_COMPARE" 1620 "pcmpeq\t%0,%1,%2" 1621 [(set_attr "type" "arith") 1622 (set_attr "mode" "SI") 1623 (set_attr "length" "4")] 1624) 1625 1626(define_insn "sne_internal_pat" 1627 [(set (match_operand:SI 0 "register_operand" "=d") 1628 (ne:SI 1629 (match_operand:SI 1 "register_operand" "d") 1630 (match_operand:SI 2 "register_operand" "d")))] 1631 "TARGET_PATTERN_COMPARE" 1632 "pcmpne\t%0,%1,%2" 1633 [(set_attr "type" "arith") 1634 (set_attr "mode" "SI") 1635 (set_attr "length" "4")] 1636) 1637 1638;;---------------------------------------------------------------- 1639;; Setting a register from an floating point comparison. 1640;;---------------------------------------------------------------- 1641(define_insn "cstoresf4" 1642 [(set (match_operand:SI 0 "register_operand" "=r") 1643 (match_operator:SI 1 "ordered_comparison_operator" 1644 [(match_operand:SF 2 "register_operand" "r") 1645 (match_operand:SF 3 "register_operand" "r")]))] 1646 "TARGET_HARD_FLOAT" 1647 "fcmp.%C1\t%0,%3,%2" 1648 [(set_attr "type" "fcmp") 1649 (set_attr "mode" "SF") 1650 (set_attr "length" "4")] 1651) 1652 1653;;---------------------------------------------------------------- 1654;; Conditional branches 1655;;---------------------------------------------------------------- 1656 1657(define_expand "cbranchsi4" 1658 [(set (pc) 1659 (if_then_else (match_operator 0 "ordered_comparison_operator" 1660 [(match_operand:SI 1 "register_operand") 1661 (match_operand:SI 2 "arith_operand")]) 1662 (label_ref (match_operand 3 "")) 1663 (pc)))] 1664 "" 1665{ 1666 microblaze_expand_conditional_branch (SImode, operands); 1667 DONE; 1668}) 1669 1670(define_expand "cbranchsf4" 1671 [(set (pc) 1672 (if_then_else (match_operator 0 "ordered_comparison_operator" 1673 [(match_operand:SF 1 "register_operand") 1674 (match_operand:SF 2 "register_operand")]) 1675 (label_ref (match_operand 3 "")) 1676 (pc)))] 1677 "TARGET_HARD_FLOAT" 1678{ 1679 microblaze_expand_conditional_branch_sf (operands); 1680 DONE; 1681 1682}) 1683 1684;; Used to implement comparison instructions 1685(define_expand "condjump" 1686 [(set (pc) 1687 (if_then_else (match_operand 0) 1688 (label_ref (match_operand 1)) 1689 (pc)))]) 1690 1691(define_insn "branch_zero" 1692 [(set (pc) 1693 (if_then_else (match_operator:SI 0 "ordered_comparison_operator" 1694 [(match_operand:SI 1 "register_operand" "d") 1695 (const_int 0)]) 1696 (match_operand:SI 2 "pc_or_label_operand" "") 1697 (match_operand:SI 3 "pc_or_label_operand" ""))) 1698 ] 1699 "" 1700 { 1701 if (operands[3] == pc_rtx) 1702 return "b%C0i%?\t%z1,%2"; 1703 else 1704 return "b%N0i%?\t%z1,%3"; 1705 } 1706 [(set_attr "type" "branch") 1707 (set_attr "mode" "none") 1708 (set_attr "length" "4")] 1709) 1710 1711(define_insn "branch_compare" 1712 [(set (pc) 1713 (if_then_else (match_operator:SI 0 "cmp_op" 1714 [(match_operand:SI 1 "register_operand" "d") 1715 (match_operand:SI 2 "register_operand" "d") 1716 ]) 1717 (label_ref (match_operand 3)) 1718 (pc))) 1719 (clobber(reg:SI R_TMP))] 1720 "" 1721 { 1722 operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1723 enum rtx_code code = GET_CODE (operands[0]); 1724 1725 if (code == GT || code == LE) 1726 { 1727 output_asm_insn ("cmp\tr18,%z1,%z2", operands); 1728 code = swap_condition (code); 1729 } 1730 else if (code == GTU || code == LEU) 1731 { 1732 output_asm_insn ("cmpu\tr18,%z1,%z2", operands); 1733 code = swap_condition (code); 1734 } 1735 else if (code == GE || code == LT) 1736 { 1737 output_asm_insn ("cmp\tr18,%z2,%z1", operands); 1738 } 1739 else if (code == GEU || code == LTU) 1740 { 1741 output_asm_insn ("cmpu\tr18,%z2,%z1", operands); 1742 } 1743 1744 operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); 1745 return "b%C0i%?\tr18,%3"; 1746 } 1747 [(set_attr "type" "branch") 1748 (set_attr "mode" "none") 1749 (set_attr "length" "12")] 1750) 1751 1752;;---------------------------------------------------------------- 1753;; Unconditional branches 1754;;---------------------------------------------------------------- 1755(define_insn "jump" 1756 [(set (pc) 1757 (label_ref (match_operand 0 "" "")))] 1758 "" 1759 { 1760 if (GET_CODE (operands[0]) == REG) 1761 return "br%?\t%0"; 1762 else 1763 return "bri%?\t%l0"; 1764 } 1765 [(set_attr "type" "jump") 1766 (set_attr "mode" "none") 1767 (set_attr "length" "4")]) 1768 1769(define_expand "indirect_jump" 1770 [(set (pc) (match_operand 0 "register_operand" "d"))] 1771 "" 1772 { 1773 rtx dest = operands[0]; 1774 if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) 1775 operands[0] = copy_to_mode_reg (Pmode, dest); 1776 1777 emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); 1778 DONE; 1779 } 1780) 1781 1782;; Indirect jumps. Jump to register values. Assuming absolute jumps 1783 1784(define_insn "indirect_jump_internal1" 1785 [(set (pc) (match_operand:SI 0 "register_operand" "d"))] 1786 "" 1787 "bra%?\t%0" 1788 [(set_attr "type" "jump") 1789 (set_attr "mode" "none") 1790 (set_attr "length" "4")]) 1791 1792(define_expand "tablejump" 1793 [(set (pc) 1794 (match_operand 0 "register_operand" "d")) 1795 (use (label_ref (match_operand 1 "" "")))] 1796 "" 1797 { 1798 gcc_assert (GET_MODE (operands[0]) == Pmode); 1799 1800 if (!flag_pic) 1801 emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); 1802 else 1803 emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1])); 1804 DONE; 1805 } 1806) 1807 1808(define_insn "tablejump_internal1" 1809 [(set (pc) 1810 (match_operand:SI 0 "register_operand" "d")) 1811 (use (label_ref (match_operand 1 "" "")))] 1812 "" 1813 "bra%?\t%0 " 1814 [(set_attr "type" "jump") 1815 (set_attr "mode" "none") 1816 (set_attr "length" "4")]) 1817 1818(define_expand "tablejump_internal3" 1819 [(parallel [(set (pc) 1820 (plus:SI (match_operand:SI 0 "register_operand" "d") 1821 (label_ref:SI (match_operand:SI 1 "" "")))) 1822 (use (label_ref:SI (match_dup 1)))])] 1823 "" 1824 "" 1825) 1826 1827;; need to change for MicroBlaze PIC 1828(define_insn "" 1829 [(set (pc) 1830 (plus:SI (match_operand:SI 0 "register_operand" "d") 1831 (label_ref:SI (match_operand 1 "" "")))) 1832 (use (label_ref:SI (match_dup 1)))] 1833 "next_active_insn (insn) != 0 1834 && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC 1835 && PREV_INSN (next_active_insn (insn)) == operands[1] 1836 && flag_pic" 1837 { 1838 output_asm_insn ("addk\t%0,%0,r20",operands); 1839 return "bra%?\t%0"; 1840} 1841 [(set_attr "type" "jump") 1842 (set_attr "mode" "none") 1843 (set_attr "length" "4")]) 1844 1845(define_expand "tablejump_internal4" 1846 [(parallel [(set (pc) 1847 (plus:DI (match_operand:DI 0 "register_operand" "d") 1848 (label_ref:DI (match_operand:SI 1 "" "")))) 1849 (use (label_ref:DI (match_dup 1)))])] 1850 "" 1851 "" 1852) 1853 1854;;---------------------------------------------------------------- 1855;; Function prologue/epilogue and stack allocation 1856;;---------------------------------------------------------------- 1857(define_expand "prologue" 1858 [(const_int 1)] 1859 "" 1860 { 1861 microblaze_expand_prologue (); 1862 DONE; 1863 } 1864) 1865 1866(define_expand "epilogue" 1867 [(use (const_int 0))] 1868 "" 1869 { 1870 microblaze_expand_epilogue (); 1871 DONE; 1872 } 1873) 1874 1875;; An insn to allocate new stack space for dynamic use (e.g., alloca). 1876;; We copy the return address, decrement the stack pointer and save the 1877;; return address again at the new stack top 1878 1879(define_expand "allocate_stack" 1880 [(set (match_operand 0 "register_operand" "=r") 1881 (minus (reg 1) (match_operand 1 "register_operand" ""))) 1882 (set (reg 1) 1883 (minus (reg 1) (match_dup 1)))] 1884 "" 1885 { 1886 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1887 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1888 rtx neg_op0; 1889 1890 emit_move_insn (rtmp, retaddr); 1891 if (GET_CODE (operands[1]) != CONST_INT) 1892 { 1893 neg_op0 = gen_reg_rtx (Pmode); 1894 emit_insn (gen_negsi2 (neg_op0, operands[1])); 1895 } else 1896 neg_op0 = GEN_INT (- INTVAL (operands[1])); 1897 1898 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0)); 1899 emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp); 1900 emit_move_insn (operands[0], virtual_stack_dynamic_rtx); 1901 emit_insn (gen_rtx_CLOBBER (SImode, rtmp)); 1902 DONE; 1903 } 1904) 1905 1906(define_expand "save_stack_block" 1907 [(match_operand 0 "register_operand" "") 1908 (match_operand 1 "register_operand" "")] 1909 "" 1910 { 1911 emit_move_insn (operands[0], operands[1]); 1912 DONE; 1913 } 1914) 1915 1916(define_expand "restore_stack_block" 1917 [(match_operand 0 "register_operand" "") 1918 (match_operand 1 "register_operand" "")] 1919 "" 1920 { 1921 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1922 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1923 1924 /* Move the retaddr. */ 1925 emit_move_insn (rtmp, retaddr); 1926 emit_move_insn (operands[0], operands[1]); 1927 emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), rtmp); 1928 DONE; 1929 } 1930) 1931 1932;; Trivial return. Make it look like a normal return insn as that 1933;; allows jump optimizations to work better . 1934(define_expand "return" 1935 [(simple_return)] 1936 "microblaze_can_use_return_insn ()" 1937 {} 1938) 1939 1940(define_expand "simple_return" 1941 [(simple_return)] 1942 "" 1943 {} 1944) 1945 1946(define_insn "*<optab>" 1947 [(any_return)] 1948 "" 1949 { 1950 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_interrupt_variant ()) 1968 return "rtid\tr14,0 \;%#"; 1969 else 1970 return "rtsd\tr15,8 \;%#"; 1971 } 1972 [(set_attr "type" "jump") 1973 (set_attr "mode" "none") 1974 (set_attr "length" "4")]) 1975 1976 1977;; Block any insns from across this point 1978;; Useful to group sequences together. 1979(define_insn "blockage" 1980 [(unspec_volatile [(const_int 0)] 0)] 1981 "" 1982 "" 1983 [(set_attr "type" "unknown") 1984 (set_attr "mode" "none") 1985 (set_attr "length" "0")]) 1986 1987 1988;;---------------------------------------------------------------- 1989;; Function calls 1990;;---------------------------------------------------------------- 1991 1992(define_expand "call" 1993 [(parallel [(call (match_operand 0 "memory_operand" "m") 1994 (match_operand 1 "" "i")) 1995 (clobber (reg:SI R_SR)) 1996 (use (match_operand 2 "" "")) 1997 (use (match_operand 3 "" ""))])] 1998 "" 1999 { 2000 rtx addr = XEXP (operands[0], 0); 2001 2002 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF 2003 && !SYMBOL_REF_LOCAL_P (addr)) 2004 { 2005 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 2006 XEXP (operands[0], 0) = temp; 2007 } 2008 2009 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 2010 || !call_insn_operand (addr, VOIDmode)) 2011 XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); 2012 2013 if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC) 2014 emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1], 2015 gen_rtx_REG (SImode, 2016 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2017 pic_offset_table_rtx)); 2018 else 2019 emit_call_insn (gen_call_internal0 (operands[0], operands[1], 2020 gen_rtx_REG (SImode, 2021 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2022 2023 DONE; 2024 } 2025) 2026 2027(define_expand "call_internal0" 2028 [(parallel [(call (match_operand 0 "" "") 2029 (match_operand 1 "" "")) 2030 (clobber (match_operand:SI 2 "" ""))])] 2031 "" 2032 { 2033 } 2034) 2035 2036(define_expand "call_internal_plt0" 2037 [(parallel [(call (match_operand 0 "" "") 2038 (match_operand 1 "" "")) 2039 (clobber (match_operand:SI 2 "" "")) 2040 (use (match_operand:SI 3 "" ""))])] 2041 "" 2042 { 2043 } 2044) 2045 2046(define_insn "call_internal_plt" 2047 [(call (mem (match_operand:SI 0 "call_insn_plt_operand" "")) 2048 (match_operand:SI 1 "" "i")) 2049 (clobber (reg:SI R_SR)) 2050 (use (reg:SI R_GOT))] 2051 "flag_pic" 2052 { 2053 register rtx target2 = gen_rtx_REG (Pmode, 2054 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2055 gen_rtx_CLOBBER (VOIDmode, target2); 2056 return "brlid\tr15,%0\;%#"; 2057 } 2058 [(set_attr "type" "call") 2059 (set_attr "mode" "none") 2060 (set_attr "length" "4")]) 2061 2062(define_insn "call_internal1" 2063 [(call (mem (match_operand:SI 0 "call_insn_simple_operand" "ri")) 2064 (match_operand:SI 1 "" "i")) 2065 (clobber (reg:SI R_SR))] 2066 "" 2067 { 2068 register rtx target = operands[0]; 2069 register rtx target2 = gen_rtx_REG (Pmode, 2070 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2071 if (GET_CODE (target) == SYMBOL_REF) { 2072 gen_rtx_CLOBBER (VOIDmode, target2); 2073 return "brlid\tr15,%0\;%#"; 2074 } else if (GET_CODE (target) == CONST_INT) 2075 return "la\t%@,r0,%0\;brald\tr15,%@\;%#"; 2076 else if (GET_CODE (target) == REG) 2077 return "brald\tr15,%0\;%#"; 2078 else { 2079 fprintf (stderr,"Unsupported call insn\n"); 2080 return NULL; 2081 } 2082 } 2083 [(set_attr "type" "call") 2084 (set_attr "mode" "none") 2085 (set_attr "length" "4")]) 2086 2087;; calls.c now passes a fourth argument, make saber happy 2088 2089(define_expand "call_value" 2090 [(parallel [(set (match_operand 0 "register_operand" "=d") 2091 (call (match_operand 1 "memory_operand" "m") 2092 (match_operand 2 "" "i"))) 2093 (clobber (reg:SI R_SR)) 2094 (use (match_operand 3 "" ""))])] ;; next_arg_reg 2095 "" 2096 { 2097 rtx addr = XEXP (operands[1], 0); 2098 2099 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF 2100 && !SYMBOL_REF_LOCAL_P (addr)) 2101 { 2102 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 2103 XEXP (operands[1], 0) = temp; 2104 } 2105 2106 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 2107 || !call_insn_operand (addr, VOIDmode)) 2108 XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); 2109 2110 if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC) 2111 emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1], 2112 operands[2], 2113 gen_rtx_REG (SImode, 2114 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2115 pic_offset_table_rtx)); 2116 else 2117 emit_call_insn (gen_call_value_internal (operands[0], operands[1], 2118 operands[2], 2119 gen_rtx_REG (SImode, 2120 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2121 2122 DONE; 2123 } 2124) 2125 2126 2127(define_expand "call_value_internal" 2128 [(parallel [(set (match_operand 0 "" "") 2129 (call (match_operand 1 "" "") 2130 (match_operand 2 "" ""))) 2131 (clobber (match_operand:SI 3 "" "")) 2132 ])] 2133 "" 2134 {} 2135) 2136 2137(define_expand "call_value_intern_plt0" 2138 [(parallel[(set (match_operand 0 "" "") 2139 (call (match_operand 1 "" "") 2140 (match_operand 2 "" ""))) 2141 (clobber (match_operand:SI 3 "" "")) 2142 (use (match_operand:SI 4 "" ""))])] 2143 "flag_pic" 2144 {} 2145) 2146 2147(define_insn "call_value_intern_plt" 2148 [(set (match_operand:VOID 0 "register_operand" "=d") 2149 (call (mem (match_operand:SI 1 "call_insn_plt_operand" "")) 2150 (match_operand:SI 2 "" "i"))) 2151 (clobber (match_operand:SI 3 "register_operand" "=d")) 2152 (use (match_operand:SI 4 "register_operand"))] 2153 "flag_pic" 2154 { 2155 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2156 2157 gen_rtx_CLOBBER (VOIDmode,target2); 2158 return "brlid\tr15,%1\;%#"; 2159 } 2160 [(set_attr "type" "call") 2161 (set_attr "mode" "none") 2162 (set_attr "length" "4")]) 2163 2164(define_insn "call_value_intern" 2165 [(set (match_operand:VOID 0 "register_operand" "=d") 2166 (call (mem (match_operand:VOID 1 "call_insn_operand" "ri")) 2167 (match_operand:SI 2 "" "i"))) 2168 (clobber (match_operand:SI 3 "register_operand" "=d"))] 2169 "" 2170 { 2171 register rtx target = operands[1]; 2172 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2173 2174 if (GET_CODE (target) == SYMBOL_REF) 2175 { 2176 gen_rtx_CLOBBER (VOIDmode,target2); 2177 if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION) 2178 { 2179 return "brlid\tr15,%1\;%#"; 2180 } 2181 else 2182 { 2183 return "bralid\tr15,%1\;%#"; 2184 } 2185 } 2186 else if (GET_CODE (target) == CONST_INT) 2187 return "la\t%@,r0,%1\;brald\tr15,%@\;%#"; 2188 else if (GET_CODE (target) == REG) 2189 return "brald\tr15,%1\;%#"; 2190 else 2191 return "Unsupported call insn\n"; 2192 } 2193 [(set_attr "type" "call") 2194 (set_attr "mode" "none") 2195 (set_attr "length" "4")]) 2196 2197 2198;; Call subroutine returning any type. 2199(define_expand "untyped_call" 2200 [(parallel [(call (match_operand 0 "" "") 2201 (const_int 0)) 2202 (match_operand 1 "" "") 2203 (match_operand 2 "" "")])] 2204 "" 2205 { 2206 if (operands[0]) /* silence statement not reached warnings */ 2207 { 2208 int i; 2209 2210 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); 2211 2212 for (i = 0; i < XVECLEN (operands[2], 0); i++) 2213 { 2214 rtx set = XVECEXP (operands[2], 0, i); 2215 emit_move_insn (SET_DEST (set), SET_SRC (set)); 2216 } 2217 2218 emit_insn (gen_blockage ()); 2219 DONE; 2220 } 2221 } 2222) 2223 2224;;---------------------------------------------------------------- 2225;; Misc. 2226;;---------------------------------------------------------------- 2227 2228(define_insn "nop" 2229 [(const_int 0)] 2230 "" 2231 "nop" 2232 [(set_attr "type" "nop") 2233 (set_attr "mode" "none") 2234 (set_attr "length" "4")]) 2235 2236;; Trap instruction pattern for __builtin_trap. Same as the glibc ABORT_INSTRUCTION 2237(define_insn "trap" 2238 [(trap_if (const_int 1) (const_int 0))] 2239 "" 2240 "brki\tr0,-1" 2241 [(set_attr "type" "trap")] 2242) 2243 2244;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference 2245;; between "mfs" and "addik" instructions. 2246(define_insn "set_got" 2247 [(set (match_operand:SI 0 "register_operand" "=r") 2248 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))] 2249 "" 2250 "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8" 2251 [(set_attr "type" "multi") 2252 (set_attr "length" "12")]) 2253 2254;; This insn gives the count of leading number of zeros for the second 2255;; operand and stores the result in first operand. 2256(define_insn "clzsi2" 2257 [(set (match_operand:SI 0 "register_operand" "=r") 2258 (clz:SI (match_operand:SI 1 "register_operand" "r")))] 2259 "TARGET_HAS_CLZ" 2260 "clz\t%0,%1" 2261 [(set_attr "type" "arith") 2262 (set_attr "mode" "SI") 2263 (set_attr "length" "4")]) 2264