;; ;; dlx.md ;; ;; Aaron Sawdey ;; ;; 1994-1995 ;; ;; modified for Vamp-DLX by Carsten Meyer ;; ;; carsten@wjpserver.cs.uni-sb.de ;; ;; 2001/02 ;; ;; A Vamp-DLX Machine Description for GCC 2.x ;; ;; ;; Since parts of this come from mips.md: ;; ;; This file is part of GNU CC. ;; ;; GNU CC 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 2, or (at your option) ;; any later version. ;; ;; GNU CC 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 GNU CC; see the file COPYING. If not, write to ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;; ;; (define_attr "slot_usable" "no,yes" (const_string "yes")) (define_attr "type" "unknown,load,store,move,alu,branch,jump,fp,multi" (const_string "unknown")) (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown")) ;; # instructions (4 bytes each) (define_attr "length" "" (const_int 1)) ;;(define_delay (eq_attr "type" "branch,jump") ;; [(and (eq_attr "type" "!branch,jump") ;; (eq_attr "length" "200")) (nil) (nil)]) (define_delay (eq_attr "type" "branch,jump") [(and (eq_attr "slot_usable" "yes") (eq_attr "length" "1")) (nil) (nil)]) (define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") (plus:SF (match_operand:SF 1 "register_operand" "%f") (match_operand:SF 2 "register_operand" "f")))] "" "fadds\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (match_operand:DF 1 "register_operand" "%f") (match_operand:DF 2 "register_operand" "f")))] "" "faddd\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "DF")]) (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f") (minus:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "fsubs\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "fsubd\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "DF")]) (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (match_operand:SF 1 "register_operand" "%f") (match_operand:SF 2 "register_operand" "f")))] "" "fmuls\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (match_operand:DF 1 "register_operand" "%f") (match_operand:DF 2 "register_operand" "f")))] "" "fmuld\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "DF")]) (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f") (div:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "fdivs\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "fdivd\\t%0,%1,%2" [(set_attr "type" "fp") (set_attr "mode" "DF")]) (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (plus:SI (match_operand:SI 1 "register_operand" "%d,d,d") (match_operand:SI 2 "nonmemory_operand" "d,I,L")))] "" "@ add\\t%0,%1,%2 addi\\t%0,%1,%G2 lhi\\tr28,%U2\\n\\tsrli\\tr28,r28,#16\\n\\tadd\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1,1,3")]) (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (minus:SI (match_operand:SI 1 "register_operand" "d,d,d") (match_operand:SI 2 "nonmemory_operand" "d,I,L")))] "" "@ sub\\t%0,%1,%2 subi\\t%0,%1,%G2 lhi\\tr28,%U2\\n\\tsrli\\tr28,r28,#16\\n\\tsub\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1,1,3")]) (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (and:SI (match_operand:SI 1 "register_operand" "%d,d,d") (match_operand:SI 2 "nonmemory_operand" "d,I,L")))] "" "@ and\\t%0,%1,%2 andi\\t%0,%1,%G2 lhi\\tr28,%U2\\n\\tsrli\\tr28,r28,#16\\n\\tand\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1,1,3")]) (define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (ior:SI (match_operand:SI 1 "register_operand" "%d,d,d") (match_operand:SI 2 "nonmemory_operand" "d,I,L")))] "" "@ or\\t%0,%1,%2 ori\\t%0,%1,%G2 lhi\\tr28,%U2\\n\\tsrli\\tr28,r28,#16\\n\\tor\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1,1,3")]) (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (xor:SI (match_operand:SI 1 "register_operand" "%d,d,d") (match_operand:SI 2 "nonmemory_operand" "d,I,L")))] "" "@ xor\\t%0,%1,%2 xori\\t%0,%1,%G2 lhi\\tr28,%U2\\n\\tsrli\\tr28,r28,#16\\n\\txor\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1,1,3")]) ;; ;; -x = 0-x ;; This is ok for integers. ;; (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=d") (neg:SI (match_operand:SI 1 "register_operand" "d")))] "" "sub\\t%0,r0,%1" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "register_operand" "f")))] "" "fnegs\\t%0,%1" [(set_attr "type" "alu") (set_attr "mode" "SF")]) (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "register_operand" "f")))] "" "fnegd\\t%0,%1" [(set_attr "type" "alu") (set_attr "mode" "DF")]) (define_insn "one_cmplqi2" [(set (match_operand:QI 0 "register_operand" "=d") (not:QI (match_operand:QI 1 "register_operand" "d")))] "" "xori\\t%0,%1,#0x00ff" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "1")]) (define_insn "one_cmplhi2" [(set (match_operand:HI 0 "register_operand" "=d") (not:HI (match_operand:HI 1 "register_operand" "d")))] "" "lhi\\tr28,#0xffff\\n\\tsrli\\tr28,r28,#16\\n\\txor\\t%0,%1,r28" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "3")]) (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,#0xffff" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "2")]) (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") (ashift:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "nonmemory_operand" "d,I")))] "" "@ sll\\t%0,%1,%2 slli\\t%0,%1,%2" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "nonmemory_operand" "d,I")))] "" "@ sra\\t%0,%1,%2 srai\\t%0,%1,%2" [(set_attr "type" "alu") (set_attr "mode" "SI")]) (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "nonmemory_operand" "d,I")))] "" "@ srl\\t%0,%1,%2 srli\\t%0,%1,%2" [(set_attr "type" "alu") (set_attr "mode" "SI")]) ;; for there is no instruction for integer multiplying/dividing we have to ;; solve this in software with the floating point ones ;; we have to move & convert the integers to floats. Here we need 3 more ;; instructions than HP for moving & converting does not work in one ;; single instruction (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_scratch:DF 3 "=&f")) (clobber (match_scratch:DF 4 "=&f"))] "" "mi2f\\t%3,%1\\n\\ \\tmi2f\\t%4,%2\\n\\ \\tcvtid\\t%4,%4\\n\\ \\tcvtid\\t%3,%3\\n\\ \\tfmuld\\t%3,%3,%4\\n\\ \\tcvtdi\\t%3,%3\\n\\ \\tmf2i\\t%0,%3" [(set_attr "type" "fp") (set_attr "mode" "SI") (set_attr "length" "7")]) ;; Here's the same thing: 7 instead of 4 instructions (define_insn "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"))) (clobber (match_scratch:DF 3 "=&f")) (clobber (match_scratch:DF 4 "=&f"))] "" "mi2f\\t%3,%1\\n\\ \\tmi2f\\t%4,%2\\n\\ \\tcvtid\\t%4,%4\\n\\ \\tcvtid\\t%3,%3\\n\\ \\tfdivd\\t%3,%3,%4\\n\\ \\tcvtdi\\t%3,%3\\n\\ \\tmf2i\\t%0,%3" [(set_attr "type" "fp") (set_attr "mode" "SI") (set_attr "length" "7")]) ;; ;; Conversion patterns ;; (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:SI 1 "register_operand" "d")))] "" "mi2f\\t%0,%1\\n\\tcvtis\\t%0,%0" [(set_attr "type" "fp") (set_attr "mode" "SF") (set_attr "length" "2") ]) (define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:SI 1 "register_operand" "d")))] "" "mi2f\\t%0,%1\\n\\tcvtid\\t%0,%0" [(set_attr "type" "fp") (set_attr "mode" "DF") (set_attr "length" "2")]) (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (match_operand:SF 1 "register_operand" "+f"))) (clobber (match_scratch:SF 2 "=&f"))] "" "cvtsi\\t%2,%1\\n\\tmf2i\\t%0,%2\\n" [(set_attr "type" "fp") (set_attr "mode" "SF") (set_attr "length" "2")]) (define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (match_operand:DF 1 "register_operand" "+f"))) (clobber (match_scratch:DF 2 "=&f"))] "" "cvtdi\\t%2,%1\\n\\tmf2i\\t%0,%2\\n" [(set_attr "type" "fp") (set_attr "mode" "DF") (set_attr "length" "2")]) (define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "" "cvtds\\t%0,%1" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=d,m") (truncate:HI (match_operand:SI 1 "register_operand" "d,d")))] "" "@ slli\\t%0,%1,#16\\n\\tsrli\\t%0,%0,#16 sh\\t%0,%1" [(set_attr "type" "alu,store") (set_attr "mode" "HI") (set_attr "length" "2,1")]) (define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=d,m") (truncate:QI (match_operand:SI 1 "register_operand" "d,d")))] "" "@ andi\\t%0,%1,#0x00ff sb\\t%0,%1" [(set_attr "type" "alu,store") (set_attr "mode" "QI")]) (define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=d,m") (truncate:QI (match_operand:HI 1 "register_operand" "d,d")))] "" "@ andi\\t%0,%1,#0x00ff sb\\t%0,%1" [(set_attr "type" "alu,store") (set_attr "mode" "QI")]) (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=d,d") (zero_extend:HI (match_operand:QI 1 "general_operand" "d,m")))] "" "@ andi\\t%0,%1,#0x00ff lbu\\t%0,%1" [(set_attr "type" "alu,load") (set_attr "mode" "HI")]) (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (zero_extend:SI (match_operand:HI 1 "general_operand" "d,m")))] "" "@ slli\\t%0,%1,#16\\n\\tsrli\\t%0,%0,#16 lhu\\t%0,%1" [(set_attr "type" "alu,load") (set_attr "mode" "SI") (set_attr "length" "2,1")]) (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (zero_extend:SI (match_operand:QI 1 "general_operand" "d,m")))] "" "@ andi\\t%0,%1,#0x00ff lbu\\t%0,%1" [(set_attr "type" "alu,load") (set_attr "mode" "SI")]) (define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:QI 1 "general_operand" "d,m")))] "" "@ slli\\t%0,%1,#24\\n\\tsrai\\t%0,%0,#24 lb\\t%0,%1" [(set_attr "type" "alu,load") (set_attr "mode" "SI") (set_attr "length" "2,1")]) (define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=d,d") (sign_extend:SI (match_operand:HI 1 "general_operand" "d,m")))] "" "@ slli\\t%0,%1,#16\\n\\tsrai\\t%0,%0,#16 lh\\t%0,%1" [(set_attr "type" "alu,load") (set_attr "mode" "SI") (set_attr "length" "2,1")]) (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=d") (sign_extend:HI (match_operand:QI 1 "register_operand" "d")))] "" "slli\\t%0,%1,#24\\n\\tsrai\\t%0,%0,#8\\n\\tsrli\\t%0,%0,#16" [(set_attr "type" "alu") (set_attr "mode" "HI") (set_attr "length" "3")]) (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "cvtsd\\t%0,%1" [(set_attr "type" "fp") (set_attr "mode" "DF")]) ;; ;; move instructions: ;; mem-reg, reg-mem, imm-reg ;; ;; The standard "movsi" pattern for RTL generation. It ;; makes sure one of the operands is in a register, but ;; avoids trying to do this later during compilation when ;; the register allocation is complete. ;; ;; This pattern was lifted almost verbatim from the MIPS machine ;; description. ;; (define_expand "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { if ((reload_in_progress | reload_completed) == 0 && !register_operand (operands[0], SImode) && !register_operand (operands[1], SImode)) { rtx temp = force_reg (SImode, operands[1]); temp = emit_move_insn (operands[0], temp); DONE; } }") ;; ;; This is used to match against RTL during assembly code ;; generation. It knows how to move floats in and out of ;; integer registers. ;; ;; We have to be sure to set the length correctly. Otherwise, ;; the delay slot filler will try to move something into a delay ;; slot that produces more than one DLX instruction, which would ;; produce incorrect code. So when we generate an addui/lhi sequence ;; to load a constant, we have to make sure the length is set to 2. ;; ;; case1: ;; here addui is replaced by addi and a masking that removes sign extension ;; for we have no addi without se ;; perhaps to be replaced by a lhi followed by a 16bit right shift ;; case2: ;; here the lhi/addui sequence had to be replaced, for we have no unsigned ;; Addition where no sign-extension is made ;; so here we need our special fixed TMP Register r28 (define_insn "movsi_general" [(set (match_operand:SI 0 "general_operand" "=d,d,d,d,m,df") (match_operand:SI 1 "general_operand" "I,L,i,m,d,df"))] "" "* { switch(which_alternative) { case 0: return \"addi\\t%0,r0,%G1\"; case 1: return \"lhi\\t%0,%U1\\n\\tsrli\\t%0,%0,#16\"; case 2: if(GET_CODE(operands[1]) == CONST_INT) { return \"lhi\\t%0,%H1\\n\\tlhi\\tr28,%L1\\n\\tsrli\\tr28,r28,#16\\n\\tadd\\t%0,%0,r28\"; } else { return \"lhi\\t%0,((%1)>>16)&0xffff\\n\\tlhi\\tr28,(%1)&0xffff\\n\\tsrli\\tr28,r28,#16\\n\\tadd\\t%0,%0,r28\"; } case 3: return \"lw\\t%0,%1\"; case 4: return \"sw\\t%0,%1\"; case 5: { int f0,f1; f0 = FLOAT_MODE_P(GET_MODE(operands[0])); f1 = FLOAT_MODE_P(GET_MODE(operands[1])); if(!f0 && !f1) return \"add\\t%0,r0,%1\"; else if(!f0 && f1) return \"mf2i\\t%0,%1\"; else if(f0 && !f1) return \"mi2f\\t%0,%1\"; else return \"fmovs\\t%0,%1\"; } } }" [(set_attr "type" "move,move,move,load,store,move") (set_attr "mode" "SI") (set_attr "length" "1,2,4,1,1,1")]) ;; ;; Move half words. ;; (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)) { rtx temp = force_reg (HImode, operands[1]); temp = emit_move_insn (operands[0], temp); DONE; } }") (define_insn "movhi_general" [(set (match_operand:HI 0 "general_operand" "=d,d,m,d") (match_operand:HI 1 "general_operand" "i,m,d,d"))] "" "* { switch(which_alternative) { case 0: return \"addi\\t%0,r0,%G1\"; case 1: return \"lh\\t%0,%1\"; case 2: return \"sh\\t%0,%1\"; case 3: return \"add\\t%0,r0,%1\"; } }" [(set_attr "type" "move,load,store,move") (set_attr "mode" "HI") (set_attr "length" "1,1,1,1")]) ;; ;; move bytes. ;; (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)) { rtx temp = force_reg (QImode, operands[1]); temp = emit_move_insn (operands[0], temp); DONE; } }") (define_insn "movqi_general" [(set (match_operand:QI 0 "general_operand" "=d,d,m,d") (match_operand:QI 1 "general_operand" "i,m,d,d"))] "" "* { switch(which_alternative) { case 0: return \"addi\\t%0,r0,(%1)&0xff\"; case 1: return \"lb\\t%0,%1\"; case 2: return \"sb\\t%0,%1\"; case 3: return \"add\\t%0,r0,%1\"; } }" [(set_attr "type" "move,load,store,move") (set_attr "mode" "QI") (set_attr "length" "1,1,1,1")]) ;; ;; Move floats. ;; (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)) { rtx temp = force_reg (SFmode, operands[1]); temp = emit_move_insn (operands[0], temp); DONE; } }") ;; case 2: ;; This pattern has to handle the strange special case of ;; moving a float value into r1 to return it. This is required ;; to be compatible with Peter Dahl's C-Regs C Compiler. ;; (define_insn "movsf_general" [(set (match_operand:SF 0 "general_operand" "=f,m,df") (match_operand:SF 1 "general_operand" "m,f,df"))] "" "* { switch(which_alternative) { case 0: return \"loads\\t%0,%1\"; case 1: return \"stores\\t%0,%1\"; case 2: { int f0,f1; f0 = (REGNO(operands[0]) >= FIRST_FP_REG); f1 = (REGNO(operands[1]) >= FIRST_FP_REG); if(!f0 && !f1) return \"add\\t%0,r0,%1\"; else if(!f0 && f1) return \"mf2i\\t%0,%1\"; else if(f0 && !f1) return \"mi2f\\t%0,%1\"; else return \"fmovs\\t%0,%1\"; } } }" [(set_attr "type" "load,store,move") (set_attr "mode" "SF")]) (define_expand "movdf" [(set (match_operand:DF 0 "nonimmediate_operand" "") (match_operand:DF 1 "general_operand" ""))] "" " { if ((reload_in_progress | reload_completed) == 0 && !register_operand (operands[0], DFmode) && !register_operand (operands[1], DFmode)) { rtx temp = force_reg (DFmode, operands[1]); temp = emit_move_insn (operands[0], temp); DONE; } }") (define_insn "movdf_general" [(set (match_operand:DF 0 "general_operand" "=f,m,f") (match_operand:DF 1 "general_operand" "m,f,f"))] "" "* { switch(which_alternative) { case 0: return \"loadd\\t%0,%1\"; case 1: return \"stored\\t%0,%1\"; case 2: return \"fmovd\\t%0,%1\"; } }" [(set_attr "type" "load,store,move") (set_attr "mode" "DF")]) ;; ;; No-Op ;; (define_insn "nop" [(const_int 0)] "" "nop" [(set_attr "type" "alu") (set_attr "mode" "none") (set_attr "length" "1")]) ;; ;; unconditional branches and such. ;; (define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "d"))] "" "jr\\t%0%(" [(set_attr "type" "jump") (set_attr "mode" "none")]) (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "* { if (GET_CODE (operands[0]) == REG) return \"jr\\t%0%(\"; else return \"j\\t%0%(\"; }" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; calls ;; (define_expand "call_value" [(parallel [(set (match_operand 0 "register_operand" "=df") (call (match_operand 1 "sym_ref_mem_operand" "") (match_operand 2 "" "i"))) (clobber (reg:SI 31))])] "" "{ gen_call_value_1(operands); DONE; }") (define_insn "call" [(parallel [(call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i")) (clobber (reg:SI 31))])] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) (define_insn "call_value_indirect" [(parallel [(set (match_operand 0 "register_operand" "=df") (call (mem:QI (match_operand 1 "register_operand" "d")) (match_operand 2 "" "i"))) (clobber (reg:SI 31))])] "" "jalr\\t%1%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) (define_insn "call_indirect" [(parallel [(call (mem:QI (match_operand 0 "register_operand" "d")) (match_operand 1 "" "i")) (clobber (reg:SI 31))])] "" "jalr\\t%0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; RTL for this is generated by the define_expand for call_value. ;; ;; ;; calls that return int in r1 ;; (define_insn "call_val_internal_return_r1" [(parallel [(set (reg:SI 1) (call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))) (clobber (reg:SI 31))])] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) (define_insn "call_val_internal_return_r1_halfword" [(parallel [(set (reg:HI 1) (call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))) (clobber (reg:SI 31))])] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) (define_insn "call_val_internal_return_r1_quarterword" [(parallel [(set (reg:QI 1) (call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))) (clobber (reg:SI 31))])] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; calls that return float in f0 ;; (define_insn "call_val_internal_return_f0_float" [(parallel [(set (reg:SF 32) (call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))) (clobber (reg:SI 31))])] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; calls that return double in f0/f1 ;; (define_insn "call_val_internal_return_f0f1" [(parallel [(set (reg:DF 32) (call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))) (clobber (reg:SI 31))])] "" "jal\\t%S0%(\\n" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; calls that don't return a value. ;; (define_insn "call_val_internal_no_return" [(call (match_operand 0 "sym_ref_mem_operand" "") (match_operand 1 "" "i"))] "" "jal\\t%S0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "slot_usable" "no")]) ;; ;; tablejump insn; used in generating code for switches. ;; (define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "d")) (use (label_ref (match_operand 1 "" "")))] "" "jr\\t%0%(" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1") (set_attr "slot_usable" "no")]) ;; ;; Comparisons and branches. ;; (define_expand "cmpsi" [(set (cc0) (compare:CC (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "nonmemory_operand" "dI")))] "" " { dlx_compare_op0 = operands[0]; dlx_compare_op1 = operands[1]; dlx_compare_mode = SImode; DONE; }") (define_expand "tstsi" [(set (cc0) (match_operand:SI 0 "register_operand" "d"))] "" " { dlx_compare_op0 = operands[0]; dlx_compare_op1 = const0_rtx; dlx_compare_mode = SImode; DONE; }") (define_expand "cmpdf" [(set (cc0) (compare:CCFP (match_operand:DF 0 "register_operand" "f") (match_operand:DF 1 "register_operand" "f")))] "" " { dlx_compare_op0 = operands[0]; dlx_compare_op1 = operands[1]; dlx_compare_mode = DFmode; DONE; }") (define_expand "cmpsf" [(set (cc0) (compare:CCFP (match_operand:SF 0 "register_operand" "f") (match_operand:SF 1 "register_operand" "f")))] "" " { dlx_compare_op0 = operands[0]; dlx_compare_op1 = operands[1]; dlx_compare_mode = SFmode; DONE; }") ;; ;; Branches. ;; These have to be written out individually because they ;; are called by name during code generation. ;; (define_expand "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, EQ); DONE; }") (define_expand "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, NE); DONE; }") (define_expand "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, LT); DONE; }") (define_expand "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, GT); DONE; }") (define_expand "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, LE); DONE; }") (define_expand "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, GE); DONE; }") (define_expand "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, LTU); DONE; }") (define_expand "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, GTU); DONE; }") (define_expand "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, LEU); DONE; }") (define_expand "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ gen_conditional_branch(operands, GEU); DONE; }") ; ; Set instructions. ; (define_expand "seq" [(set (match_operand:SI 0 "register_operand" "=d") (eq:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sne" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "slt" [(set (match_operand:SI 0 "register_operand" "=d") (lt:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "=d") (gt:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sle" [(set (match_operand:SI 0 "register_operand" "=d") (le:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sge" [(set (match_operand:SI 0 "register_operand" "=d") (ge:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sltu" [(set (match_operand:SI 0 "register_operand" "=d") (ltu:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sgtu" [(set (match_operand:SI 0 "register_operand" "=d") (gtu:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sleu" [(set (match_operand:SI 0 "register_operand" "=d") (leu:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0; operands[2] = dlx_compare_op1; ") (define_expand "sgeu" [(set (match_operand:SI 0 "register_operand" "=d") (geu:SI (match_dup 1) (match_dup 2)))] "" " if(dlx_compare_mode != SImode) FAIL; operands[1] = dlx_compare_op0;; operands[2] = dlx_compare_op1; ") ;; ;; Integer conditional branches; the RTL for these is ;; generated in gen_conditional_branch(). ;; (define_insn "int_cond_branch" [(set (pc) (if_then_else (eq:SI (const_int 0) (match_operand:SI 0 "register_operand" "d")) (label_ref (match_operand 1 "" "")) (pc)))] "" "beqz\\t%0,%1%(" [(set_attr "type" "branch") (set_attr "mode" "SI") (set_attr "slot_usable" "no")]) (define_insn "int_cond_branch_rev" [(set (pc) (if_then_else (ne:SI (const_int 0) (match_operand:SI 0 "register_operand" "d")) (label_ref (match_operand 1 "" "")) (pc)))] "" "bnez\\t%0,%1%(" [(set_attr "type" "branch") (set_attr "mode" "SI") (set_attr "slot_usable" "no")]) ;; ;; Floating point conditional branches, ;; also generated in gen_conditional_branch(). ;; (define_insn "fp_cond_branch" [(set (pc) (if_then_else (ne:CCFP (match_operand:CCFP 0 "register_operand" "z") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" "fbnez\\t%1%(" [(set_attr "type" "branch") (set_attr "mode" "SF") (set_attr "slot_usable" "no")]) (define_insn "fp_cond_branch_rev" [(set (pc) (if_then_else (eq:CCFP (match_operand:CCFP 0 "register_operand" "z") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc)))] "" "fbeqz\\t%1%(" [(set_attr "type" "branch") (set_attr "mode" "SF") (set_attr "slot_usable" "no")]) ;; ;; RTL for s__ instructions. ;; The RTL for these is generated in gen_conditional_branch(). ;; ;; (define_insn "set_internal" [(set (match_operand:SI 0 "register_operand" "=d,d") (match_operator:SI 1 "comparison_operator" [(match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "nonmemory_operand" "d,I")]))] "" "* { switch(which_alternative) { static int cmlabelcnt=0; static char cmbuf[500]; case 0: { enum rtx_code code = GET_CODE(operands[1]); switch (code) { case GTU: sprintf(cmbuf, \"srli\\tr28,%%2,#1\\n\\tsrli\\tr27,%%3,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tsub\\tr28,%%3,%%2\\nCML%d:\\n\\tslti\\t%%0,r28,#0\" , cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case GEU: sprintf(cmbuf, \"srli\\tr28,%%2,#1\\n\\tsrli\\tr27,%%3,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tsub\\tr28,%%3,%%2\\nCML%d:\\n\\tslei\\t%%0,r28,#0\" , cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case LTU: sprintf(cmbuf, \"srli\\tr28,%%2,#1\\n\\tsrli\\tr27,%%3,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tsub\\tr28,%%3,%%2\\nCML%d:\\n\\tsgti\\t%%0,r28,#0\" , cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case LEU: sprintf(cmbuf, \"srli\\tr28,%%2,#1\\n\\tsrli\\tr27,%%3,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tsub\\tr28,%%3,%%2\\nCML%d:\\n\\tsgei\\t%%0,r28,#0\" , cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; default : return \"s%C1\\t%0,%2,%3\"; } } case 1: { enum rtx_code code = GET_CODE(operands[1]); switch (code) { case GTU: sprintf(cmbuf, \"lhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#17\\n\\tsrli\\tr28,%%2,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tlhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#16\\n\\tsub\\tr28,r27,%%2\\nCML%d:\\n\\tslti\\t%%0,r28,#0\", cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case GEU: sprintf(cmbuf, \"lhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#17\\n\\tsrli\\tr28,%%2,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tlhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#16\\n\\tsub\\tr28,r27,%%2\\nCML%d:\\n\\tslei\\t%%0,r28,#0\", cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case LTU: sprintf(cmbuf, \"lhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#17\\n\\tsrli\\tr28,%%2,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tlhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#16\\n\\tsub\\tr28,r27,%%2\\nCML%d:\\n\\tsgti\\t%%0,r28,#0\", cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; case LEU:sprintf(cmbuf, \"lhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#17\\n\\tsrli\\tr28,%%2,#1\\n\\tsub\\tr28,r27,r28\\n\\tbnez\\tr28,CML%d\\n\\tnop\\n\\tlhi\\tr27,%%G3\\n\\tsrli\\tr27,r27,#16\\n\\tsub\\tr28,r27,%%2\\nCML%d:\\n\\tsgei\\t%%0,r28,#0\", cmlabelcnt, cmlabelcnt); cmlabelcnt++; return cmbuf;break; default : return \"s%C1i\\t%0,%2,%G3\"; } } } }" [(set_attr "type" "alu") (set_attr "mode" "SI") (set_attr "length" "7,10")]) ;; ;; Float compares. ;; The RTL for these is also generated in ;; gen_conditional_branch(). ;; (define_insn "" [(set (match_operand:CCFP 0 "register_operand" "=z") (match_operator:SF 1 "signed_comparison_operator" [(match_operand:SF 2 "register_operand" "f") (match_operand:SF 3 "register_operand" "f")]))] "" "fc%C1s\\t%2,%3" [(set_attr "type" "fp") (set_attr "mode" "SF")]) (define_insn "" [(set (match_operand:CCFP 0 "register_operand" "=z") (match_operator:DF 1 "signed_comparison_operator" [(match_operand:DF 2 "register_operand" "f") (match_operand:DF 3 "register_operand" "f")]))] "" "fc%C1d\\t%2,%3" [(set_attr "type" "fp") (set_attr "mode" "DF")])