;; Machine description for GNU compiler, Tahoe version ;; Copyright (C) 1989, 1994 Free Software Foundation, Inc. ;; 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, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ; File: tahoe.md ; ; Original port made at the University of Buffalo by Devon Bowen, ; Dale Wiles and Kevin Zachmann. ; ; Piet van Oostrum (piet@cs.ruu.nl) made changes for HCX/UX, fixed ; some bugs and made some improvements (hopefully). ; ; Mail bugs reports or fixes to: gcc@cs.buffalo.edu ; movdi must call the output_move_double routine to move it around since ; the tahoe doesn't efficiently support 8 bit moves. (define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=g") (match_operand:DI 1 "general_operand" "g"))] "" "* { CC_STATUS_INIT; return output_move_double (operands); }") ; the trick in the movsi is accessing the contents of the sp register. The ; tahoe doesn't allow you to access it directly so you have to access the ; address of the top of the stack instead. (define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:SI 1 "general_operand" "g"))] "" "* { rtx link; if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) && ! INSN_DELETED_P (XEXP (link, 0)) && GET_CODE (XEXP (link, 0)) != NOTE && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) return \"incl %0\"; if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) { if (push_operand (operands[0], SImode)) return \"pushab %a1\"; return \"movab %a1,%0\"; } if (operands[1] == const0_rtx) return \"clrl %0\"; if (push_operand (operands[0], SImode)) return \"pushl %1\"; if (GET_CODE(operands[1]) == REG && REGNO(operands[1]) == 14) return \"moval (sp),%0\"; return \"movl %1,%0\"; }") (define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=g") (match_operand:HI 1 "general_operand" "g"))] "" "* { rtx link; if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) && ! INSN_DELETED_P (XEXP (link, 0)) && GET_CODE (XEXP (link, 0)) != NOTE && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) return \"incw %0\"; if (operands[1] == const0_rtx) return \"clrw %0\"; return \"movw %1,%0\"; }") (define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=g") (match_operand:QI 1 "general_operand" "g"))] "" "* { if (operands[1] == const0_rtx) return \"clrb %0\"; return \"movb %1,%0\"; }") ; movsf has three cases since they can move from one place to another ; or to/from the fpp and since different instructions are needed for ; each case. The fpp related instructions don't set the flags properly. (define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=g,=a,=g") (match_operand:SF 1 "general_operand" "g,g,a"))] "" "* { CC_STATUS_INIT; switch (which_alternative) { case 0: return \"movl %1,%0\"; case 1: return \"ldf %1\"; case 2: return \"stf %0\"; } }") ; movdf has a number of different cases. If it's going to or from ; the fpp, use the special instructions to do it. If not, use the ; output_move_double function. (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=a,=g,?=g") (match_operand:DF 1 "general_operand" "g,a,g"))] "" "* { CC_STATUS_INIT; switch (which_alternative) { case 0: return \"ldd %1\"; case 1: if (push_operand (operands[0], DFmode)) return \"pushd\"; else return \"std %0\"; case 2: return output_move_double (operands); } }") ;======================================================================== ; The tahoe has the following semantics for byte (and similar for word) ; operands: if the operand is a register or immediate, it takes the full 32 ; bit operand, if the operand is memory, it sign-extends the byte. The ; operation is performed on the 32 bit values. If the destination is a ; register, the full 32 bit result is stored, if the destination is memory, ; of course only the low part is stored. The condition code is based on the ; 32 bit operation. Only on the movz instructions the byte from memory is ; zero-extended rather than sign-extended. ; This means that for arithmetic instructions we can use addb etc. to ; perform a long add from a signed byte from memory to a register. Of ; course this would also work for logical operations, but that doesn't seem ; very useful. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] "" "addb3 %1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "nonmemory_operand" "%ri") (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"addb2 %2,%0\"; return \"addb3 %1,%2,%0\"; }") ; We can also consider the result to be a half integer (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (plus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] "" "addb3 %1,%2,%0") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (plus:HI (match_operand:HI 1 "nonmemory_operand" "%ri") (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"addb2 %2,%0\"; return \"addb3 %1,%2,%0\"; }") ; The same applies to words (HI) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] "" "addw3 %1,%2,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "nonmemory_operand" "%ri") (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"addw2 %2,%0\"; return \"addw3 %1,%2,%0\"; }") ; ======================= Now for subtract ============================== (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] "" "subb3 %2,%1,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "nonmemory_operand" "ri") (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"subb2 %2,%0\"; return \"subb3 %2,%1,%0\"; }") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) (match_operand:SI 2 "nonmemory_operand" "ri")))] "" "subb3 %2,%1,%0") ; We can also consider the result to be a half integer (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (minus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] "" "subb3 %2,%1,%0") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (minus:HI (match_operand:HI 1 "nonmemory_operand" "%ri") (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"subb2 %2,%0\"; return \"subb3 %2,%1,%0\"; }") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (minus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) (match_operand:HI 2 "nonmemory_operand" "ri")))] "" "subb3 %2,%1,%0") ; The same applies to words (HI) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] "" "subw3 %2,%1,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "nonmemory_operand" "ri") (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"subw2 %2,%0\"; return \"subw3 %2,%1,%0\"; }") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) (match_operand:SI 2 "nonmemory_operand" "ri")))] "" "subw3 %2,%1,%0") ; ======================= Now for neg ============================== (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] "" "mnegb %1,%0") (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (neg:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m"))))] "" "mnegb %1,%0") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] "" "mnegw %1,%0") ;======================================================================== (define_insn "addsi3" [(set (match_operand:SI 0 "general_operand" "=g") (plus:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incl %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"decl %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl2 $%n2,%0\"; return \"addl2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addl2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == REG) { if (push_operand (operands[0], SImode)) return \"pushab %c2(%1)\"; return \"movab %c2(%1),%0\"; } if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl3 $%n2,%1,%0\"; return \"addl3 %1,%2,%0\"; }") (define_insn "addhi3" [(set (match_operand:HI 0 "general_operand" "=g") (plus:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incw %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"decw %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subw2 $%n2,%0\"; return \"addw2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addw2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subw3 $%n2,%1,%0\"; return \"addw3 %1,%2,%0\"; }") (define_insn "addqi3" [(set (match_operand:QI 0 "general_operand" "=g") (plus:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incb %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"decb %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subb2 $%n2,%0\"; return \"addb2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addb2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subb3 $%n2,%1,%0\"; return \"addb3 %1,%2,%0\"; }") ; addsf3 can only add into the fpp register since the fpp is treated ; as a separate unit in the machine. It also doesn't set the flags at ; all. (define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=a") (plus:SF (match_operand:SF 1 "register_operand" "%0") (match_operand:SF 2 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"addf %2\"; }") ; adddf3 can only add into the fpp reg since the fpp is treated as a ; separate entity. Doubles can only be read from a register or memory ; since a double is not an immediate mode. Flags are not set by this ; instruction. (define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=a") (plus:DF (match_operand:DF 1 "register_operand" "%0") (match_operand:DF 2 "general_operand" "rm")))] "" "* { CC_STATUS_INIT; return \"addd %2\"; }") ; Subtraction from the sp (needed by the built in alloc function) needs ; to be different since the sp cannot be directly read on the tahoe. ; If it's a simple constant, you just use displacement. Otherwise, you ; push the sp, and then do the subtraction off the stack. (define_insn "subsi3" [(set (match_operand:SI 0 "general_operand" "=g") (minus:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decl %0\"; if (GET_CODE(operands[0]) == REG && REGNO(operands[0]) == 14) { if (GET_CODE(operands[2]) == CONST_INT) return \"movab %n2(sp),sp\"; else return \"pushab (sp)\;subl3 %2,(sp),sp\"; } return \"subl2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrl %0\"; return \"subl3 %2,%1,%0\"; }") (define_insn "subhi3" [(set (match_operand:HI 0 "general_operand" "=g") (minus:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decw %0\"; return \"subw2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrw %0\"; return \"subw3 %2,%1,%0\"; }") (define_insn "subqi3" [(set (match_operand:QI 0 "general_operand" "=g") (minus:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decb %0\"; return \"subb2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrb %0\"; return \"subb3 %2,%1,%0\"; }") ; subsf3 can only subtract into the fpp accumulator due to the way ; the fpp reg is limited by the instruction set. This also doesn't ; bother setting up flags. (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=a") (minus:SF (match_operand:SF 1 "register_operand" "0") (match_operand:SF 2 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"subf %2\"; }") ; subdf3 is set up to subtract into the fpp reg due to limitations ; of the fpp instruction set. Doubles can not be immediate. This ; instruction does not set the flags. (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=a") (minus:DF (match_operand:DF 1 "register_operand" "0") (match_operand:DF 2 "general_operand" "rm")))] "" "* { CC_STATUS_INIT; return \"subd %2\"; }") (define_insn "mulsi3" [(set (match_operand:SI 0 "general_operand" "=g") (mult:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"mull2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"mull2 %1,%0\"; return \"mull3 %1,%2,%0\"; }") ; mulsf3 can only multiply into the fpp accumulator due to limitations ; of the fpp. It also does not set the condition codes properly. (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=a") (mult:SF (match_operand:SF 1 "register_operand" "%0") (match_operand:SF 2 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"mulf %2\"; }") ; muldf3 can only multiply into the fpp reg since the fpp is limited ; from the rest. Doubles may not be immediate mode. This does not set ; the flags like gcc would expect. (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=a") (mult:DF (match_operand:DF 1 "register_operand" "%0") (match_operand:DF 2 "general_operand" "rm")))] "" "* { CC_STATUS_INIT; return \"muld %2\"; }") (define_insn "divsi3" [(set (match_operand:SI 0 "general_operand" "=g") (div:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[1], operands[2])) return \"movl $1,%0\"; if (operands[1] == const0_rtx) return \"clrl %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"mnegl %1,%0\"; if (rtx_equal_p (operands[0], operands[1])) return \"divl2 %2,%0\"; return \"divl3 %2,%1,%0\"; }") ; divsf3 must divide into the fpp accumulator. Flags are not set by ; this instruction, so they are cleared. (define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=a") (div:SF (match_operand:SF 1 "register_operand" "0") (match_operand:SF 2 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"divf %2\"; }") ; divdf3 also must divide into the fpp reg so optimization isn't ; possible. Note that doubles cannot be immediate. The flags here ; are not set correctly so they must be ignored. (define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=a") (div:DF (match_operand:DF 1 "register_operand" "0") (match_operand:DF 2 "general_operand" "rm")))] "" "* { CC_STATUS_INIT; return \"divd %2\"; }") (define_insn "andsi3" [(set (match_operand:SI 0 "general_operand" "=g") (and:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"andl2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"andl2 %1,%0\"; return \"andl3 %2,%1,%0\"; }") (define_insn "andhi3" [(set (match_operand:HI 0 "general_operand" "=g") (and:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"andw2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"andw2 %1,%0\"; return \"andw3 %2,%1,%0\"; }") (define_insn "andqi3" [(set (match_operand:QI 0 "general_operand" "=g") (and:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"andb2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"andb2 %1,%0\"; return \"andb3 %2,%1,%0\"; }") (define_insn "iorsi3" [(set (match_operand:SI 0 "general_operand" "=g") (ior:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"orl2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"orl2 %1,%0\"; return \"orl3 %2,%1,%0\"; }") (define_insn "iorhi3" [(set (match_operand:HI 0 "general_operand" "=g") (ior:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"orw2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"orw2 %1,%0\"; return \"orw3 %2,%1,%0\"; }") (define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=g") (ior:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"orb2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"orb2 %1,%0\"; return \"orb3 %2,%1,%0\"; }") (define_insn "xorsi3" [(set (match_operand:SI 0 "general_operand" "=g") (xor:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"xorl2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"xorl2 %1,%0\"; return \"xorl3 %2,%1,%0\"; }") (define_insn "xorhi3" [(set (match_operand:HI 0 "general_operand" "=g") (xor:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"xorw2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"xorw2 %1,%0\"; return \"xorw3 %2,%1,%0\"; }") (define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=g") (xor:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (rtx_equal_p (operands[0], operands[1])) return \"xorb2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"xorb2 %1,%0\"; return \"xorb3 %2,%1,%0\"; }") ; shifts on the tahoe are expensive, try some magic first... (define_insn "ashlsi3" [(set (match_operand:SI 0 "general_operand" "=g") (ashift:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "* { if (GET_CODE(operands[2]) == REG) return \"mull3 ___shtab[%2],%1,%0\"; /* if (GET_CODE(operands[2]) == REG) if (rtx_equal_p (operands[0], operands[1])) return \"mull2 ___shtab[%2],%1\"; else return \"mull3 ___shtab[%2],%1,%0\"; */ if (GET_CODE(operands[1]) == REG) { if (operands[2] == const1_rtx) { CC_STATUS_INIT; return \"movaw 0[%1],%0\"; } if (GET_CODE(operands[2]) == CONST_INT && INTVAL(operands[2]) == 2) { CC_STATUS_INIT; return \"moval 0[%1],%0\"; } } if (GET_CODE(operands[2]) != CONST_INT || INTVAL(operands[2]) == 1) return \"shal %2,%1,%0\"; if (rtx_equal_p (operands[0], operands[1])) return \"mull2 %s2,%1\"; else return \"mull3 %s2,%1,%0\"; }") (define_insn "ashrsi3" [(set (match_operand:SI 0 "general_operand" "=g") (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "shar %2,%1,%0") ; shifts are very expensive, try some magic first... (define_insn "lshrsi3" [(set (match_operand:SI 0 "general_operand" "=g") (lshiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "shrl %2,%1,%0") (define_insn "negsi2" [(set (match_operand:SI 0 "general_operand" "=g") (neg:SI (match_operand:SI 1 "general_operand" "g")))] "" "mnegl %1,%0") (define_insn "neghi2" [(set (match_operand:HI 0 "general_operand" "=g") (neg:HI (match_operand:HI 1 "general_operand" "g")))] "" "mnegw %1,%0") (define_insn "negqi2" [(set (match_operand:QI 0 "general_operand" "=g") (neg:QI (match_operand:QI 1 "general_operand" "g")))] "" "mnegb %1,%0") ; negsf2 can only negate the value already in the fpp accumulator. ; The value remains in the fpp accumulator. No flags are set. (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=a,=a") (neg:SF (match_operand:SF 1 "register_operand" "a,g")))] "" "* { CC_STATUS_INIT; switch (which_alternative) { case 0: return \"negf\"; case 1: return \"lnf %1\"; } }") ; negdf2 can only negate the value already in the fpp accumulator. ; The value remains in the fpp accumulator. No flags are set. (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=a,=a") (neg:DF (match_operand:DF 1 "register_operand" "a,g")))] "" "* { CC_STATUS_INIT; switch (which_alternative) { case 0: return \"negd\"; case 1: return \"lnd %1\"; } }") ; sqrtsf2 tahoe can calculate the square root of a float in the ; fpp accumulator. The answer remains in the fpp accumulator. No ; flags are set by this function. (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=a") (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] "" "* { CC_STATUS_INIT; return \"sqrtf\"; }") ; ffssi2 tahoe instruction gives one less than gcc desired result for ; any given input. So the increment is necessary here. (define_insn "ffssi2" [(set (match_operand:SI 0 "general_operand" "=g") (ffs:SI (match_operand:SI 1 "general_operand" "g")))] "" "* { if (push_operand(operands[0], SImode)) return \"ffs %1,%0\;incl (sp)\"; return \"ffs %1,%0\;incl %0\"; }") (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "general_operand" "=g") (not:SI (match_operand:SI 1 "general_operand" "g")))] "" "mcoml %1,%0") (define_insn "one_cmplhi2" [(set (match_operand:HI 0 "general_operand" "=g") (not:HI (match_operand:HI 1 "general_operand" "g")))] "" "mcomw %1,%0") (define_insn "one_cmplqi2" [(set (match_operand:QI 0 "general_operand" "=g") (not:QI (match_operand:QI 1 "general_operand" "g")))] "" "mcomb %1,%0") ; cmpsi works fine, but due to microcode problems, the tahoe doesn't ; properly compare hi's and qi's. Leaving them out seems to be acceptable ; to the compiler, so they were left out. Compares of the stack are ; possible, though. ; There are optimized cases possible, however. These follow first. (define_insn "" [(set (cc0) (compare (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")) (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] "" "cmpw %0,%1") (define_insn "" [(set (cc0) (compare (match_operand:SI 0 "nonmemory_operand" "ri") (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] "" "cmpw %0,%1") (define_insn "" [(set (cc0) (compare (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")) (match_operand:SI 1 "nonmemory_operand" "ri")))] "" "cmpw %0,%1") ; zero-extended compares give the same result as sign-extended compares, if ; the compare is unsigned. Just see: if both operands are <65536 they are the ; same in both cases. If both are >=65536 the you effectively compare x+D ; with y+D, where D=2**32-2**16, so the result is the same. if x<65536 and ; y>=65536 then you compare x with y+D, and in both cases the result is x 32767) operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 0xffff0000); return \"cmpw %0,%1\"; }") (define_insn "" [(set (cc0) (compare (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")) (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] "" "cmpb %0,%1") (define_insn "" [(set (cc0) (compare (match_operand:SI 0 "nonmemory_operand" "ri") (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] "" "cmpb %0,%1") (define_insn "" [(set (cc0) (compare (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")) (match_operand:SI 1 "nonmemory_operand" "ri")))] "" "cmpb %0,%1") ; zero-extended compares give the same result as sign-extended compares, if ; the compare is unsigned. Just see: if both operands are <128 they are the ; same in both cases. If both are >=128 the you effectively compare x+D ; with y+D, where D=2**32-2**8, so the result is the same. if x<128 and ; y>=128 then you compare x with y+D, and in both cases the result is x 127) operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 0xffffff00); return \"cmpb %0,%1\"; }") (define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "g") (match_operand:SI 1 "general_operand" "g")))] "" "cmpl %0,%1") ; cmpsf similar to vax, but first operand is expected to be in the ; fpp accumulator. (define_insn "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "general_operand" "a,g") (match_operand:SF 1 "general_operand" "g,g")))] "" "* { switch (which_alternative) { case 0: return \"cmpf %1\"; case 1: return \"cmpf2 %0,%1\"; } }") ; cmpdf similar to vax, but first operand is expected to be in the ; fpp accumulator. Immediate doubles not allowed. (define_insn "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "a,rm") (match_operand:DF 1 "general_operand" "rm,rm")))] "" "* { switch (which_alternative) { case 0: return \"cmpd %1\"; case 1: return \"cmpd2 %0,%1\"; } }") ;; We don't want to allow a constant operand for test insns because ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. (define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "g"))] "" "tstl %0") ; small tests from memory are normal, but testing from registers doesn't ; expand the data properly. So test in this case does a convert and tests ; the new register data from the stack. ; First some special cases that do work (define_insn "" [(set (cc0) (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")))] "" "tstw %0") (define_insn "" [(set (cc0) (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")))] "tahoe_cmp_check (insn, operands[0], 0)" "tstw %0") (define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "extendable_operand" "m,!r"))] "GET_MODE (operands[0]) != VOIDmode" "* { rtx xoperands[2]; extern rtx tahoe_reg_conversion_loc; switch (which_alternative) { case 0: return \"tstw %0\"; case 1: xoperands[0] = operands[0]; xoperands[1] = tahoe_reg_conversion_loc; output_asm_insn (\"movl %0,%1\", xoperands); xoperands[1] = plus_constant (XEXP (tahoe_reg_conversion_loc, 0), 2); output_asm_insn (\"tstw %a1\", xoperands); return \"\"; } }") (define_insn "" [(set (cc0) (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")))] "" "tstb %0") (define_insn "" [(set (cc0) (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")))] "tahoe_cmp_check (insn, operands[0], 0)" "tstb %0") (define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "extendable_operand" "m,!r"))] "GET_MODE (operands[0]) != VOIDmode" "* { rtx xoperands[2]; extern rtx tahoe_reg_conversion_loc; switch (which_alternative) { case 0: return \"tstb %0\"; case 1: xoperands[0] = operands[0]; xoperands[1] = tahoe_reg_conversion_loc; output_asm_insn (\"movl %0,%1\", xoperands); xoperands[1] = plus_constant (XEXP (tahoe_reg_conversion_loc, 0), 3); output_asm_insn (\"tstb %a1\", xoperands); return \"\"; } }") ; tstsf compares a given value to a value already in the fpp accumulator. ; No flags are set by this so ignore them. (define_insn "tstsf" [(set (cc0) (match_operand:SF 0 "register_operand" "a"))] "" "tstf") ; tstdf compares a given value to a value already in the fpp accumulator. ; immediate doubles not allowed. Flags are ignored after this. (define_insn "tstdf" [(set (cc0) (match_operand:DF 0 "register_operand" "a"))] "" "tstd") ; movstrhi tahoe instruction does not load registers by itself like ; the vax counterpart does. registers 0-2 must be primed by hand. ; we have loaded the registers in the order: dst, src, count. (define_insn "movstrhi" [(set (match_operand:BLK 0 "general_operand" "p") (match_operand:BLK 1 "general_operand" "p")) (use (match_operand:HI 2 "general_operand" "g")) (clobber (reg:SI 0)) (clobber (reg:SI 1)) (clobber (reg:SI 2))] "" "movab %0,r1\;movab %1,r0\;movl %2,r2\;movblk") ; floatsisf2 on tahoe converts the long from reg/mem into the fpp ; accumulator. There are no hi and qi counterparts. Flags are not ; set correctly here. (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=a") (float:SF (match_operand:SI 1 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"cvlf %1\"; }") ; floatsidf2 on tahoe converts the long from reg/mem into the fpp ; accumulator. There are no hi and qi counterparts. Flags are not ; set correctly here. (define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=a") (float:DF (match_operand:SI 1 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"cvld %1\"; }") ; fix_truncsfsi2 to convert a float to long, tahoe must have the float ; in the fpp accumulator. Flags are not set here. (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "general_operand" "=g") (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "a"))))] "" "* { CC_STATUS_INIT; return \"cvfl %0\"; }") ; fix_truncsfsi2 to convert a double to long, tahoe must have the double ; in the fpp accumulator. Flags are not set here. (define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "general_operand" "=g") (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a"))))] "" "* { CC_STATUS_INIT; return \"cvdl %0\"; }") (define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=g") (truncate:HI (match_operand:SI 1 "general_operand" "g")))] "" "cvtlw %1,%0") (define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:SI 1 "general_operand" "g")))] "" "cvtlb %1,%0") (define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:HI 1 "general_operand" "g")))] "" "cvtwb %1,%0") ; The fpp related instructions don't set flags, so ignore them ; after this instruction. (define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=a") (float_truncate:SF (match_operand:DF 1 "register_operand" "0")))] "" "* { CC_STATUS_INIT; return \"cvdf\"; }") ; This monster is to cover for the Tahoe's nasty habit of not extending ; a number if the source is in a register. (It just moves it!) Case 0 is ; a normal extend from memory. Case 1 does the extension from the top of ; the stack. Extension from the stack doesn't set the flags right since ; the moval changes them. (define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=g,?=g") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"cvtwl %1,%0\"; case 1: if (push_operand (operands[0], SImode)) return \"pushl %1\;cvtwl 2(sp),(sp)\"; else { CC_STATUS_INIT; return \"pushl %1\;cvtwl 2(sp),%0\;moval 4(sp),sp\"; } } }") ; This monster is to cover for the Tahoe's nasty habit of not extending ; a number if the source is in a register. (It just moves it!) Case 0 is ; a normal extend from memory. Case 1 does the extension from the top of ; the stack. Extension from the stack doesn't set the flags right since ; the moval changes them. (define_insn "extendqisi2" [(set (match_operand:SI 0 "general_operand" "=g,?=g") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"cvtbl %1,%0\"; case 1: if (push_operand (operands[0], SImode)) return \"pushl %1\;cvtbl 3(sp),(sp)\"; else { CC_STATUS_INIT; return \"pushl %1\;cvtbl 3(sp),%0\;moval 4(sp),sp\"; } } }") ; This monster is to cover for the Tahoe's nasty habit of not extending ; a number if the source is in a register. (It just moves it!) Case 0 is ; a normal extend from memory. Case 1 does the extension from the top of ; the stack. Extension from the stack doesn't set the flags right since ; the moval changes them. (define_insn "extendqihi2" [(set (match_operand:HI 0 "general_operand" "=g,?=g") (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"cvtbw %1,%0\"; case 1: if (push_operand (operands[0], SImode)) return \"pushl %1\;cvtbw 3(sp),(sp)\"; else { CC_STATUS_INIT; return \"pushl %1\;cvtbw 3(sp),%0\;moval 4(sp),sp\"; } } }") ; extendsfdf2 tahoe uses the fpp accumulator to do the extension. ; It takes a float and loads it up directly as a double. (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=a") (float_extend:DF (match_operand:SF 1 "general_operand" "g")))] "" "* { CC_STATUS_INIT; return \"ldfd %1\"; }") ; movz works fine from memory but not from register for the same reasons ; the cvt instructions don't work right. So we use the normal instruction ; from memory and we use an and to simulate it from register. This is faster ; than pulling it off the stack. (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "general_operand" "=g,?=g") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"movzwl %1,%0\"; case 1: return \"andl3 $0xffff,%1,%0\"; } }") ; movz works fine from memory but not from register for the same reasons ; the cvt instructions don't work right. So we use the normal instruction ; from memory and we use an and to simulate it from register. This is faster ; than pulling it off the stack. (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "general_operand" "=g,?=g") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"movzbw %1,%0\"; case 1: return \"andw3 $0xff,%1,%0\"; } }") ; movz works fine from memory but not from register for the same reasons ; the cvt instructions don't work right. So we use the normal instruction ; from memory and we use an and to simulate it from register. This is faster ; than pulling it off the stack. (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "general_operand" "=g,?=g") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] "" "* { switch (which_alternative) { case 0: return \"movzbl %1,%0\"; case 1: return \"andl3 $0xff,%1,%0\"; } }") (define_insn "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jeql %l0") (define_insn "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jneq %l0") (define_insn "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jgtr %l0") (define_insn "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jgtru %l0") (define_insn "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jlss %l0") (define_insn "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jlssu %l0") (define_insn "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jgeq %l0") (define_insn "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jgequ %l0") (define_insn "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jleq %l0") (define_insn "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jlequ %l0") ; gcc does not account for register mask/argc longword. Thus the number ; for the call = number bytes for args + 4 (define_insn "call" [(call (match_operand:QI 0 "memory_operand" "m") (match_operand:QI 1 "general_operand" "g"))] "" "* { operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 4)); if (GET_CODE(operands[0]) == MEM && CONSTANT_ADDRESS_P (XEXP(operands[0], 0)) && INTVAL (operands[1]) < 64) return \"callf %1,%0\"; /* this is much faster */ return \"calls %1,%0\"; }") ; gcc does not account for register mask/argc longword. Thus the number ; for the call = number bytes for args + 4 (define_insn "call_value" [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g")))] "" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 4)); if (GET_CODE(operands[1]) == MEM && CONSTANT_ADDRESS_P (XEXP(operands[1], 0)) && INTVAL (operands[2]) < 64) return \"callf %2,%1\"; /* this is much faster */ return \"calls %2,%1\"; }") (define_insn "return" [(return)] "" "ret") (define_insn "nop" [(const_int 0)] "" "nop") ; casesi this code extracted from the vax code. The instructions are ; very similar. Tahoe requires that the table be word aligned. GCC ; places the table immediately after, thus the alignment directive. (define_insn "casesi" [(set (pc) (if_then_else (le (minus:SI (match_operand:SI 0 "general_operand" "g") (match_operand:SI 1 "general_operand" "g")) (match_operand:SI 2 "general_operand" "g")) (plus:SI (sign_extend:SI (mem:HI (plus:SI (pc) (minus:SI (match_dup 0) (match_dup 1))))) (label_ref:SI (match_operand 3 "" ""))) (pc)))] "" "casel %0,%1,%2\;.align %@") (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "jbr %l0") ;; This is the list of all the non-standard insn patterns ; This is used to access the address of a byte. This is similar to ; movqi, but the second operand had to be "address_operand" type, so ; it had to be an unnamed one. (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:QI 1 "address_operand" "p"))] "" "* { if (push_operand (operands[0], SImode)) return \"pushab %a1\"; return \"movab %a1,%0\"; }") ; This is used to access the address of a word. This is similar to ; movhi, but the second operand had to be "address_operand" type, so ; it had to be an unnamed one. (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:HI 1 "address_operand" "p"))] "" "* { if (push_operand (operands[0], SImode)) return \"pushaw %a1\"; return \"movaw %a1,%0\"; }") ; This is used to access the address of a long. This is similar to ; movsi, but the second operand had to be "address_operand" type, so ; it had to be an unnamed one. (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:SI 1 "address_operand" "p"))] "" "* { if (push_operand (operands[0], SImode)) return \"pushal %a1\"; return \"moval %a1,%0\"; }") ; bit test longword instruction, same as vax (define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "g") (match_operand:SI 1 "general_operand" "g")))] "" "bitl %0,%1") ; bit test word instructions, same as vax (define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "g") (match_operand:HI 1 "general_operand" "g")))] "" "bitw %0,%1") ; bit test instructions, same as vax (define_insn "" [(set (cc0) (and:QI (match_operand:QI 0 "general_operand" "g") (match_operand:QI 1 "general_operand" "g")))] "" "bitb %0,%1") ; bne counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jneq %l0") ; beq counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jeql %l0") ; ble counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jleq %l0") ; bleu counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jlequ %l0") ; bge counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jgeq %l0") ; bgeu counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jgequ %l0") ; blt counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jlss %l0") ; bltu counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jlssu %l0") ; bgt counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jgtr %l0") ; bgtu counterpart. in case gcc reverses the conditional. (define_insn "" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "jgtru %l0") ; casesi alternate form as found in vax code. this form is to ; compensate for the table's offset being no distance (0 displacement) (define_insn "" [(set (pc) (if_then_else (le (match_operand:SI 0 "general_operand" "g") (match_operand:SI 1 "general_operand" "g")) (plus:SI (sign_extend:SI (mem:HI (plus:SI (pc) (minus:SI (match_dup 0) (const_int 0))))) (label_ref:SI (match_operand 3 "" ""))) (pc)))] "" "casel %0,$0,%1\;.align %@") ; casesi alternate form as found in vax code. another form to ; compensate for the table's offset being no distance (0 displacement) (define_insn "" [(set (pc) (if_then_else (le (match_operand:SI 0 "general_operand" "g") (match_operand:SI 1 "general_operand" "g")) (plus:SI (sign_extend:SI (mem:HI (plus:SI (pc) (match_dup 0)))) (label_ref:SI (match_operand 3 "" ""))) (pc)))] "" "casel %0,$0,%1 \;.align %@") (define_insn "" [(set (pc) (if_then_else (lt (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "" "aoblss %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (le (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "" "aobleq %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (pc) (label_ref (match_operand 2 "" "")))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "" "aoblss %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (gt (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (pc) (label_ref (match_operand 2 "" "")))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "" "aobleq %1,%0,%l2") ; bbs/bbc (define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "bbs %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "bbc %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) (const_int 0)) (pc) (label_ref (match_operand 2 "" ""))))] "" "bbc %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) (const_int 0)) (pc) (label_ref (match_operand 2 "" ""))))] "" "bbs %1,%0,%l2") ; if the shift count is a byte in a register we can use it as a long (define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:QI 1 "register_operand" "r")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "bbs %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:QI 1 "register_operand" "r")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "bbc %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:QI 1 "register_operand" "r")) (const_int 0)) (pc) (label_ref (match_operand 2 "" ""))))] "" "bbc %1,%0,%l2") (define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") (const_int 1) (match_operand:QI 1 "register_operand" "r")) (const_int 0)) (pc) (label_ref (match_operand 2 "" ""))))] "" "bbs %1,%0,%l2") ; special case for 1 << constant. We don't do these because they are slower ; than the bitl instruction ;(define_insn "" ; [(set (pc) ; (if_then_else ; (ne (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") ; (match_operand:SI 1 "immediate_operand" "i")) ; (const_int 0)) ; (label_ref (match_operand 2 "" "")) ; (pc)))] ; "GET_CODE (operands[1]) == CONST_INT ; && exact_log2 (INTVAL (operands[1])) >= 0" ; "* ;{ ; operands[1] ; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); ; return \"bbs %1,%0,%l2\"; ;}") ; ;(define_insn "" ; [(set (pc) ; (if_then_else ; (eq (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") ; (match_operand:SI 1 "immediate_operand" "i")) ; (const_int 0)) ; (label_ref (match_operand 2 "" "")) ; (pc)))] ; "GET_CODE (operands[1]) == CONST_INT ; && exact_log2 (INTVAL (operands[1])) >= 0" ; "* ;{ ; operands[1] ; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); ; return \"bbc %1,%0,%l2\"; ;}") ; ;(define_insn "" ; [(set (pc) ; (if_then_else ; (ne (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") ; (match_operand:SI 1 "immediate_operand" "i")) ; (const_int 0)) ; (pc) ; (label_ref (match_operand 2 "" ""))))] ; "GET_CODE (operands[1]) == CONST_INT ; && exact_log2 (INTVAL (operands[1])) >= 0" ; "* ;{ ; operands[1] ; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); ; return \"bbc %1,%0,%l2\"; ;}") ; ;(define_insn "" ; [(set (pc) ; (if_then_else ; (eq (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") ; (match_operand:SI 1 "immediate_operand" "i")) ; (const_int 0)) ; (pc) ; (label_ref (match_operand 2 "" ""))))] ; "GET_CODE (operands[1]) == CONST_INT ; && exact_log2 (INTVAL (operands[1])) >= 0" ; "* ;{ ; operands[1] ; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); ; return \"bbs %1,%0,%l2\"; ;}")