URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [microblaze/] [microblaze.md] - Rev 709
Compare with Previous | Blame | View Log
;; microblaze.md -- Machine description for Xilinx MicroBlaze processors.;; Copyright 2009, 2010 Free Software Foundation, Inc.;; Contributed by Michael Eager <eager@eagercon.com>.;; This file is part of GCC.;; GCC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 3, or (at your option);; any later version.;; GCC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GCC; see the file COPYING3. If not see;; <http://www.gnu.org/licenses/>. */(include "constraints.md")(include "predicates.md");;----------------------------------------------------;; Constants;;----------------------------------------------------(define_constants [(R_SP 1) ;; Stack pointer reg(R_SR 15) ;; Sub-routine return addr reg(R_IR 14) ;; Interrupt return addr reg(R_DR 16) ;; Debug trap return addr reg(R_ER 17) ;; Exception return addr reg(R_TMP 18) ;; Assembler temporary reg(R_GOT 20) ;; GOT ptr reg(MB_PIPE_3 0) ;; Microblaze 3-stage pipeline(MB_PIPE_5 1) ;; Microblaze 5-stage pipeline(UNSPEC_SET_GOT 101) ;;(UNSPEC_GOTOFF 102) ;; GOT offset(UNSPEC_PLT 103) ;; jump table(UNSPEC_CMP 104) ;; signed compare(UNSPEC_CMPU 105) ;; unsigned compare]);;----------------------------------------------------;; Instruction Attributes;;----------------------------------------------------;; Classification of each insn.;; branch conditional branch;; jump unconditional jump;; call unconditional call;; load load instruction(s);; store store instruction(s);; move data movement within same register set;; arith integer arithmetic instruction;; darith double precision integer arithmetic instructions;; imul integer multiply;; idiv integer divide;; icmp integer compare;; Xfadd floating point add/subtract;; Xfmul floating point multiply;; Xfmadd floating point multiply-add;; Xfdiv floating point divide;; Xfabs floating point absolute value;; Xfneg floating point negation;; Xfcmp floating point compare;; Xfcvt floating point convert;; Xfsqrt floating point square root;; multi multiword sequence (or user asm statements);; nop no operation;; bshift Shift operations(define_attr "type""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"(const_string "unknown"));; Main data type used by the insn(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"));; # instructions (4 bytes each)(define_attr "length" "" (const_int 4))(define_code_iterator any_return [return simple_return]);; <optab> expands to the name of the optab for a particular code.(define_code_attr optab [(return "return")(simple_return "simple_return")]);;----------------------------------------------------;; Attribute describing the processor.;;----------------------------------------------------;; Describe a user's asm statement.(define_asm_attributes[(set_attr "type" "multi")]);; whether or not generating calls to position independent functions(define_attr "abicalls" "no,yes"(const (symbol_ref "microblaze_abicalls_attr")));;----------------------------------------------------------------;; Microblaze DFA Pipeline description;;----------------------------------------------------------------;;-----------------------------------------------------------------/*This is description of pipeline hazards based on DFA. Thefollowing constructions can be used for this:o define_cpu_unit string [string]) describes a cpu functional unit(separated by comma).1st operand: Names of cpu function units.2nd operand: Name of automaton (see comments forDEFINE_AUTOMATON).All define_reservations and define_cpu_units should have uniquenames which can not be "nothing".o (exclusion_set string string) means that each CPU function unitin the first string can not be reserved simultaneously with eachunit whose name is in the second string and vise versa. CPUunits in the string are separated by commas. For example, it isuseful for description CPU with fully pipelined floating pointfunctional unit which can execute simultaneously only singlefloating point insns or only double floating point insns.o (presence_set string string) means that each CPU function unit inthe first string can not be reserved unless at least one of unitswhose names are in the second string is reserved. This is anasymmetric relation. CPU units in the string are separated bycommas. For example, it is useful for description that slot1 isreserved after slot0 reservation for a VLIW processor.o (absence_set string string) means that each CPU function unit inthe first string can not be reserved only if each unit whose nameis in the second string is not reserved. This is an asymmetricrelation (actually exclusion set is analogous to this one but itis symmetric). CPU units in the string are separated by commas.For example, it is useful for description that slot0 can not bereserved after slot1 or slot2 reservation for a VLIW processor.o (define_bypass number out_insn_names in_insn_names) names bypass withgiven latency (the first number) from insns given by the firststring (see define_insn_reservation) into insns given by thesecond string. Insn names in the strings are separated bycommas.o (define_automaton string) describes names of an automatongenerated and used for pipeline hazards recognition. The namesare separated by comma. Actually it is possibly to generate thesingle automaton but unfortunately it can be very large. If weuse more one automata, the summary size of the automata usuallyis less than the single one. The automaton name is used indefine_cpu_unit. All automata should have unique names.o (define_reservation string string) names reservation (the firststring) of cpu functional units (the 2nd string). Sometimes unitreservations for different insns contain common parts. In suchcase, you describe common part and use one its name (the 1stparameter) in regular expression in define_insn_reservation. Alldefine_reservations, define results and define_cpu_units shouldhave unique names which can not be "nothing".o (define_insn_reservation name default_latency condition regexpr)describes reservation of cpu functional units (the 3nd operand)for instruction which is selected by the condition (the 2ndparameter). The first parameter is used for output of debugginginformation. The reservations are described by a regularexpression according the following syntax:regexp = regexp "," oneof| oneofoneof = oneof "|" allof| allofallof = allof "+" repeat| repeatrepeat = element "*" number| elementelement = cpu_function_name| reservation_name| result_name| "nothing"| "(" regexp ")"1. "," is used for describing start of the next cycle inreservation.2. "|" is used for describing the reservation described by thefirst regular expression *or* the reservation described bythe second regular expression *or* etc.3. "+" is used for describing the reservation described by thefirst regular expression *and* the reservation described bythe second regular expression *and* etc.4. "*" is used for convenience and simply means sequence inwhich the regular expression are repeated NUMBER times withcycle advancing (see ",").5. cpu function unit name which means reservation.6. reservation name -- see define_reservation.7. string "nothing" means no units reservation.*/;;-----------------------------------------------------------------;;----------------------------------------------------------------;; Microblaze 5-stage pipeline description (v5.00.a and later);;----------------------------------------------------------------(define_automaton "mbpipe_5")(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")(define_insn_reservation "mb-integer" 1(and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_iu,mb_wb")(define_insn_reservation "mb-special-move" 2(and (eq_attr "type" "move")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_iu*2,mb_wb")(define_insn_reservation "mb-mem-load" 3(and (eq_attr "type" "load,no_delay_load")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_iu,mb_wb")(define_insn_reservation "mb-mem-store" 1(and (eq_attr "type" "store,no_delay_store")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_iu,mb_wb")(define_insn_reservation "mb-mul" 3(and (eq_attr "type" "imul,no_delay_imul")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_mul,mb_mul_2*2,mb_wb")(define_insn_reservation "mb-div" 34(and (eq_attr "type" "idiv")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_div,mb_div_2*33,mb_wb")(define_insn_reservation "mb-bs" 2(and (eq_attr "type" "bshift")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_bs,mb_bs_2,mb_wb")(define_insn_reservation "mb-fpu-add-sub-mul" 6(and (eq_attr "type" "fadd,frsub,fmul")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_fpu,mb_fpu_2*5,mb_wb")(define_insn_reservation "mb-fpu-fcmp" 3(and (eq_attr "type" "fcmp")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_fpu,mb_fpu*2,mb_wb")(define_insn_reservation "mb-fpu-div" 30(and (eq_attr "type" "fdiv")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")(define_insn_reservation "mb-fpu-sqrt" 30(and (eq_attr "type" "fsqrt")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")(define_insn_reservation "mb-fpu-fcvt" 4(and (eq_attr "type" "fcvt")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))"mb_issue,mb_fpu,mb_fpu_2*3,mb_wb");;----------------------------------------------------------------;; Microblaze 3-stage pipeline description (for v4.00.a and earlier);;----------------------------------------------------------------(define_automaton "mbpipe_3")(define_cpu_unit "mb3_iu" "mbpipe_3")(define_insn_reservation "mb3-integer" 1(and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-special-move" 2(and (eq_attr "type" "move")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu*2")(define_insn_reservation "mb3-mem-load" 2(and (eq_attr "type" "load,no_delay_load")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-mem-store" 1(and (eq_attr "type" "store,no_delay_store")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-mul" 3(and (eq_attr "type" "imul,no_delay_imul")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-div" 34(and (eq_attr "type" "idiv")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-bs" 2(and (eq_attr "type" "bshift")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-fpu-add-sub-mul" 6(and (eq_attr "type" "fadd,frsub,fmul")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-fpu-fcmp" 3(and (eq_attr "type" "fcmp")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-fpu-div" 30(and (eq_attr "type" "fdiv")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-fpu-sqrt" 30(and (eq_attr "type" "fsqrt")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(define_insn_reservation "mb3-fpu-fcvt" 4(and (eq_attr "type" "fcvt")(eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))"mb3_iu")(automata_option "v")(automata_option "time")(automata_option "progress");;----------------------------------------------------------------;; Microblaze delay slot description;;----------------------------------------------------------------(define_delay (eq_attr "type" "branch,call,jump")[(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")(ior (not (match_test "microblaze_no_unsafe_delay"))(eq_attr "type" "!fadd,frsub,fmul,fdiv,fcmp,store,load")))(nil) (nil)]);;----------------------------------------------------------------;; Microblaze FPU;;----------------------------------------------------------------(define_insn "addsf3"[(set (match_operand:SF 0 "register_operand" "=d")(plus:SF (match_operand:SF 1 "register_operand" "d")(match_operand:SF 2 "register_operand" "d")))]"TARGET_HARD_FLOAT""fadd\t%0,%1,%2"[(set_attr "type" "fadd")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "subsf3"[(set (match_operand:SF 0 "register_operand" "=d")(minus:SF (match_operand:SF 1 "register_operand" "d")(match_operand:SF 2 "register_operand" "d")))]"TARGET_HARD_FLOAT""frsub\t%0,%2,%1"[(set_attr "type" "frsub")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "mulsf3"[(set (match_operand:SF 0 "register_operand" "=d")(mult:SF (match_operand:SF 1 "register_operand" "d")(match_operand:SF 2 "register_operand" "d")))]"TARGET_HARD_FLOAT""fmul\t%0,%1,%2"[(set_attr "type" "fmul")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "divsf3"[(set (match_operand:SF 0 "register_operand" "=d")(div:SF (match_operand:SF 1 "register_operand" "d")(match_operand:SF 2 "register_operand" "d")))]"TARGET_HARD_FLOAT""fdiv\t%0,%2,%1"[(set_attr "type" "fdiv")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "sqrtsf2"[(set (match_operand:SF 0 "register_operand" "=d")(sqrt:SF (match_operand:SF 1 "register_operand" "d")))]"TARGET_HARD_FLOAT && TARGET_FLOAT_SQRT""fsqrt\t%0,%1"[(set_attr "type" "fsqrt")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "floatsisf2"[(set (match_operand:SF 0 "register_operand" "=d")(float:SF (match_operand:SI 1 "register_operand" "d")))]"TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT""flt\t%0,%1"[(set_attr "type" "fcvt")(set_attr "mode" "SF")(set_attr "length" "4")])(define_insn "fix_truncsfsi2"[(set (match_operand:SI 0 "register_operand" "=d")(fix:SI (match_operand:SF 1 "register_operand" "d")))]"TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT""fint\t%0,%1"[(set_attr "type" "fcvt")(set_attr "mode" "SF")(set_attr "length" "4")]);;----------------------------------------------------------------;; Add;;----------------------------------------------------------------;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ];; Leave carry as is(define_insn "addsi3"[(set (match_operand:SI 0 "register_operand" "=d,d,d")(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")(match_operand:SI 2 "arith_operand" "d,I,i")))]"""@addk\t%0,%z1,%2addik\t%0,%z1,%2addik\t%0,%z1,%2"[(set_attr "type" "arith,arith,no_delay_arith")(set_attr "mode" "SI,SI,SI")(set_attr "length" "4,4,8")]);;----------------------------------------------------------------;; Double Precision Additions;;----------------------------------------------------------------;; reg_DI_dest = reg_DI_src1 + DI_src2;; Adding 2 DI operands in register or reg/imm(define_insn "adddi3"[(set (match_operand:DI 0 "register_operand" "=d,d,d")(plus:DI (match_operand:DI 1 "register_operand" "%d,d,d")(match_operand:DI 2 "arith_operand32" "d,P,N")))]"""@add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0\;addi\t%M0,%M0,-1"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8,8,12")]);;----------------------------------------------------------------;; Subtraction;;----------------------------------------------------------------(define_insn "subsi3"[(set (match_operand:SI 0 "register_operand" "=d,d")(minus:SI (match_operand:SI 1 "arith_operand" "d,d")(match_operand:SI 2 "arith_operand" "d,n")))]"""@rsubk\t%0,%2,%z1addik\t%0,%z1,-%2"[(set_attr "type" "arith,no_delay_arith")(set_attr "mode" "SI")(set_attr "length" "4,8")]);;----------------------------------------------------------------;; Double Precision Subtraction;;----------------------------------------------------------------(define_insn "subdi3"[(set (match_operand:DI 0 "register_operand" "=&d")(minus:DI (match_operand:DI 1 "register_operand" "d")(match_operand:DI 2 "arith_operand32" "d")))]"""@rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")]);;----------------------------------------------------------------;; Multiplication;;----------------------------------------------------------------(define_insn "mulsi3"[(set (match_operand:SI 0 "register_operand" "=d,d,d")(mult:SI (match_operand:SI 1 "register_operand" "d,d,d")(match_operand:SI 2 "arith_operand" "d,I,i")))]"!TARGET_SOFT_MUL""@mul\t%0,%1,%2muli\t%0,%1,%2muli\t%0,%1,%2"[(set_attr "type" "imul,imul,no_delay_imul")(set_attr "mode" "SI")(set_attr "length" "4,4,8")])(define_insn "mulsidi3"[(set (match_operand:DI 0 "register_operand" "=&d")(mult:DI(sign_extend:DI (match_operand:SI 1 "register_operand" "d"))(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mul\t%L0,%1,%2\;mulh\t%M0,%1,%2"[(set_attr "type" "no_delay_arith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_insn "umulsidi3"[(set (match_operand:DI 0 "register_operand" "=&d")(mult:DI(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))(zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2"[(set_attr "type" "no_delay_arith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_insn "usmulsidi3"[(set (match_operand:DI 0 "register_operand" "=&d")(mult:DI(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1"[(set_attr "type" "no_delay_arith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_insn "*smulsi3_highpart"[(set (match_operand:SI 0 "register_operand" "=d")(truncate:SI(lshiftrt:DI(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))(sign_extend:DI (match_operand:SI 2 "register_operand" "d")))(const_int 32))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mulh\t%0,%1,%2"[(set_attr "type" "imul")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "*umulsi3_highpart"[(set (match_operand:SI 0 "register_operand" "=d")(truncate:SI(lshiftrt:DI(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))(zero_extend:DI (match_operand:SI 2 "register_operand" "d")))(const_int 32))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mulhu\t%0,%1,%2"[(set_attr "type" "imul")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "*usmulsi3_highpart"[(set (match_operand:SI 0 "register_operand" "=d")(truncate:SI(lshiftrt:DI(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))(sign_extend:DI (match_operand:SI 2 "register_operand" "d")))(const_int 32))))]"!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH""mulhsu\t%0,%2,%1"[(set_attr "type" "imul")(set_attr "mode" "SI")(set_attr "length" "4")]);;----------------------------------------------------------------;; Division and remainder;;----------------------------------------------------------------(define_expand "divsi3"[(set (match_operand:SI 0 "register_operand" "=d")(div:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]"(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)"{if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES){microblaze_expand_divide (operands);DONE;}else if (!TARGET_SOFT_DIV){emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));DONE;}})(define_insn "divsi3_internal"[(set (match_operand:SI 0 "register_operand" "=d")(div:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]"!TARGET_SOFT_DIV""idiv\t%0,%2,%1"[(set_attr "type" "idiv")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "udivsi3"[(set (match_operand:SI 0 "register_operand" "=d")(udiv:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]"!TARGET_SOFT_DIV""idivu\t%0,%2,%1"[(set_attr "type" "idiv")(set_attr "mode" "SI")(set_attr "length" "4")]);;----------------------------------------------------------------;; Negation and one's complement;;----------------------------------------------------------------(define_insn "negsi2"[(set (match_operand:SI 0 "register_operand" "=d")(neg:SI (match_operand:SI 1 "register_operand" "d")))]"""rsubk\t%0,%1,r0"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "negdi2"[(set (match_operand:DI 0 "register_operand" "=d")(neg:DI (match_operand:DI 1 "register_operand" "d")))]"""rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_insn "one_cmplsi2"[(set (match_operand:SI 0 "register_operand" "=d")(not:SI (match_operand:SI 1 "register_operand" "d")))]"""xori\t%0,%1,-1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "*one_cmpldi2"[(set (match_operand:DI 0 "register_operand" "=d")(not:DI (match_operand:DI 1 "register_operand" "d")))]"""nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_split[(set (match_operand:DI 0 "register_operand" "")(not:DI (match_operand:DI 1 "register_operand" "")))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"[(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))(set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]"");;----------------------------------------------------------------;; Logical;;----------------------------------------------------------------(define_insn "andsi3"[(set (match_operand:SI 0 "register_operand" "=d,d,d,d")(and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")(match_operand:SI 2 "arith_operand" "d,I,i,M")))]"""@and\t%0,%1,%2andi\t%0,%1,%2 #and1andi\t%0,%1,%2 #and2andi\t%0,%1,%2 #and3"[(set_attr "type" "arith,arith,no_delay_arith,no_delay_arith")(set_attr "mode" "SI,SI,SI,SI")(set_attr "length" "4,8,8,8")])(define_insn "anddi3"[(set (match_operand:DI 0 "register_operand" "=d")(and:DI (match_operand:DI 1 "register_operand" "d")(match_operand:DI 2 "register_operand" "d")))]"""and\t%M0,%M1,%M2\;and\t%L0,%L1,%L2"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_split[(set (match_operand:DI 0 "register_operand" "")(and:DI (match_operand:DI 1 "register_operand" "")(match_operand:DI 2 "register_operand" "")))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"[(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0)(subreg:SI (match_dup 2) 0)))(set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4)(subreg:SI (match_dup 2) 4)))]"")(define_insn "iorsi3"[(set (match_operand:SI 0 "register_operand" "=d,d,d,d")(ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")(match_operand:SI 2 "arith_operand" "d,I,M,i")))]"""@or\t%0,%1,%2ori\t%0,%1,%2ori\t%0,%1,%2ori\t%0,%1,%2"[(set_attr "type" "arith,no_delay_arith,no_delay_arith,no_delay_arith")(set_attr "mode" "SI,SI,SI,SI")(set_attr "length" "4,8,8,8")])(define_insn "iordi3"[(set (match_operand:DI 0 "register_operand" "=d")(ior:DI (match_operand:DI 1 "register_operand" "d")(match_operand:DI 2 "register_operand" "d")))]"""or\t%M0,%M1,%M2\;or\t%L0,%L1,%L2"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_split[(set (match_operand:DI 0 "register_operand" "")(ior:DI (match_operand:DI 1 "register_operand" "")(match_operand:DI 2 "register_operand" "")))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"[(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0)(subreg:SI (match_dup 2) 0)))(set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4)(subreg:SI (match_dup 2) 4)))]"")(define_insn "xorsi3"[(set (match_operand:SI 0 "register_operand" "=d,d,d")(xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d")(match_operand:SI 2 "arith_operand" "d,I,i")))]"""@xor\t%0,%1,%2xori\t%0,%1,%2xori\t%0,%1,%2"[(set_attr "type" "arith,arith,no_delay_arith")(set_attr "mode" "SI,SI,SI")(set_attr "length" "4,8,8")])(define_insn "xordi3"[(set (match_operand:DI 0 "register_operand" "=d")(xor:DI (match_operand:DI 1 "register_operand" "d")(match_operand:DI 2 "register_operand" "d")))]"""xor\t%M0,%M1,%M2\;xor\t%L0,%L1,%L2"[(set_attr "type" "darith")(set_attr "mode" "DI")(set_attr "length" "8")])(define_split[(set (match_operand:DI 0 "register_operand" "")(xor:DI (match_operand:DI 1 "register_operand" "")(match_operand:DI 2 "register_operand" "")))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"[(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0)(subreg:SI (match_dup 2) 0)))(set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4)(subreg:SI (match_dup 2) 4)))]"");;----------------------------------------------------------------;; Zero extension;;----------------------------------------------------------------(define_insn "zero_extendhisi2"[(set (match_operand:SI 0 "register_operand" "=d,d,d")(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))]"""@andi\t%0,%1,0xfffflhu%i1\t%0,%1lhu%i1\t%0,%1"[(set_attr "type" "no_delay_arith,load,no_delay_load")(set_attr "mode" "SI,SI,SI")(set_attr "length" "8,4,8")])(define_insn "zero_extendqihi2"[(set (match_operand:HI 0 "register_operand" "=d,d,d")(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]"""@andi\t%0,%1,0x00fflbu%i1\t%0,%1lbu%i1\t%0,%1"[(set_attr "type" "arith,load,no_delay_load")(set_attr "mode" "HI")(set_attr "length" "4,4,8")])(define_insn "zero_extendqisi2"[(set (match_operand:SI 0 "register_operand" "=d,d,d")(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]"""@andi\t%0,%1,0x00fflbu%i1\t%0,%1lbu%i1\t%0,%1"[(set_attr "type" "arith,load,no_delay_load")(set_attr "mode" "SI,SI,SI")(set_attr "length" "4,4,8")]);;----------------------------------------------------------------;; Sign extension;;----------------------------------------------------------------;; basic Sign Extend Operations(define_insn "extendqisi2"[(set (match_operand:SI 0 "register_operand" "=d")(sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]"""sext8\t%0,%1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "extendhisi2"[(set (match_operand:SI 0 "register_operand" "=d")(sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]"""sext16\t%0,%1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")]);; Those for integer source operand are ordered;; widest source type first.(define_insn "extendsidi2"[(set (match_operand:DI 0 "register_operand" "=d,d,d")(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]""{if (which_alternative == 0)output_asm_insn ("addk\t%D0,r0,%1", operands);elseoutput_asm_insn ("lw%i1\t%D0,%1", operands);output_asm_insn ("add\t%0,%D0,%D0", operands);output_asm_insn ("addc\t%0,r0,r0", operands);output_asm_insn ("beqi\t%0,.+8", operands);return "addi\t%0,r0,0xffffffff";}[(set_attr "type" "multi,multi,multi")(set_attr "mode" "DI")(set_attr "length" "20,20,20")]);;----------------------------------------------------------------;; Data movement;;----------------------------------------------------------------;; 64-bit integer moves;; Unlike most other insns, the move insns can't be split with;; different predicates, because register spilling and other parts of;; the compiler, have memoized the insn number already.(define_expand "movdi"[(set (match_operand:DI 0 "nonimmediate_operand" "")(match_operand:DI 1 "general_operand" ""))]""{/* If operands[1] is a constant address illegal for pic, then we need tohandle it just like microblaze_legitimize_address does. */if (flag_pic && pic_address_needs_scratch (operands[1])){rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0));rtx temp2 = XEXP (XEXP (operands[1], 0), 1);emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2));DONE;}if ((reload_in_progress | reload_completed) == 0&& !register_operand (operands[0], DImode)&& !register_operand (operands[1], DImode)&& (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)&& operands[1] != CONST0_RTX (DImode)))){rtx temp = force_reg (DImode, operands[1]);emit_move_insn (operands[0], temp);DONE;}})(define_insn "*movdi_internal"[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")(match_operand:DI 1 "general_operand" " d,i,J,R,m,d,d"))]""{switch (which_alternative){case 0:return "addk\t%0,%1\n\taddk\t%D0,%d1";case 1:return "addik\t%0,r0,%h1\n\taddik\t%D0,r0,%j1 #li => la";case 2:return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";case 3:case 4:if (reg_mentioned_p (operands[0], operands[1]))return "lwi\t%D0,%o1\n\tlwi\t%0,%1";elsereturn "lwi\t%0,%1\n\tlwi\t%D0,%o1";case 5:case 6:return "swi\t%1,%0\n\tswi\t%D1,%o0";}return "unreachable";}[(set_attr "type" "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store")(set_attr "mode" "DI")(set_attr "length" "8,8,8,8,12,8,12")])(define_split[(set (match_operand:DI 0 "register_operand" "")(match_operand:DI 1 "register_operand" ""))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& (REGNO(operands[0]) == (REGNO(operands[1]) + 1))"[(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]"")(define_split[(set (match_operand:DI 0 "register_operand" "")(match_operand:DI 1 "register_operand" ""))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]"");; Unlike most other insns, the move insns can't be split with;; different predicates, because register spilling and other parts of;; the compiler, have memoized the insn number already.(define_expand "movsi"[(set (match_operand:SI 0 "nonimmediate_operand" "")(match_operand:SI 1 "general_operand" ""))]""{if (microblaze_expand_move (SImode, operands)) DONE;});; Added for status resgisters(define_insn "movsi_status"[(set (match_operand:SI 0 "register_operand" "=d,d,z")(match_operand:SI 1 "register_operand" "z,d,d"))]"interrupt_handler""@mfs\t%0,%1 #mfsaddk\t%0,%1,r0 #add movsimts\t%0,%1 #mts"[(set_attr "type" "move")(set_attr "mode" "SI")(set_attr "length" "12")]);; This move will be not be moved to delay slot.(define_insn "*movsi_internal3"[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d")(match_operand:SI 1 "immediate_operand" "J,I,Mnis"))]"(register_operand (operands[0], SImode) &&(GET_CODE (operands[1]) == CONST_INT &&(INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))""@addk\t%0,r0,r0addik\t%0,r0,%1\t# %X1addik\t%0,r0,%1\t# %X1"[(set_attr "type" "arith,arith,no_delay_arith")(set_attr "mode" "SI")(set_attr "length" "4")]);; This move may be used for PLT label operand(define_insn "*movsi_internal5_pltop"[(set (match_operand:SI 0 "register_operand" "=d,d")(match_operand:SI 1 "call_insn_operand" ""))]"(register_operand (operands[0], Pmode) &&PLT_ADDR_P (operands[1]))"{gcc_unreachable ();}[(set_attr "type" "load")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "*movsi_internal2"[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R, T")(match_operand:SI 1 "move_operand" " d,I,Mnis,R,m,dJ,dJ"))]"(register_operand (operands[0], SImode)|| register_operand (operands[1], SImode)|| (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))&& (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF&& GET_CODE (operands[1]) != LABEL_REF))""@addk\t%0,%1,r0addik\t%0,r0,%1\t# %X1addik\t%0,%a1lw%i1\t%0,%1lw%i1\t%0,%1sw%i0\t%z1,%0sw%i0\t%z1,%0"[(set_attr "type" "load,load,no_delay_load,load,no_delay_load,store,no_delay_store")(set_attr "mode" "SI")(set_attr "length" "4,4,8,4,8,4,8")]);; 16-bit Integer moves;; Unlike most other insns, the move insns can't be split with;; different predicates, because register spilling and other parts of;; the compiler, have memoized the insn number already.;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined(define_expand "movhi"[(set (match_operand:HI 0 "nonimmediate_operand" "")(match_operand:HI 1 "general_operand" ""))]""{if ((reload_in_progress | reload_completed) == 0&& !register_operand (operands[0], HImode)&& !register_operand (operands[1], HImode)&& ((GET_CODE (operands[1]) != CONST_INT|| INTVAL (operands[1]) != 0))){rtx temp = force_reg (HImode, operands[1]);emit_move_insn (operands[0], temp);DONE;}})(define_insn "*movhi_internal2"[(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m")(match_operand:HI 1 "general_operand" "I,d,R,m,dJ,dJ"))]"""@addik\t%0,r0,%1\t# %X1addk\t%0,%1,r0lhui\t%0,%1lhui\t%0,%1sh%i0\t%z1,%0sh%i0\t%z1,%0"[(set_attr "type" "arith,move,load,no_delay_load,store,no_delay_store")(set_attr "mode" "HI")(set_attr "length" "4,4,4,8,8,8")]);; 8-bit Integer moves;; Unlike most other insns, the move insns can't be split with;; different predicates, because register spilling and other parts of;; the compiler, have memoized the insn number already.;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined(define_expand "movqi"[(set (match_operand:QI 0 "nonimmediate_operand" "")(match_operand:QI 1 "general_operand" ""))]""{if ((reload_in_progress | reload_completed) == 0&& !register_operand (operands[0], QImode)&& !register_operand (operands[1], QImode)&& ((GET_CODE (operands[1]) != CONST_INT|| INTVAL (operands[1]) != 0))){rtx temp = force_reg (QImode, operands[1]);emit_move_insn (operands[0], temp);DONE;}})(define_insn "*movqi_internal2"[(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")(match_operand:QI 1 "general_operand" "J,I,d,R,m,dJ,dJ"))]"""@addk\t%0,r0,%z1addik\t%0,r0,%1\t# %X1addk\t%0,%1,r0lbu%i1\t%0,%1lbu%i1\t%0,%1sb%i0\t%z1,%0sbi\t%z1,%0"[(set_attr "type" "arith,arith,move,load,no_delay_load,store,no_delay_store")(set_attr "mode" "QI")(set_attr "length" "4,4,8,4,8,4,8")]);; Block moves, see microblaze.c for more details.;; Argument 0 is the destination;; Argument 1 is the source;; Argument 2 is the length;; Argument 3 is the alignment(define_expand "movmemsi"[(parallel [(set (match_operand:BLK 0 "general_operand")(match_operand:BLK 1 "general_operand"))(use (match_operand:SI 2 ""))(use (match_operand:SI 3 "const_int_operand"))])]""{if (microblaze_expand_block_move (operands[0], operands[1],operands[2], operands[3]))DONE;elseFAIL;});; 32-bit floating point moves(define_expand "movsf"[(set (match_operand:SF 0 "nonimmediate_operand" "")(match_operand:SF 1 "general_operand" ""))]""{if ((reload_in_progress | reload_completed) == 0&& !register_operand (operands[0], SFmode)&& !register_operand (operands[1], SFmode)&& ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)&& operands[1] != CONST0_RTX (SFmode)))){rtx temp = force_reg (SFmode, operands[1]);emit_move_insn (operands[0], temp);DONE;}});; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT;;(define_insn "*movsf_internal"[(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")(match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))]"(register_operand (operands[0], SFmode)|| register_operand (operands[1], SFmode)|| operands[1] == CONST0_RTX (SFmode))""@addk\t%0,r0,r0addk\t%0,%1,r0lw%i1\t%0,%1addik\t%0,r0,%F1lw%i1\t%0,%1sw%i0\t%z1,%0swi\t%z1,%0"[(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store")(set_attr "mode" "SF")(set_attr "length" "4,4,4,4,4,4,4")]);; 64-bit floating point moves(define_expand "movdf"[(set (match_operand:DF 0 "nonimmediate_operand" "")(match_operand:DF 1 "general_operand" ""))]""{if (flag_pic == 2) {if (GET_CODE (operands[1]) == MEM&& !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0)){rtx ptr_reg;rtx result;ptr_reg = force_reg (Pmode, XEXP (operands[1],0));result = gen_rtx_MEM (DFmode, ptr_reg);emit_move_insn (operands[0], result);DONE;}}if ((reload_in_progress | reload_completed) == 0&& !register_operand (operands[0], DFmode)&& !register_operand (operands[1], DFmode)&& (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)&& operands[1] != CONST0_RTX (DFmode)))){rtx temp = force_reg (DFmode, operands[1]);emit_move_insn (operands[0], temp);DONE;}});; movdf_internal;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT;;(define_insn "*movdf_internal"[(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")(match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]""{switch (which_alternative){case 0:return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";case 1:case 3:if (reg_mentioned_p (operands[0], operands[1]))return "lwi\t%D0,%o1\n\tlwi\t%0,%1";elsereturn "lwi\t%0,%1\n\tlwi\t%D0,%o1";case 2:{return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo";}case 4:return "swi\t%1,%0\n\tswi\t%D1,%o0";}gcc_unreachable ();}[(set_attr "type" "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store")(set_attr "mode" "DF")(set_attr "length" "4,8,8,16,8")])(define_split[(set (match_operand:DF 0 "register_operand" "")(match_operand:DF 1 "register_operand" ""))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& (REGNO (operands[0]) == (REGNO (operands[1]) + 1))"[(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]"")(define_split[(set (match_operand:DF 0 "register_operand" "")(match_operand:DF 1 "register_operand" ""))]"reload_completed&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))&& (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]"");;----------------------------------------------------------------;; Shifts;;----------------------------------------------------------------;;----------------------------------------------------------------;; 32-bit left shifts;;----------------------------------------------------------------(define_expand "ashlsi3"[(set (match_operand:SI 0 "register_operand" "=&d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "")))]""{/* Avoid recursion for trivial cases. */if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))if (microblaze_expand_shift (operands))DONE;});; Irrespective of if we have a barrel-shifter or not, we want to match;; shifts by 1 with a special pattern. When a barrel shifter is present,;; saves a cycle. If not, allows us to annotate the instruction for delay;; slot optimization(define_insn "*ashlsi3_byone"[(set (match_operand:SI 0 "register_operand" "=d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "I")))]"(INTVAL (operands[2]) == 1)""addk\t%0,%1,%1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")]);; Barrel shift left(define_insn "ashlsi3_bshift"[(set (match_operand:SI 0 "register_operand" "=d,d")(ashift:SI (match_operand:SI 1 "register_operand" "d,d")(match_operand:SI 2 "arith_operand" "I,d")))]"TARGET_BARREL_SHIFT""@bslli\t%0,%1,%2bsll\t%0,%1,%2"[(set_attr "type" "bshift,bshift")(set_attr "mode" "SI,SI")(set_attr "length" "4,4")]);; The following patterns apply when there is no barrel shifter present(define_insn "*ashlsi3_with_mul_delay"[(set (match_operand:SI 0 "register_operand" "=d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]"!TARGET_SOFT_MUL&& ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)""muli\t%0,%1,%m2";; This MUL will not generate an imm. Can go into a delay slot.[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "*ashlsi3_with_mul_nodelay"[(set (match_operand:SI 0 "register_operand" "=d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]"!TARGET_SOFT_MUL""muli\t%0,%1,%m2";; This MUL will generate an IMM. Cannot go into a delay slot[(set_attr "type" "no_delay_arith")(set_attr "mode" "SI")(set_attr "length" "8")])(define_insn "*ashlsi3_with_size_opt"[(set (match_operand:SI 0 "register_operand" "=&d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]"(INTVAL (operands[2]) > 5 && optimize_size)"{operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);output_asm_insn ("ori\t%3,r0,%2", operands);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,%1,r0", operands);output_asm_insn ("addik\t%3,%3,-1", operands);output_asm_insn ("bneid\t%3,.-4", operands);return "addk\t%0,%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "20")])(define_insn "*ashlsi3_with_rotate"[(set (match_operand:SI 0 "register_operand" "=&d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]"(INTVAL (operands[2]) > 17 && !optimize_size)"{int i, nshift;nshift = INTVAL (operands[2]);operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode);/* We do one extra shift so that the first bit (carry) coming into the MSBwill be masked out */output_asm_insn ("src\t%0,%1", operands);for (i = 0; i < (32 - nshift); i++)output_asm_insn ("src\t%0,%0", operands);return "andi\t%0,%0,%3";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "80")])(define_insn "*ashlsi_inline"[(set (match_operand:SI 0 "register_operand" "=&d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]""{int i;int nshift = INTVAL (operands[2]);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);output_asm_insn ("addk\t%0,%1,%1", operands);for (i = 0; i < (nshift - 2); i++)output_asm_insn ("addk\t%0,%0,%0", operands);return "addk\t%0,%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "124")])(define_insn "*ashlsi_reg"[(set (match_operand:SI 0 "register_operand" "=&d")(ashift:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]""{operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);output_asm_insn ("andi\t%3,%2,31", operands);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);/* Exit the loop if zero shift. */output_asm_insn ("beqid\t%3,.+20", operands);/* Emit the loop. */output_asm_insn ("addk\t%0,%0,r0", operands);output_asm_insn ("addik\t%3,%3,-1", operands);output_asm_insn ("bneid\t%3,.-4", operands);return "addk\t%0,%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "28")]);;----------------------------------------------------------------;; 32-bit right shifts;;----------------------------------------------------------------(define_expand "ashrsi3"[(set (match_operand:SI 0 "register_operand" "=&d")(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "")))]""{/* Avoid recursion for trivial cases. */if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))if (microblaze_expand_shift (operands))DONE;});; Irrespective of if we have a barrel-shifter or not, we want to match;; shifts by 1 with a special pattern. When a barrel shifter is present,;; saves a cycle. If not, allows us to annotate the instruction for delay;; slot optimization(define_insn "*ashrsi3_byone"[(set (match_operand:SI 0 "register_operand" "=d")(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "I")))]"(INTVAL (operands[2]) == 1)""sra\t%0,%1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")]);; Barrel shift right logical(define_insn "*ashrsi3_bshift"[(set (match_operand:SI 0 "register_operand" "=d,d")(ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d")(match_operand:SI 2 "arith_operand" "I,d")))]"TARGET_BARREL_SHIFT""@bsrai\t%0,%1,%2bsra\t%0,%1,%2"[(set_attr "type" "bshift,bshift")(set_attr "mode" "SI,SI")(set_attr "length" "4,4")])(define_insn "*ashrsi_inline"[(set (match_operand:SI 0 "register_operand" "=&d")(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]""{int i;int nshift = INTVAL (operands[2]);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);output_asm_insn ("sra\t%0,%1", operands);for (i = 0; i < (nshift - 2); i++)output_asm_insn ("sra\t%0,%0", operands);return "sra\t%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "124")])(define_insn "*ashlri_reg"[(set (match_operand:SI 0 "register_operand" "=&d")(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]""{operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);output_asm_insn ("andi\t%3,%2,31", operands);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);/* Exit the loop if zero shift. */output_asm_insn ("beqid\t%3,.+20", operands);/* Emit the loop. */output_asm_insn ("addk\t%0,%0,r0", operands);output_asm_insn ("addik\t%3,%3,-1", operands);output_asm_insn ("bneid\t%3,.-4", operands);return "sra\t%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "28")]);;----------------------------------------------------------------;; 32-bit right shifts (logical);;----------------------------------------------------------------(define_expand "lshrsi3"[(set (match_operand:SI 0 "register_operand" "=&d")(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "")))]""{/* Avoid recursion for trivial cases. */if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))if (microblaze_expand_shift (operands))DONE;});; Irrespective of if we have a barrel-shifter or not, we want to match;; shifts by 1 with a special pattern. When a barrel shifter is present,;; saves a cycle. If not, allows us to annotate the instruction for delay;; slot optimization(define_insn "*lshrsi3_byone"[(set (match_operand:SI 0 "register_operand" "=d")(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "arith_operand" "I")))]"(INTVAL (operands[2]) == 1)""srl\t%0,%1"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")]);; Barrel shift right logical(define_insn "*lshrsi3_bshift"[(set (match_operand:SI 0 "register_operand" "=d,d")(lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")(match_operand:SI 2 "arith_operand" "I,d")))]"TARGET_BARREL_SHIFT""@bsrli\t%0,%1,%2bsrl\t%0,%1,%2"[(set_attr "type" "bshift,bshift")(set_attr "mode" "SI,SI")(set_attr "length" "4,4")])(define_insn "*lshrsi_inline"[(set (match_operand:SI 0 "register_operand" "=&d")(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "immediate_operand" "I")))]""{int i;int nshift = INTVAL (operands[2]);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);output_asm_insn ("srl\t%0,%1", operands);for (i = 0; i < (nshift - 2); i++)output_asm_insn ("srl\t%0,%0", operands);return "srl\t%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "124")])(define_insn "*lshlri_reg"[(set (match_operand:SI 0 "register_operand" "=&d")(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]""{operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);output_asm_insn ("andi\t%3,%2,31", operands);if (REGNO (operands[0]) != REGNO (operands[1]))output_asm_insn ("addk\t%0,r0,%1", operands);/* Exit the loop if zero shift. */output_asm_insn ("beqid\t%3,.+20", operands);/* Emit the loop. */output_asm_insn ("addk\t%0,%0,r0", operands);output_asm_insn ("addik\t%3,%3,-1", operands);output_asm_insn ("bneid\t%3,.-4", operands);return "srl\t%0,%0";}[(set_attr "type" "multi")(set_attr "mode" "SI")(set_attr "length" "28")]);;----------------------------------------------------------------;; Setting a register from an integer comparison.;;----------------------------------------------------------------(define_expand "cstoresi4"[(set (match_operand:SI 0 "register_operand")(match_operator:SI 1 "ordered_comparison_operator"[(match_operand:SI 2 "register_operand")(match_operand:SI 3 "register_operand")]))]"TARGET_PATTERN_COMPARE""if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE)FAIL;")(define_insn "seq_internal_pat"[(set (match_operand:SI 0 "register_operand" "=d")(eq:SI(match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]"TARGET_PATTERN_COMPARE""pcmpeq\t%0,%1,%2"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "sne_internal_pat"[(set (match_operand:SI 0 "register_operand" "=d")(ne:SI(match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")))]"TARGET_PATTERN_COMPARE""pcmpne\t%0,%1,%2"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "signed_compare"[(set (match_operand:SI 0 "register_operand" "=d")(unspec[(match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]"""cmp\t%0,%1,%2"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")])(define_insn "unsigned_compare"[(set (match_operand:SI 0 "register_operand" "=d")(unspec[(match_operand:SI 1 "register_operand" "d")(match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]"""cmpu\t%0,%1,%2"[(set_attr "type" "arith")(set_attr "mode" "SI")(set_attr "length" "4")]);;----------------------------------------------------------------;; Setting a register from an floating point comparison.;;----------------------------------------------------------------(define_insn "cstoresf4"[(set (match_operand:SI 0 "register_operand")(match_operator:SI 1 "ordered_comparison_operator"[(match_operand:SF 2 "register_operand")(match_operand:SF 3 "register_operand")]))]"TARGET_HARD_FLOAT""fcmp.%C1\t%0,%3,%2"[(set_attr "type" "fcmp")(set_attr "mode" "SF")(set_attr "length" "4")]);;----------------------------------------------------------------;; Conditional branches;;----------------------------------------------------------------(define_expand "cbranchsi4"[(set (pc)(if_then_else (match_operator 0 "ordered_comparison_operator"[(match_operand:SI 1 "register_operand")(match_operand:SI 2 "arith_operand")])(label_ref (match_operand 3 ""))(pc)))]""{microblaze_expand_conditional_branch (SImode, operands);DONE;})(define_expand "cbranchsf4"[(set (pc)(if_then_else (match_operator:SI 0 "ordered_comparison_operator"[(match_operand:SF 1 "register_operand")(match_operand:SF 2 "register_operand")])(label_ref (match_operand 3 ""))(pc)))]"TARGET_HARD_FLOAT"{microblaze_expand_conditional_branch_sf (operands);DONE;});; Used to implement comparison instructions(define_expand "condjump"[(set (pc)(if_then_else (match_operand 0)(label_ref (match_operand 1))(pc)))])(define_insn "branch_zero"[(set (pc)(if_then_else (match_operator:SI 0 "ordered_comparison_operator"[(match_operand:SI 1 "register_operand" "d")(const_int 0)])(match_operand:SI 2 "pc_or_label_operand" "")(match_operand:SI 3 "pc_or_label_operand" "")))]""{if (operands[3] == pc_rtx)return "b%C0i%?\t%z1,%2";elsereturn "b%N0i%?\t%z1,%3";}[(set_attr "type" "branch")(set_attr "mode" "none")(set_attr "length" "4")]);;----------------------------------------------------------------;; Unconditional branches;;----------------------------------------------------------------(define_insn "jump"[(set (pc)(label_ref (match_operand 0 "" "")))]""{if (GET_CODE (operands[0]) == REG)return "br%?\t%0";elsereturn "bri%?\t%l0";}[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")])(define_expand "indirect_jump"[(set (pc) (match_operand 0 "register_operand" "d"))]""{rtx dest = operands[0];if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode)operands[0] = copy_to_mode_reg (Pmode, dest);emit_jump_insn (gen_indirect_jump_internal1 (operands[0]));DONE;});; Indirect jumps. Jump to register values. Assuming absolute jumps(define_insn "indirect_jump_internal1"[(set (pc) (match_operand:SI 0 "register_operand" "d"))]"""bra%?\t%0"[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")])(define_expand "tablejump"[(set (pc)(match_operand 0 "register_operand" "d"))(use (label_ref (match_operand 1 "" "")))]""{gcc_assert (GET_MODE (operands[0]) == Pmode);if (!flag_pic)emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));elseemit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));DONE;})(define_insn "tablejump_internal1"[(set (pc)(match_operand:SI 0 "register_operand" "d"))(use (label_ref (match_operand 1 "" "")))]"""bra%?\t%0 "[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")])(define_expand "tablejump_internal3"[(parallel [(set (pc)(plus:SI (match_operand:SI 0 "register_operand" "d")(label_ref:SI (match_operand:SI 1 "" ""))))(use (label_ref:SI (match_dup 1)))])]"""");; need to change for MicroBlaze PIC(define_insn ""[(set (pc)(plus:SI (match_operand:SI 0 "register_operand" "d")(label_ref:SI (match_operand 1 "" ""))))(use (label_ref:SI (match_dup 1)))]"next_active_insn (insn) != 0&& GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC&& PREV_INSN (next_active_insn (insn)) == operands[1]&& flag_pic"{output_asm_insn ("addk\t%0,%0,r20",operands);return "bra%?\t%0";}[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")])(define_expand "tablejump_internal4"[(parallel [(set (pc)(plus:DI (match_operand:DI 0 "register_operand" "d")(label_ref:DI (match_operand:SI 1 "" ""))))(use (label_ref:DI (match_dup 1)))])]"""");;----------------------------------------------------------------;; Function prologue/epilogue and stack allocation;;----------------------------------------------------------------(define_expand "prologue"[(const_int 1)]""{microblaze_expand_prologue ();DONE;})(define_expand "epilogue"[(use (const_int 0))]""{microblaze_expand_epilogue ();DONE;});; An insn to allocate new stack space for dynamic use (e.g., alloca).;; We copy the return address, decrement the stack pointer and save the;; return address again at the new stack top(define_expand "allocate_stack"[(set (match_operand 0 "register_operand" "=r")(minus (reg 1) (match_operand 1 "register_operand" "")))(set (reg 1)(minus (reg 1) (match_dup 1)))]""{rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);rtx rtmp = gen_rtx_REG (SImode, R_TMP);rtx neg_op0;emit_move_insn (rtmp, retaddr);if (GET_CODE (operands[1]) != CONST_INT){neg_op0 = gen_reg_rtx (Pmode);emit_insn (gen_negsi2 (neg_op0, operands[1]));} elseneg_op0 = GEN_INT (- INTVAL (operands[1]));emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp);emit_move_insn (operands[0], virtual_stack_dynamic_rtx);emit_insn (gen_rtx_CLOBBER (SImode, rtmp));DONE;});; Trivial return. Make it look like a normal return insn as that;; allows jump optimizations to work better .(define_expand "return"[(simple_return)]"microblaze_can_use_return_insn ()"{})(define_expand "simple_return"[(simple_return)]""{})(define_insn "*<optab>"[(any_return)]""{if (microblaze_is_interrupt_handler ())return "rtid\tr14, 0\;%#";elsereturn "rtsd\tr15, 8\;%#";}[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")]);; Normal return.(define_insn "<optab>_internal"[(any_return)(use (match_operand:SI 0 "register_operand" ""))]""{if (microblaze_is_interrupt_handler ())return "rtid\tr14,0 \;%#";elsereturn "rtsd\tr15,8 \;%#";}[(set_attr "type" "jump")(set_attr "mode" "none")(set_attr "length" "4")]);; Block any insns from across this point;; Useful to group sequences together.(define_insn "blockage"[(unspec_volatile [(const_int 0)] 0)]""""[(set_attr "type" "unknown")(set_attr "mode" "none")(set_attr "length" "0")]);;----------------------------------------------------------------;; Function calls;;----------------------------------------------------------------(define_expand "call"[(parallel [(call (match_operand 0 "memory_operand" "m")(match_operand 1 "" "i"))(clobber (reg:SI R_SR))(use (match_operand 2 "" ""))(use (match_operand 3 "" ""))])]""{rtx addr = XEXP (operands[0], 0);if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF&& !SYMBOL_REF_LOCAL_P (addr)){rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);XEXP (operands[0], 0) = temp;}if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))|| !call_insn_operand (addr, VOIDmode))XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC)emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1],gen_rtx_REG (SImode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),pic_offset_table_rtx));elseemit_call_insn (gen_call_internal0 (operands[0], operands[1],gen_rtx_REG (SImode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));DONE;})(define_expand "call_internal0"[(parallel [(call (match_operand 0 "" "")(match_operand 1 "" ""))(clobber (match_operand:SI 2 "" ""))])]""{})(define_expand "call_internal_plt0"[(parallel [(call (match_operand 0 "" "")(match_operand 1 "" ""))(clobber (match_operand:SI 2 "" ""))(use (match_operand:SI 3 "" ""))])]""{})(define_insn "call_internal_plt"[(call (mem (match_operand:SI 0 "call_insn_plt_operand" ""))(match_operand:SI 1 "" "i"))(clobber (reg:SI R_SR))(use (reg:SI R_GOT))]"flag_pic"{register rtx target2 = gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);gen_rtx_CLOBBER (VOIDmode, target2);return "brlid\tr15,%0\;%#";}[(set_attr "type" "call")(set_attr "mode" "none")(set_attr "length" "4")])(define_insn "call_internal1"[(call (mem (match_operand:SI 0 "call_insn_operand" "ri"))(match_operand:SI 1 "" "i"))(clobber (reg:SI R_SR))]""{register rtx target = operands[0];register rtx target2 = gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);if (GET_CODE (target) == SYMBOL_REF) {gen_rtx_CLOBBER (VOIDmode, target2);return "brlid\tr15,%0\;%#";} else if (GET_CODE (target) == CONST_INT)return "la\t%@,r0,%0\;brald\tr15,%@\;%#";else if (GET_CODE (target) == REG)return "brald\tr15,%0\;%#";else {fprintf (stderr,"Unsupported call insn\n");return NULL;}}[(set_attr "type" "call")(set_attr "mode" "none")(set_attr "length" "4")]);; calls.c now passes a fourth argument, make saber happy(define_expand "call_value"[(parallel [(set (match_operand 0 "register_operand" "=d")(call (match_operand 1 "memory_operand" "m")(match_operand 2 "" "i")))(clobber (reg:SI R_SR))(use (match_operand 3 "" ""))])] ;; next_arg_reg""{rtx addr = XEXP (operands[1], 0);if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF&& !SYMBOL_REF_LOCAL_P (addr)){rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);XEXP (operands[1], 0) = temp;}if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))|| !call_insn_operand (addr, VOIDmode))XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC)emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1],operands[2],gen_rtx_REG (SImode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),pic_offset_table_rtx));elseemit_call_insn (gen_call_value_internal (operands[0], operands[1],operands[2],gen_rtx_REG (SImode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));DONE;})(define_expand "call_value_internal"[(parallel [(set (match_operand 0 "" "")(call (match_operand 1 "" "")(match_operand 2 "" "")))(clobber (match_operand:SI 3 "" ""))])]""{})(define_expand "call_value_intern_plt0"[(parallel[(set (match_operand 0 "" "")(call (match_operand 1 "" "")(match_operand 2 "" "")))(clobber (match_operand:SI 3 "" ""))(use (match_operand:SI 4 "" ""))])]"flag_pic"{})(define_insn "call_value_intern_plt"[(set (match_operand:VOID 0 "register_operand" "=d")(call (mem (match_operand:SI 1 "call_insn_plt_operand" ""))(match_operand:SI 2 "" "i")))(clobber (match_operand:SI 3 "register_operand" "=d"))(use (match_operand:SI 4 "register_operand"))]"flag_pic"{register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);gen_rtx_CLOBBER (VOIDmode,target2);return "brlid\tr15,%1\;%#";}[(set_attr "type" "call")(set_attr "mode" "none")(set_attr "length" "4")])(define_insn "call_value_intern"[(set (match_operand:VOID 0 "register_operand" "=d")(call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))(match_operand:SI 2 "" "i")))(clobber (match_operand:SI 3 "register_operand" "=d"))]""{register rtx target = operands[1];register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);if (GET_CODE (target) == SYMBOL_REF){gen_rtx_CLOBBER (VOIDmode,target2);return "brlid\tr15,%1\;%#";}else if (GET_CODE (target) == CONST_INT)return "la\t%@,r0,%1\;brald\tr15,%@\;%#";else if (GET_CODE (target) == REG)return "brald\tr15,%1\;%#";elsereturn "Unsupported call insn\n";}[(set_attr "type" "call")(set_attr "mode" "none")(set_attr "length" "4")]);; Call subroutine returning any type.(define_expand "untyped_call"[(parallel [(call (match_operand 0 "" "")(const_int 0))(match_operand 1 "" "")(match_operand 2 "" "")])]""{if (operands[0]) /* silence statement not reached warnings */{int i;emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));for (i = 0; i < XVECLEN (operands[2], 0); i++){rtx set = XVECEXP (operands[2], 0, i);emit_move_insn (SET_DEST (set), SET_SRC (set));}emit_insn (gen_blockage ());DONE;}});;----------------------------------------------------------------;; Misc.;;----------------------------------------------------------------(define_insn "nop"[(const_int 0)]"""nop"[(set_attr "type" "nop")(set_attr "mode" "none")(set_attr "length" "4")]);; The insn to set GOT. The hardcoded number "8" accounts for $pc difference;; between "mfs" and "addik" instructions.(define_insn "set_got"[(set (match_operand:SI 0 "register_operand" "=r")(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))]"""mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8"[(set_attr "type" "multi")(set_attr "length" "12")])
