gcc-papermario/config/tahoe/tahoe.md
2020-09-20 21:06:00 -04:00

53 KiB

;; Machine description for GNU compiler, Tahoe version ;; Copyright (C) 1989, 1994, 1996, 1997 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=232-216, 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<y.

(define_insn "" [(set (cc0) (compare (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) (zero_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] "tahoe_cmp_check (insn, operands[0], 0)" "cmpw %0,%1")

(define_insn "" [(set (cc0) (compare (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) (match_operand:SI 1 "immediate_operand" "i")))] "tahoe_cmp_check(insn, operands[1], 65535)" "* { if (INTVAL (operands[1]) > 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=232-28, 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<y.

(define_insn "" [(set (cc0) (compare (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) (zero_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] "tahoe_cmp_check (insn, operands[0], 0)" "cmpb %0,%1")

(define_insn "" [(set (cc0) (compare (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) (match_operand:SI 1 "immediate_operand" "i")))] "tahoe_cmp_check(insn, operands[1], 255)" "* { if (INTVAL (operands[1]) > 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 "extensible_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 "extensible_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 "register_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 "register_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 "register_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 "register_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 "register_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 "register_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 "register_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 "register_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"; ;}")