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;; 32-bit floating point moves 1123 1124(define_expand "movsf" 1125 [(set (match_operand:SF 0 "nonimmediate_operand" "") 1126 (match_operand:SF 1 "general_operand" ""))] 1127 "" 1128 { 1129 if ((reload_in_progress | reload_completed) == 0 1130 && !register_operand (operands[0], SFmode) 1131 && !register_operand (operands[1], SFmode) 1132 && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1133 && operands[1] != CONST0_RTX (SFmode)))) 1134 { 1135 rtx temp = force_reg (SFmode, operands[1]); 1136 emit_move_insn (operands[0], temp); 1137 DONE; 1138 } 1139 } 1140) 1141 1142;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1143;; 1144(define_insn "*movsf_internal" 1145 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m") 1146 (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))] 1147 "(register_operand (operands[0], SFmode) 1148 || register_operand (operands[1], SFmode) 1149 || operands[1] == CONST0_RTX (SFmode))" 1150 "@ 1151 addk\t%0,r0,r0 1152 addk\t%0,%1,r0 1153 lw%i1\t%0,%1 1154 addik\t%0,r0,%F1 1155 lw%i1\t%0,%1 1156 sw%i0\t%z1,%0 1157 swi\t%z1,%0" 1158 [(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store") 1159 (set_attr "mode" "SF") 1160 (set_attr "length" "4,4,4,4,4,4,4")]) 1161 1162;; 64-bit floating point moves 1163(define_expand "movdf" 1164 [(set (match_operand:DF 0 "nonimmediate_operand" "") 1165 (match_operand:DF 1 "general_operand" ""))] 1166 "" 1167 { 1168 if (flag_pic == 2) { 1169 if (GET_CODE (operands[1]) == MEM 1170 && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0)) 1171 { 1172 rtx ptr_reg; 1173 rtx result; 1174 ptr_reg = force_reg (Pmode, XEXP (operands[1],0)); 1175 result = gen_rtx_MEM (DFmode, ptr_reg); 1176 emit_move_insn (operands[0], result); 1177 DONE; 1178 } 1179 } 1180 if ((reload_in_progress | reload_completed) == 0 1181 && !register_operand (operands[0], DFmode) 1182 && !register_operand (operands[1], DFmode) 1183 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) 1184 && operands[1] != CONST0_RTX (DFmode)))) 1185 { 1186 rtx temp = force_reg (DFmode, operands[1]); 1187 emit_move_insn (operands[0], temp); 1188 DONE; 1189 } 1190 } 1191) 1192 1193;; movdf_internal 1194;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT 1195;; 1196(define_insn "*movdf_internal" 1197 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o") 1198 (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))] 1199 "" 1200 { 1201 switch (which_alternative) 1202 { 1203 case 0: 1204 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0"; 1205 case 1: 1206 case 3: 1207 if (reg_mentioned_p (operands[0], operands[1])) 1208 return "lwi\t%D0,%o1\n\tlwi\t%0,%1"; 1209 else 1210 return "lwi\t%0,%1\n\tlwi\t%D0,%o1"; 1211 case 2: 1212 { 1213 return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo"; 1214 } 1215 case 4: 1216 return "swi\t%1,%0\n\tswi\t%D1,%o0"; 1217 } 1218 gcc_unreachable (); 1219 } 1220 [(set_attr "type" "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store") 1221 (set_attr "mode" "DF") 1222 (set_attr "length" "4,8,8,16,8")]) 1223 1224(define_split 1225 [(set (match_operand:DF 0 "register_operand" "") 1226 (match_operand:DF 1 "register_operand" ""))] 1227 "reload_completed 1228 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) 1229 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) 1230 && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))" 1231 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4)) 1232 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))] 1233 "") 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) 0) (subreg:SI (match_dup 1) 0)) 1243 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))] 1244 "") 1245 1246;;---------------------------------------------------------------- 1247;; Shifts 1248;;---------------------------------------------------------------- 1249 1250;;---------------------------------------------------------------- 1251;; 32-bit left shifts 1252;;---------------------------------------------------------------- 1253(define_expand "ashlsi3" 1254 [(set (match_operand:SI 0 "register_operand" "=&d") 1255 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1256 (match_operand:SI 2 "arith_operand" "")))] 1257 "" 1258 { 1259 /* Avoid recursion for trivial cases. */ 1260 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1261 if (microblaze_expand_shift (operands)) 1262 DONE; 1263 } 1264) 1265 1266;; Irrespective of if we have a barrel-shifter or not, we want to match 1267;; shifts by 1 with a special pattern. When a barrel shifter is present, 1268;; saves a cycle. If not, allows us to annotate the instruction for delay 1269;; slot optimization 1270(define_insn "*ashlsi3_byone" 1271 [(set (match_operand:SI 0 "register_operand" "=d") 1272 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1273 (match_operand:SI 2 "arith_operand" "I")))] 1274 "(INTVAL (operands[2]) == 1)" 1275 "addk\t%0,%1,%1" 1276 [(set_attr "type" "arith") 1277 (set_attr "mode" "SI") 1278 (set_attr "length" "4")] 1279) 1280 1281;; Barrel shift left 1282(define_insn "ashlsi3_bshift" 1283 [(set (match_operand:SI 0 "register_operand" "=d,d") 1284 (ashift:SI (match_operand:SI 1 "register_operand" "d,d") 1285 (match_operand:SI 2 "arith_operand" "I,d")))] 1286 "TARGET_BARREL_SHIFT" 1287 "@ 1288 bslli\t%0,%1,%2 1289 bsll\t%0,%1,%2" 1290 [(set_attr "type" "bshift,bshift") 1291 (set_attr "mode" "SI,SI") 1292 (set_attr "length" "4,4")] 1293) 1294 1295;; The following patterns apply when there is no barrel shifter present 1296 1297(define_insn "*ashlsi3_with_mul_delay" 1298 [(set (match_operand:SI 0 "register_operand" "=d") 1299 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1300 (match_operand:SI 2 "immediate_operand" "I")))] 1301 "!TARGET_SOFT_MUL 1302 && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)" 1303 "muli\t%0,%1,%m2" 1304 ;; This MUL will not generate an imm. Can go into a delay slot. 1305 [(set_attr "type" "arith") 1306 (set_attr "mode" "SI") 1307 (set_attr "length" "4")] 1308) 1309 1310(define_insn "*ashlsi3_with_mul_nodelay" 1311 [(set (match_operand:SI 0 "register_operand" "=d") 1312 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1313 (match_operand:SI 2 "immediate_operand" "I")))] 1314 "!TARGET_SOFT_MUL" 1315 "muli\t%0,%1,%m2" 1316 ;; This MUL will generate an IMM. Cannot go into a delay slot 1317 [(set_attr "type" "no_delay_arith") 1318 (set_attr "mode" "SI") 1319 (set_attr "length" "8")] 1320) 1321 1322(define_insn "*ashlsi3_with_size_opt" 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 "(INTVAL (operands[2]) > 5 && optimize_size)" 1327 { 1328 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1329 1330 output_asm_insn ("ori\t%3,r0,%2", operands); 1331 if (REGNO (operands[0]) != REGNO (operands[1])) 1332 output_asm_insn ("addk\t%0,%1,r0", operands); 1333 1334 output_asm_insn ("addik\t%3,%3,-1", operands); 1335 output_asm_insn ("bneid\t%3,.-4", operands); 1336 return "addk\t%0,%0,%0"; 1337 } 1338 [(set_attr "type" "multi") 1339 (set_attr "mode" "SI") 1340 (set_attr "length" "20")] 1341) 1342 1343(define_insn "*ashlsi3_with_rotate" 1344 [(set (match_operand:SI 0 "register_operand" "=&d") 1345 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1346 (match_operand:SI 2 "immediate_operand" "I")))] 1347 "(INTVAL (operands[2]) > 17 && !optimize_size)" 1348 { 1349 int i, nshift; 1350 1351 nshift = INTVAL (operands[2]); 1352 operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode); 1353 1354 /* We do one extra shift so that the first bit (carry) coming into the MSB 1355 will be masked out */ 1356 output_asm_insn ("src\t%0,%1", operands); 1357 for (i = 0; i < (32 - nshift); i++) 1358 output_asm_insn ("src\t%0,%0", operands); 1359 1360 return "andi\t%0,%0,%3"; 1361 } 1362 [(set_attr "type" "multi") 1363 (set_attr "mode" "SI") 1364 (set_attr "length" "80")] 1365) 1366 1367(define_insn "*ashlsi_inline" 1368 [(set (match_operand:SI 0 "register_operand" "=&d") 1369 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1370 (match_operand:SI 2 "immediate_operand" "I")))] 1371 "" 1372 { 1373 int i; 1374 int nshift = INTVAL (operands[2]); 1375 if (REGNO (operands[0]) != REGNO (operands[1])) 1376 output_asm_insn ("addk\t%0,r0,%1", operands); 1377 output_asm_insn ("addk\t%0,%1,%1", operands); 1378 for (i = 0; i < (nshift - 2); i++) 1379 output_asm_insn ("addk\t%0,%0,%0", operands); 1380 return "addk\t%0,%0,%0"; 1381 } 1382 [(set_attr "type" "multi") 1383 (set_attr "mode" "SI") 1384 (set_attr "length" "124")] 1385) 1386 1387(define_insn "*ashlsi_reg" 1388 [(set (match_operand:SI 0 "register_operand" "=&d") 1389 (ashift:SI (match_operand:SI 1 "register_operand" "d") 1390 (match_operand:SI 2 "register_operand" "d")))] 1391 "" 1392 { 1393 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1394 output_asm_insn ("andi\t%3,%2,31", operands); 1395 if (REGNO (operands[0]) != REGNO (operands[1])) 1396 output_asm_insn ("addk\t%0,r0,%1", operands); 1397 /* Exit the loop if zero shift. */ 1398 output_asm_insn ("beqid\t%3,.+20", operands); 1399 /* Emit the loop. */ 1400 output_asm_insn ("addk\t%0,%0,r0", operands); 1401 output_asm_insn ("addik\t%3,%3,-1", operands); 1402 output_asm_insn ("bneid\t%3,.-4", operands); 1403 return "addk\t%0,%0,%0"; 1404 } 1405 [(set_attr "type" "multi") 1406 (set_attr "mode" "SI") 1407 (set_attr "length" "28")] 1408) 1409 1410 1411;;---------------------------------------------------------------- 1412;; 32-bit right shifts 1413;;---------------------------------------------------------------- 1414(define_expand "ashrsi3" 1415 [(set (match_operand:SI 0 "register_operand" "=&d") 1416 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1417 (match_operand:SI 2 "arith_operand" "")))] 1418 "" 1419 { 1420 /* Avoid recursion for trivial cases. */ 1421 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1422 if (microblaze_expand_shift (operands)) 1423 DONE; 1424 } 1425) 1426 1427;; Irrespective of if we have a barrel-shifter or not, we want to match 1428;; shifts by 1 with a special pattern. When a barrel shifter is present, 1429;; saves a cycle. If not, allows us to annotate the instruction for delay 1430;; slot optimization 1431(define_insn "*ashrsi3_byone" 1432 [(set (match_operand:SI 0 "register_operand" "=d") 1433 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1434 (match_operand:SI 2 "arith_operand" "I")))] 1435 "(INTVAL (operands[2]) == 1)" 1436 "sra\t%0,%1" 1437 [(set_attr "type" "arith") 1438 (set_attr "mode" "SI") 1439 (set_attr "length" "4")] 1440) 1441 1442;; Barrel shift right logical 1443(define_insn "*ashrsi3_bshift" 1444 [(set (match_operand:SI 0 "register_operand" "=d,d") 1445 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1446 (match_operand:SI 2 "arith_operand" "I,d")))] 1447 "TARGET_BARREL_SHIFT" 1448 "@ 1449 bsrai\t%0,%1,%2 1450 bsra\t%0,%1,%2" 1451 [(set_attr "type" "bshift,bshift") 1452 (set_attr "mode" "SI,SI") 1453 (set_attr "length" "4,4")] 1454) 1455 1456(define_insn "*ashrsi_inline" 1457 [(set (match_operand:SI 0 "register_operand" "=&d") 1458 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1459 (match_operand:SI 2 "immediate_operand" "I")))] 1460 "" 1461 { 1462 int i; 1463 int nshift = INTVAL (operands[2]); 1464 if (REGNO (operands[0]) != REGNO (operands[1])) 1465 output_asm_insn ("addk\t%0,r0,%1", operands); 1466 output_asm_insn ("sra\t%0,%1", operands); 1467 for (i = 0; i < (nshift - 2); i++) 1468 output_asm_insn ("sra\t%0,%0", operands); 1469 return "sra\t%0,%0"; 1470 } 1471 [(set_attr "type" "multi") 1472 (set_attr "mode" "SI") 1473 (set_attr "length" "124")] 1474) 1475 1476(define_insn "*ashrsi_reg" 1477 [(set (match_operand:SI 0 "register_operand" "=&d") 1478 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d") 1479 (match_operand:SI 2 "register_operand" "d")))] 1480 "" 1481 { 1482 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1483 output_asm_insn ("andi\t%3,%2,31", operands); 1484 if (REGNO (operands[0]) != REGNO (operands[1])) 1485 output_asm_insn ("addk\t%0,r0,%1", operands); 1486 /* Exit the loop if zero shift. */ 1487 output_asm_insn ("beqid\t%3,.+20", operands); 1488 /* Emit the loop. */ 1489 output_asm_insn ("addk\t%0,%0,r0", operands); 1490 output_asm_insn ("addik\t%3,%3,-1", operands); 1491 output_asm_insn ("bneid\t%3,.-4", operands); 1492 return "sra\t%0,%0"; 1493 } 1494 [(set_attr "type" "multi") 1495 (set_attr "mode" "SI") 1496 (set_attr "length" "28")] 1497) 1498 1499;;---------------------------------------------------------------- 1500;; 32-bit right shifts (logical) 1501;;---------------------------------------------------------------- 1502 1503(define_expand "lshrsi3" 1504 [(set (match_operand:SI 0 "register_operand" "=&d") 1505 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1506 (match_operand:SI 2 "arith_operand" "")))] 1507 "" 1508 { 1509 /* Avoid recursion for trivial cases. */ 1510 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1))) 1511 if (microblaze_expand_shift (operands)) 1512 DONE; 1513 } 1514) 1515 1516;; Irrespective of if we have a barrel-shifter or not, we want to match 1517;; shifts by 1 with a special pattern. When a barrel shifter is present, 1518;; saves a cycle. If not, allows us to annotate the instruction for delay 1519;; slot optimization 1520(define_insn "*lshrsi3_byone" 1521 [(set (match_operand:SI 0 "register_operand" "=d") 1522 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1523 (match_operand:SI 2 "arith_operand" "I")))] 1524 "(INTVAL (operands[2]) == 1)" 1525 "srl\t%0,%1" 1526 [(set_attr "type" "arith") 1527 (set_attr "mode" "SI") 1528 (set_attr "length" "4")] 1529) 1530 1531;; Barrel shift right logical 1532(define_insn "*lshrsi3_bshift" 1533 [(set (match_operand:SI 0 "register_operand" "=d,d") 1534 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") 1535 (match_operand:SI 2 "arith_operand" "I,d")))] 1536 "TARGET_BARREL_SHIFT" 1537 "@ 1538 bsrli\t%0,%1,%2 1539 bsrl\t%0,%1,%2" 1540 [(set_attr "type" "bshift,bshift") 1541 (set_attr "mode" "SI,SI") 1542 (set_attr "length" "4,4")] 1543) 1544 1545(define_insn "*lshrsi_inline" 1546 [(set (match_operand:SI 0 "register_operand" "=&d") 1547 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1548 (match_operand:SI 2 "immediate_operand" "I")))] 1549 "" 1550 { 1551 int i; 1552 int nshift = INTVAL (operands[2]); 1553 if (REGNO (operands[0]) != REGNO (operands[1])) 1554 output_asm_insn ("addk\t%0,r0,%1", operands); 1555 output_asm_insn ("srl\t%0,%1", operands); 1556 for (i = 0; i < (nshift - 2); i++) 1557 output_asm_insn ("srl\t%0,%0", operands); 1558 return "srl\t%0,%0"; 1559 } 1560 [(set_attr "type" "multi") 1561 (set_attr "mode" "SI") 1562 (set_attr "length" "124")] 1563) 1564 1565(define_insn "*lshrsi_reg" 1566 [(set (match_operand:SI 0 "register_operand" "=&d") 1567 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d") 1568 (match_operand:SI 2 "register_operand" "d")))] 1569 "" 1570 { 1571 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1572 output_asm_insn ("andi\t%3,%2,31", operands); 1573 if (REGNO (operands[0]) != REGNO (operands[1])) 1574 output_asm_insn ("addk\t%0,r0,%1", operands); 1575 /* Exit the loop if zero shift. */ 1576 output_asm_insn ("beqid\t%3,.+20", operands); 1577 /* Emit the loop. */ 1578 output_asm_insn ("addk\t%0,%0,r0", operands); 1579 output_asm_insn ("addik\t%3,%3,-1", operands); 1580 output_asm_insn ("bneid\t%3,.-4", operands); 1581 return "srl\t%0,%0"; 1582 } 1583 [(set_attr "type" "multi") 1584 (set_attr "mode" "SI") 1585 (set_attr "length" "28")] 1586) 1587 1588;;---------------------------------------------------------------- 1589;; Setting a register from an integer comparison. 1590;;---------------------------------------------------------------- 1591(define_expand "cstoresi4" 1592 [(set (match_operand:SI 0 "register_operand") 1593 (match_operator:SI 1 "ordered_comparison_operator" 1594 [(match_operand:SI 2 "register_operand") 1595 (match_operand:SI 3 "register_operand")]))] 1596 "TARGET_PATTERN_COMPARE" 1597 "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE) 1598 FAIL; 1599 " 1600) 1601 1602(define_insn "seq_internal_pat" 1603 [(set (match_operand:SI 0 "register_operand" "=d") 1604 (eq:SI 1605 (match_operand:SI 1 "register_operand" "d") 1606 (match_operand:SI 2 "register_operand" "d")))] 1607 "TARGET_PATTERN_COMPARE" 1608 "pcmpeq\t%0,%1,%2" 1609 [(set_attr "type" "arith") 1610 (set_attr "mode" "SI") 1611 (set_attr "length" "4")] 1612) 1613 1614(define_insn "sne_internal_pat" 1615 [(set (match_operand:SI 0 "register_operand" "=d") 1616 (ne:SI 1617 (match_operand:SI 1 "register_operand" "d") 1618 (match_operand:SI 2 "register_operand" "d")))] 1619 "TARGET_PATTERN_COMPARE" 1620 "pcmpne\t%0,%1,%2" 1621 [(set_attr "type" "arith") 1622 (set_attr "mode" "SI") 1623 (set_attr "length" "4")] 1624) 1625 1626;;---------------------------------------------------------------- 1627;; Setting a register from an floating point comparison. 1628;;---------------------------------------------------------------- 1629(define_insn "cstoresf4" 1630 [(set (match_operand:SI 0 "register_operand" "=r") 1631 (match_operator:SI 1 "ordered_comparison_operator" 1632 [(match_operand:SF 2 "register_operand" "r") 1633 (match_operand:SF 3 "register_operand" "r")]))] 1634 "TARGET_HARD_FLOAT" 1635 "fcmp.%C1\t%0,%3,%2" 1636 [(set_attr "type" "fcmp") 1637 (set_attr "mode" "SF") 1638 (set_attr "length" "4")] 1639) 1640 1641;;---------------------------------------------------------------- 1642;; Conditional branches 1643;;---------------------------------------------------------------- 1644 1645(define_expand "cbranchsi4" 1646 [(set (pc) 1647 (if_then_else (match_operator 0 "ordered_comparison_operator" 1648 [(match_operand:SI 1 "register_operand") 1649 (match_operand:SI 2 "arith_operand")]) 1650 (label_ref (match_operand 3 "")) 1651 (pc)))] 1652 "" 1653{ 1654 microblaze_expand_conditional_branch (SImode, operands); 1655 DONE; 1656}) 1657 1658(define_expand "cbranchsf4" 1659 [(set (pc) 1660 (if_then_else (match_operator 0 "ordered_comparison_operator" 1661 [(match_operand:SF 1 "register_operand") 1662 (match_operand:SF 2 "register_operand")]) 1663 (label_ref (match_operand 3 "")) 1664 (pc)))] 1665 "TARGET_HARD_FLOAT" 1666{ 1667 microblaze_expand_conditional_branch_sf (operands); 1668 DONE; 1669 1670}) 1671 1672;; Used to implement comparison instructions 1673(define_expand "condjump" 1674 [(set (pc) 1675 (if_then_else (match_operand 0) 1676 (label_ref (match_operand 1)) 1677 (pc)))]) 1678 1679(define_insn "branch_zero" 1680 [(set (pc) 1681 (if_then_else (match_operator:SI 0 "ordered_comparison_operator" 1682 [(match_operand:SI 1 "register_operand" "d") 1683 (const_int 0)]) 1684 (match_operand:SI 2 "pc_or_label_operand" "") 1685 (match_operand:SI 3 "pc_or_label_operand" ""))) 1686 ] 1687 "" 1688 { 1689 if (operands[3] == pc_rtx) 1690 return "b%C0i%?\t%z1,%2"; 1691 else 1692 return "b%N0i%?\t%z1,%3"; 1693 } 1694 [(set_attr "type" "branch") 1695 (set_attr "mode" "none") 1696 (set_attr "length" "4")] 1697) 1698 1699(define_insn "branch_compare" 1700 [(set (pc) 1701 (if_then_else (match_operator:SI 0 "cmp_op" 1702 [(match_operand:SI 1 "register_operand" "d") 1703 (match_operand:SI 2 "register_operand" "d") 1704 ]) 1705 (label_ref (match_operand 3)) 1706 (pc))) 1707 (clobber(reg:SI R_TMP))] 1708 "" 1709 { 1710 operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); 1711 enum rtx_code code = GET_CODE (operands[0]); 1712 1713 if (code == GT || code == LE) 1714 { 1715 output_asm_insn ("cmp\tr18,%z1,%z2", operands); 1716 code = swap_condition (code); 1717 } 1718 else if (code == GTU || code == LEU) 1719 { 1720 output_asm_insn ("cmpu\tr18,%z1,%z2", operands); 1721 code = swap_condition (code); 1722 } 1723 else if (code == GE || code == LT) 1724 { 1725 output_asm_insn ("cmp\tr18,%z2,%z1", operands); 1726 } 1727 else if (code == GEU || code == LTU) 1728 { 1729 output_asm_insn ("cmpu\tr18,%z2,%z1", operands); 1730 } 1731 1732 operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); 1733 return "b%C0i%?\tr18,%3"; 1734 } 1735 [(set_attr "type" "branch") 1736 (set_attr "mode" "none") 1737 (set_attr "length" "12")] 1738) 1739 1740;;---------------------------------------------------------------- 1741;; Unconditional branches 1742;;---------------------------------------------------------------- 1743(define_insn "jump" 1744 [(set (pc) 1745 (label_ref (match_operand 0 "" "")))] 1746 "" 1747 { 1748 if (GET_CODE (operands[0]) == REG) 1749 return "br%?\t%0"; 1750 else 1751 return "bri%?\t%l0"; 1752 } 1753 [(set_attr "type" "jump") 1754 (set_attr "mode" "none") 1755 (set_attr "length" "4")]) 1756 1757(define_expand "indirect_jump" 1758 [(set (pc) (match_operand 0 "register_operand" "d"))] 1759 "" 1760 { 1761 rtx dest = operands[0]; 1762 if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) 1763 operands[0] = copy_to_mode_reg (Pmode, dest); 1764 1765 emit_jump_insn (gen_indirect_jump_internal1 (operands[0])); 1766 DONE; 1767 } 1768) 1769 1770;; Indirect jumps. Jump to register values. Assuming absolute jumps 1771 1772(define_insn "indirect_jump_internal1" 1773 [(set (pc) (match_operand:SI 0 "register_operand" "d"))] 1774 "" 1775 "bra%?\t%0" 1776 [(set_attr "type" "jump") 1777 (set_attr "mode" "none") 1778 (set_attr "length" "4")]) 1779 1780(define_expand "tablejump" 1781 [(set (pc) 1782 (match_operand 0 "register_operand" "d")) 1783 (use (label_ref (match_operand 1 "" "")))] 1784 "" 1785 { 1786 gcc_assert (GET_MODE (operands[0]) == Pmode); 1787 1788 if (!flag_pic) 1789 emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1])); 1790 else 1791 emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1])); 1792 DONE; 1793 } 1794) 1795 1796(define_insn "tablejump_internal1" 1797 [(set (pc) 1798 (match_operand:SI 0 "register_operand" "d")) 1799 (use (label_ref (match_operand 1 "" "")))] 1800 "" 1801 "bra%?\t%0 " 1802 [(set_attr "type" "jump") 1803 (set_attr "mode" "none") 1804 (set_attr "length" "4")]) 1805 1806(define_expand "tablejump_internal3" 1807 [(parallel [(set (pc) 1808 (plus:SI (match_operand:SI 0 "register_operand" "d") 1809 (label_ref:SI (match_operand:SI 1 "" "")))) 1810 (use (label_ref:SI (match_dup 1)))])] 1811 "" 1812 "" 1813) 1814 1815;; need to change for MicroBlaze PIC 1816(define_insn "" 1817 [(set (pc) 1818 (plus:SI (match_operand:SI 0 "register_operand" "d") 1819 (label_ref:SI (match_operand 1 "" "")))) 1820 (use (label_ref:SI (match_dup 1)))] 1821 "next_active_insn (insn) != 0 1822 && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC 1823 && PREV_INSN (next_active_insn (insn)) == operands[1] 1824 && flag_pic" 1825 { 1826 output_asm_insn ("addk\t%0,%0,r20",operands); 1827 return "bra%?\t%0"; 1828} 1829 [(set_attr "type" "jump") 1830 (set_attr "mode" "none") 1831 (set_attr "length" "4")]) 1832 1833(define_expand "tablejump_internal4" 1834 [(parallel [(set (pc) 1835 (plus:DI (match_operand:DI 0 "register_operand" "d") 1836 (label_ref:DI (match_operand:SI 1 "" "")))) 1837 (use (label_ref:DI (match_dup 1)))])] 1838 "" 1839 "" 1840) 1841 1842;;---------------------------------------------------------------- 1843;; Function prologue/epilogue and stack allocation 1844;;---------------------------------------------------------------- 1845(define_expand "prologue" 1846 [(const_int 1)] 1847 "" 1848 { 1849 microblaze_expand_prologue (); 1850 DONE; 1851 } 1852) 1853 1854(define_expand "epilogue" 1855 [(use (const_int 0))] 1856 "" 1857 { 1858 microblaze_expand_epilogue (); 1859 DONE; 1860 } 1861) 1862 1863;; An insn to allocate new stack space for dynamic use (e.g., alloca). 1864;; We copy the return address, decrement the stack pointer and save the 1865;; return address again at the new stack top 1866 1867(define_expand "allocate_stack" 1868 [(set (match_operand 0 "register_operand" "=r") 1869 (minus (reg 1) (match_operand 1 "register_operand" ""))) 1870 (set (reg 1) 1871 (minus (reg 1) (match_dup 1)))] 1872 "" 1873 { 1874 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1875 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1876 rtx neg_op0; 1877 1878 emit_move_insn (rtmp, retaddr); 1879 if (GET_CODE (operands[1]) != CONST_INT) 1880 { 1881 neg_op0 = gen_reg_rtx (Pmode); 1882 emit_insn (gen_negsi2 (neg_op0, operands[1])); 1883 } else 1884 neg_op0 = GEN_INT (- INTVAL (operands[1])); 1885 1886 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0)); 1887 emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp); 1888 emit_move_insn (operands[0], virtual_stack_dynamic_rtx); 1889 emit_insn (gen_rtx_CLOBBER (SImode, rtmp)); 1890 DONE; 1891 } 1892) 1893 1894(define_expand "save_stack_block" 1895 [(match_operand 0 "register_operand" "") 1896 (match_operand 1 "register_operand" "")] 1897 "" 1898 { 1899 emit_move_insn (operands[0], operands[1]); 1900 DONE; 1901 } 1902) 1903 1904(define_expand "restore_stack_block" 1905 [(match_operand 0 "register_operand" "") 1906 (match_operand 1 "register_operand" "")] 1907 "" 1908 { 1909 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx); 1910 rtx rtmp = gen_rtx_REG (SImode, R_TMP); 1911 1912 /* Move the retaddr. */ 1913 emit_move_insn (rtmp, retaddr); 1914 emit_move_insn (operands[0], operands[1]); 1915 emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), rtmp); 1916 DONE; 1917 } 1918) 1919 1920;; Trivial return. Make it look like a normal return insn as that 1921;; allows jump optimizations to work better . 1922(define_expand "return" 1923 [(simple_return)] 1924 "microblaze_can_use_return_insn ()" 1925 {} 1926) 1927 1928(define_expand "simple_return" 1929 [(simple_return)] 1930 "" 1931 {} 1932) 1933 1934(define_insn "*<optab>" 1935 [(any_return)] 1936 "" 1937 { 1938 if (microblaze_is_interrupt_variant ()) 1939 return "rtid\tr14, 0\;%#"; 1940 else 1941 return "rtsd\tr15, 8\;%#"; 1942 } 1943 [(set_attr "type" "jump") 1944 (set_attr "mode" "none") 1945 (set_attr "length" "4")] 1946) 1947 1948;; Normal return. 1949 1950(define_insn "<optab>_internal" 1951 [(any_return) 1952 (use (match_operand:SI 0 "register_operand" ""))] 1953 "" 1954 { 1955 if (microblaze_is_interrupt_variant ()) 1956 return "rtid\tr14,0 \;%#"; 1957 else 1958 return "rtsd\tr15,8 \;%#"; 1959 } 1960 [(set_attr "type" "jump") 1961 (set_attr "mode" "none") 1962 (set_attr "length" "4")]) 1963 1964 1965;; Block any insns from across this point 1966;; Useful to group sequences together. 1967(define_insn "blockage" 1968 [(unspec_volatile [(const_int 0)] 0)] 1969 "" 1970 "" 1971 [(set_attr "type" "unknown") 1972 (set_attr "mode" "none") 1973 (set_attr "length" "0")]) 1974 1975 1976;;---------------------------------------------------------------- 1977;; Function calls 1978;;---------------------------------------------------------------- 1979 1980(define_expand "call" 1981 [(parallel [(call (match_operand 0 "memory_operand" "m") 1982 (match_operand 1 "" "i")) 1983 (clobber (reg:SI R_SR)) 1984 (use (match_operand 2 "" "")) 1985 (use (match_operand 3 "" ""))])] 1986 "" 1987 { 1988 rtx addr = XEXP (operands[0], 0); 1989 1990 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF 1991 && !SYMBOL_REF_LOCAL_P (addr)) 1992 { 1993 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 1994 XEXP (operands[0], 0) = temp; 1995 } 1996 1997 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 1998 || !call_insn_operand (addr, VOIDmode)) 1999 XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); 2000 2001 if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC) 2002 emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1], 2003 gen_rtx_REG (SImode, 2004 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2005 pic_offset_table_rtx)); 2006 else 2007 emit_call_insn (gen_call_internal0 (operands[0], operands[1], 2008 gen_rtx_REG (SImode, 2009 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2010 2011 DONE; 2012 } 2013) 2014 2015(define_expand "call_internal0" 2016 [(parallel [(call (match_operand 0 "" "") 2017 (match_operand 1 "" "")) 2018 (clobber (match_operand:SI 2 "" ""))])] 2019 "" 2020 { 2021 } 2022) 2023 2024(define_expand "call_internal_plt0" 2025 [(parallel [(call (match_operand 0 "" "") 2026 (match_operand 1 "" "")) 2027 (clobber (match_operand:SI 2 "" "")) 2028 (use (match_operand:SI 3 "" ""))])] 2029 "" 2030 { 2031 } 2032) 2033 2034(define_insn "call_internal_plt" 2035 [(call (mem (match_operand:SI 0 "call_insn_plt_operand" "")) 2036 (match_operand:SI 1 "" "i")) 2037 (clobber (reg:SI R_SR)) 2038 (use (reg:SI R_GOT))] 2039 "flag_pic" 2040 { 2041 register rtx target2 = gen_rtx_REG (Pmode, 2042 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2043 gen_rtx_CLOBBER (VOIDmode, target2); 2044 return "brlid\tr15,%0\;%#"; 2045 } 2046 [(set_attr "type" "call") 2047 (set_attr "mode" "none") 2048 (set_attr "length" "4")]) 2049 2050(define_insn "call_internal1" 2051 [(call (mem (match_operand:SI 0 "call_insn_simple_operand" "ri")) 2052 (match_operand:SI 1 "" "i")) 2053 (clobber (reg:SI R_SR))] 2054 "" 2055 { 2056 register rtx target = operands[0]; 2057 register rtx target2 = gen_rtx_REG (Pmode, 2058 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2059 if (GET_CODE (target) == SYMBOL_REF) { 2060 gen_rtx_CLOBBER (VOIDmode, target2); 2061 return "brlid\tr15,%0\;%#"; 2062 } else if (GET_CODE (target) == CONST_INT) 2063 return "la\t%@,r0,%0\;brald\tr15,%@\;%#"; 2064 else if (GET_CODE (target) == REG) 2065 return "brald\tr15,%0\;%#"; 2066 else { 2067 fprintf (stderr,"Unsupported call insn\n"); 2068 return NULL; 2069 } 2070 } 2071 [(set_attr "type" "call") 2072 (set_attr "mode" "none") 2073 (set_attr "length" "4")]) 2074 2075;; calls.c now passes a fourth argument, make saber happy 2076 2077(define_expand "call_value" 2078 [(parallel [(set (match_operand 0 "register_operand" "=d") 2079 (call (match_operand 1 "memory_operand" "m") 2080 (match_operand 2 "" "i"))) 2081 (clobber (reg:SI R_SR)) 2082 (use (match_operand 3 "" ""))])] ;; next_arg_reg 2083 "" 2084 { 2085 rtx addr = XEXP (operands[1], 0); 2086 2087 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF 2088 && !SYMBOL_REF_LOCAL_P (addr)) 2089 { 2090 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT); 2091 XEXP (operands[1], 0) = temp; 2092 } 2093 2094 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) 2095 || !call_insn_operand (addr, VOIDmode)) 2096 XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); 2097 2098 if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC) 2099 emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1], 2100 operands[2], 2101 gen_rtx_REG (SImode, 2102 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM), 2103 pic_offset_table_rtx)); 2104 else 2105 emit_call_insn (gen_call_value_internal (operands[0], operands[1], 2106 operands[2], 2107 gen_rtx_REG (SImode, 2108 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM))); 2109 2110 DONE; 2111 } 2112) 2113 2114 2115(define_expand "call_value_internal" 2116 [(parallel [(set (match_operand 0 "" "") 2117 (call (match_operand 1 "" "") 2118 (match_operand 2 "" ""))) 2119 (clobber (match_operand:SI 3 "" "")) 2120 ])] 2121 "" 2122 {} 2123) 2124 2125(define_expand "call_value_intern_plt0" 2126 [(parallel[(set (match_operand 0 "" "") 2127 (call (match_operand 1 "" "") 2128 (match_operand 2 "" ""))) 2129 (clobber (match_operand:SI 3 "" "")) 2130 (use (match_operand:SI 4 "" ""))])] 2131 "flag_pic" 2132 {} 2133) 2134 2135(define_insn "call_value_intern_plt" 2136 [(set (match_operand:VOID 0 "register_operand" "=d") 2137 (call (mem (match_operand:SI 1 "call_insn_plt_operand" "")) 2138 (match_operand:SI 2 "" "i"))) 2139 (clobber (match_operand:SI 3 "register_operand" "=d")) 2140 (use (match_operand:SI 4 "register_operand"))] 2141 "flag_pic" 2142 { 2143 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2144 2145 gen_rtx_CLOBBER (VOIDmode,target2); 2146 return "brlid\tr15,%1\;%#"; 2147 } 2148 [(set_attr "type" "call") 2149 (set_attr "mode" "none") 2150 (set_attr "length" "4")]) 2151 2152(define_insn "call_value_intern" 2153 [(set (match_operand:VOID 0 "register_operand" "=d") 2154 (call (mem (match_operand:VOID 1 "call_insn_operand" "ri")) 2155 (match_operand:SI 2 "" "i"))) 2156 (clobber (match_operand:SI 3 "register_operand" "=d"))] 2157 "" 2158 { 2159 register rtx target = operands[1]; 2160 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); 2161 2162 if (GET_CODE (target) == SYMBOL_REF) 2163 { 2164 gen_rtx_CLOBBER (VOIDmode,target2); 2165 if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION) 2166 { 2167 return "brlid\tr15,%1\;%#"; 2168 } 2169 else 2170 { 2171 return "bralid\tr15,%1\;%#"; 2172 } 2173 } 2174 else if (GET_CODE (target) == CONST_INT) 2175 return "la\t%@,r0,%1\;brald\tr15,%@\;%#"; 2176 else if (GET_CODE (target) == REG) 2177 return "brald\tr15,%1\;%#"; 2178 else 2179 return "Unsupported call insn\n"; 2180 } 2181 [(set_attr "type" "call") 2182 (set_attr "mode" "none") 2183 (set_attr "length" "4")]) 2184 2185 2186;; Call subroutine returning any type. 2187(define_expand "untyped_call" 2188 [(parallel [(call (match_operand 0 "" "") 2189 (const_int 0)) 2190 (match_operand 1 "" "") 2191 (match_operand 2 "" "")])] 2192 "" 2193 { 2194 if (operands[0]) /* silence statement not reached warnings */ 2195 { 2196 int i; 2197 2198 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); 2199 2200 for (i = 0; i < XVECLEN (operands[2], 0); i++) 2201 { 2202 rtx set = XVECEXP (operands[2], 0, i); 2203 emit_move_insn (SET_DEST (set), SET_SRC (set)); 2204 } 2205 2206 emit_insn (gen_blockage ()); 2207 DONE; 2208 } 2209 } 2210) 2211 2212;;---------------------------------------------------------------- 2213;; Misc. 2214;;---------------------------------------------------------------- 2215 2216(define_insn "nop" 2217 [(const_int 0)] 2218 "" 2219 "nop" 2220 [(set_attr "type" "nop") 2221 (set_attr "mode" "none") 2222 (set_attr "length" "4")]) 2223 2224;; Trap instruction pattern for __builtin_trap. Same as the glibc ABORT_INSTRUCTION 2225(define_insn "trap" 2226 [(trap_if (const_int 1) (const_int 0))] 2227 "" 2228 "brki\tr0,-1" 2229 [(set_attr "type" "trap")] 2230) 2231 2232;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference 2233;; between "mfs" and "addik" instructions. 2234(define_insn "set_got" 2235 [(set (match_operand:SI 0 "register_operand" "=r") 2236 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))] 2237 "" 2238 "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8" 2239 [(set_attr "type" "multi") 2240 (set_attr "length" "12")]) 2241 2242;; This insn gives the count of leading number of zeros for the second 2243;; operand and stores the result in first operand. 2244(define_insn "clzsi2" 2245 [(set (match_operand:SI 0 "register_operand" "=r") 2246 (clz:SI (match_operand:SI 1 "register_operand" "r")))] 2247 "TARGET_HAS_CLZ" 2248 "clz\t%0,%1" 2249 [(set_attr "type" "arith") 2250 (set_attr "mode" "SI") 2251 (set_attr "length" "4")]) 2252