public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* RTL to Simple Three instruction code
@ 2002-12-10 23:20 Aditya Kanade
  2002-12-10 23:29 ` Peter Barada
  2002-12-11  7:17 ` Diego Novillo
  0 siblings, 2 replies; 7+ messages in thread
From: Aditya Kanade @ 2002-12-10 23:20 UTC (permalink / raw)
  To: gcc

Hi,

I'm working on a project which involves performing some optimizations
and annotating three-address code. We've been looking for some suitable
framework which can give us IR (in three-instruction format). We studied
many compiler infrastructures like SUIF, trimaran, zephyr and so on.

We feel that we can use gcc keeping in mind long-term usability and
extensibility. So is there any way of generating simple three-instruction
code from RTL (or tree representation) of gcc? Or is there a way of
reading and writing the string representation of RTL so that we can decide
on our own IR? Any help and suggestions for a getting three-instruction
code or writting programs for doing so will be of very much help.

---
Aditya Kanade.
M.Tech. Student, CSE, IIT Bombay.

http://www.cse.iitb.ac.in/~aditya

I've learned to keep my mind as open as I can.
I'm trying to look in as many directions as I can,
to find as many doors as I can, and I'm not going to
stop until I open them all.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
  2002-12-10 23:20 RTL to Simple Three instruction code Aditya Kanade
@ 2002-12-10 23:29 ` Peter Barada
  2002-12-11  7:17 ` Diego Novillo
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Barada @ 2002-12-10 23:29 UTC (permalink / raw)
  To: aditya; +Cc: gcc


>I'm working on a project which involves performing some optimizations
>and annotating three-address code. We've been looking for some suitable
>framework which can give us IR (in three-instruction format). We studied
>many compiler infrastructures like SUIF, trimaran, zephyr and so on.
>
>We feel that we can use gcc keeping in mind long-term usability and
>extensibility. So is there any way of generating simple three-instruction
>code from RTL (or tree representation) of gcc? Or is there a way of
>reading and writing the string representation of RTL so that we can decide
>on our own IR? Any help and suggestions for a getting three-instruction
>code or writting programs for doing so will be of very much help.

I think it would be pretty easy to develop a GCC port to a three
address architecture(TAA) paper machine.  In fact its probabaly easier
to do that than any of the *real* chips that GCC has been ported to
since there are little to *none* of the restrictions that real chips
have(offset limitations, instruction/register scheduling, addressing
restrictions, etc).

Read the documentation on the interanls of GCC and you should be able
to put together a very simple set of target macros/functions to
generate "assembler" code for your specific TAA.  Since you are
planning on doing your own optimizations it shouldn't matter how
efficient the code is that the port generates for your paper TAA...
You could probably start with the VAX port since it is one of the more
general ports that gcc supports...

-- 
Peter Barada
peter@baradas.org

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
  2002-12-10 23:20 RTL to Simple Three instruction code Aditya Kanade
  2002-12-10 23:29 ` Peter Barada
@ 2002-12-11  7:17 ` Diego Novillo
  2002-12-11  7:59   ` Michael S. Zick
  1 sibling, 1 reply; 7+ messages in thread
From: Diego Novillo @ 2002-12-11  7:17 UTC (permalink / raw)
  To: Aditya Kanade; +Cc: gcc

On Wed, 11 Dec 2002, Aditya Kanade wrote:

> I'm working on a project which involves performing some optimizations
> and annotating three-address code. We've been looking for some suitable
> framework which can give us IR (in three-instruction format). We studied
> many compiler infrastructures like SUIF, trimaran, zephyr and so on.
> 
Take a look at GIMPLE and tree SSA.  GIMPLE is an IL that sits
between FE trees and RTL.  It's a 3-address format that we are
using to build a new high-level optimizer framework for GCC.

http://gcc.gnu.org/projects/tree-ssa/


Diego.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
  2002-12-11  7:17 ` Diego Novillo
@ 2002-12-11  7:59   ` Michael S. Zick
  2002-12-11  9:00     ` Diego Novillo
  0 siblings, 1 reply; 7+ messages in thread
From: Michael S. Zick @ 2002-12-11  7:59 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc

On Wednesday 11 December 2002 08:30 am, Diego Novillo wrote:
>
> Take a look at GIMPLE and tree SSA.  GIMPLE is an IL that sits
> between FE trees and RTL.  It's a 3-address format that we are
> using to build a new high-level optimizer framework for GCC.
>
> http://gcc.gnu.org/projects/tree-ssa/
>
GIMPLE ?? at that URL ?
SIMPLE is mentioned at that URL.
If one follows the documentation link...
Then checks the index for GIMPLE...
Then browses the source (tree_simple.h) one finds mentions 
of GIMPLE...

Perhaps it is time to patch that page of the 
"frequently updated documentation"?
Wasn't the new name adopted last summer?

Mike

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
  2002-12-11  7:59   ` Michael S. Zick
@ 2002-12-11  9:00     ` Diego Novillo
  0 siblings, 0 replies; 7+ messages in thread
From: Diego Novillo @ 2002-12-11  9:00 UTC (permalink / raw)
  To: Michael S. Zick; +Cc: gcc

On Wed, 11 Dec 2002, Michael S. Zick wrote:

> On Wednesday 11 December 2002 08:30 am, Diego Novillo wrote:
> >
> > Take a look at GIMPLE and tree SSA.  GIMPLE is an IL that sits
> > between FE trees and RTL.  It's a 3-address format that we are
> > using to build a new high-level optimizer framework for GCC.
> >
> > http://gcc.gnu.org/projects/tree-ssa/
> >
> GIMPLE ?? at that URL ?
> SIMPLE is mentioned at that URL.
>
Ah, yes.  GIMPLE is the new name we adopted after making several
changes to the original SIMPLE grammar.  Both ILs are very
similar, but we felt we couldn't keep calling it SIMPLE after the
changes we had made.

The page has not been updated.  I will update it today. A patch
to rename the sources will come in some time soon as well.


Diego.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
@ 2002-12-10 23:36 Chris Lattner
  2002-12-10 23:30 ` Chris Lattner
  0 siblings, 1 reply; 7+ messages in thread
From: Chris Lattner @ 2002-12-10 23:36 UTC (permalink / raw)
  To: Peter Barada; +Cc: aditya, gcc

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1043 bytes --]


>>I'm working on a project which involves performing some optimizations
>>and annotating three-address code. We've been looking for some suitable
>>framework which can give us IR (in three-instruction format). We studied
>>many compiler infrastructures like SUIF, trimaran, zephyr and so on.

> I think it would be pretty easy to develop a GCC port to a three
> address architecture(TAA) paper machine.  In fact its probabaly easier
> to do that than any of the *real* chips that GCC has been ported to
> since there are little to *none* of the restrictions that real chips
> have(offset limitations, instruction/register scheduling, addressing
> restrictions, etc).

Here's the machine description file I wrote for the GCC frontend used by
the LLVM compiler infrastructure (http://llvm.cs.uiuc.edu/).  It is a very
abstract description which is used to export an IR from GCC.  It was
derived from the sparc.md file, but stripped down and simplified
drastically...

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

[-- Attachment #2: Type: TEXT/PLAIN, Size: 49848 bytes --]

;;- Machine description for LLVM "chip" for GNU C compiler -*- lisp -*-
;;  Copyright (C) 2001 Free Software Foundation, Inc.
;;  Contributed by Chris Lattner (sabre@nondot.org)

;; 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.

;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.

\f
;; Compare instructions.
;; This controls RTL generation and register allocation.

;; Now the compare DEFINE_INSNs.

(define_insn "cmpqi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:QI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpqi %0, %1")

(define_insn "cmphi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:HI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmphi %0, %1")

(define_insn "cmpsi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:SI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpsi %0, %1")

(define_insn "cmpdi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:DI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpdi %0, %1")

(define_insn "cmppdi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:PDI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmppdi %0, %1")

(define_insn "cmpsf"
  [(set (reg:CC 100)
	(compare:CC (match_operand:SF 0 "nonmemory_nonsubreg_operand" "f")
		    (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "cmpsf %0, %1")

(define_insn "cmpdf"
  [(set (reg:CC 100)
	(compare:CC (match_operand:DF 0 "nonmemory_nonsubreg_operand" "e")
		    (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "cmpdf %0, %1")

\f

;; Define setcc instructions...

(define_insn "seq"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (eq:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sne"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ne:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (gt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgtu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (gtu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "slt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (lt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sltu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ltu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sge"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ge:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgeu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (geu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sle"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (le:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sleu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (leu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunordered"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unordered:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sordered"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ordered:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sungt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ungt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunlt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unlt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "suneq"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (uneq:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunge"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unge:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunle"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unle:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sltgt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ltgt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")





;; These control RTL generation for conditional jump insns

(define_expand "beq"
  [(set (pc)
	(if_then_else (eq (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bne"
  [(set (pc)
	(if_then_else (ne (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgt"
  [(set (pc)
	(if_then_else (gt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgtu"
  [(set (pc)
	(if_then_else (gtu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "blt"
  [(set (pc)
	(if_then_else (lt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bltu"
  [(set (pc)
	(if_then_else (ltu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bge"
  [(set (pc)
	(if_then_else (ge (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgeu"
  [(set (pc)
	(if_then_else (geu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "ble"
  [(set (pc)
	(if_then_else (le (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bleu"
  [(set (pc)
	(if_then_else (leu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunordered"
  [(set (pc)
	(if_then_else (unordered (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bordered"
  [(set (pc)
	(if_then_else (ordered (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bungt"
  [(set (pc)
	(if_then_else (ungt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunlt"
  [(set (pc)
	(if_then_else (unlt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "buneq"
  [(set (pc)
	(if_then_else (uneq (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunge"
  [(set (pc)
	(if_then_else (unge (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunle"
  [(set (pc)
	(if_then_else (unle (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bltgt"
  [(set (pc)
	(if_then_else (ltgt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")
\f
;; Now match both normal and inverted jump.

(define_insn "*normal_branch"
  [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
                                      [(reg 100) (const_int 0)])
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
  ""
  "br %0 to %1
")

(define_insn "*inverted_branch"
  [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
                                      [(reg 100) (const_int 0)])
                      (pc)
                      (label_ref (match_operand 1 "" ""))))]
  ""
  "br %0 to %1 (inverted!)
")

\f
;; Load program counter insns.

;;(define_insn "get_pc"
;;  [(clobber (reg:SI 15))
;;   (set (match_operand 0 "register_operand" "=r")
;;	(unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
;;  "flag_pic && REGNO (operands[0]) == 23"
;;  "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0")

\f
;; Move instructions

(define_expand "movqi"
  [(set (match_operand:QI 0 "general_operand" "=rm")
	(match_operand:QI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, QImode)
      && !register_operand (operand1, QImode))
    operands[1] = copy_to_mode_reg (QImode, operand1);
}")

(define_insn "*movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
	(match_operand:QI 1 "input_operand"        "rim"))]
  ""
  "movqi %1 -> %0")


(define_expand "movhi"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(match_operand:HI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, HImode)
      && !register_operand (operand1, HImode))
    operands[1] = copy_to_mode_reg (HImode, operand1);
}")

;;[(set (match_operand:HI 0 "nonimmediate_operand" "=r,f,r,f,m,m")
;;	(match_operand:HI 1 "input_operand"        "ri,!f,m,!m,r,!f"))]
;;

(define_insn "*movhi"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
	(match_operand:HI 1 "input_operand"        "rim"))]
  ""
  "movhi %1 -> %0")


(define_expand "movsi"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(match_operand:SI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, SImode)
      && !register_operand (operand1, SImode))
    operands[1] = copy_to_mode_reg (SImode, operand1);
}")

(define_insn "*movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
	(match_operand:SI 1 "input_operand"        "rim"))]
  ""
  "movsi %1 -> %0")


(define_expand "movdi"
  [(set (match_operand:DI 0 "general_operand" "=rm")
	(match_operand:DI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, DImode)
      && !register_operand (operand1, DImode))
    operands[1] = copy_to_mode_reg (DImode, operand1);
}")

(define_insn "*movdi"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
	(match_operand:DI 1 "input_operand"        "rim"))]
  ""
  "movdi %1 -> %0")

(define_expand "movpdi"
  [(set (match_operand:PDI 0 "general_operand" "=rm")
	(match_operand:PDI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, PDImode)
      && !register_operand (operand1, PDImode))
    operands[1] = copy_to_mode_reg (PDImode, operand1);
}")

(define_insn "*movpdi"
  [(set (match_operand:PDI 0 "nonimmediate_operand" "=rm")
	(match_operand:PDI 1 "input_operand"        "rim"))]
  ""
  "movpdi %1 -> %0")


;; mov_to_ret, mov_from_ret - These instructions are used to set the return
;; register for a function, or to read the value returned by a function.
;;
(define_insn "*mov_to_ret"
  [(set (reg 101) (match_operand 0 "input_operand" ""))]
  ""
  "movi %0 -> %%ret")

(define_insn "*mov_from_ret"
  [(set (match_operand 0 "register_operand" "")	(reg 101))]
  ""
  "movi %%ret -> %0")




\f
;; Floating point move insns

(define_expand "movsf"
  [(set (match_operand:SF 0 "general_operand" "")
	(match_operand:SF 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, SFmode)
      && !register_operand (operand1, SFmode))
    operands[1] = copy_to_mode_reg (SFmode, operand1);
}")

(define_insn "*movsf"
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
	(match_operand:SF 1 "input_operand"         ""))]
  ""
  "movsf %1 -> %0")

(define_expand "movdf"
  [(set (match_operand:DF 0 "general_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, DFmode)
      && !register_operand (operand1, DFmode))
    operands[1] = copy_to_mode_reg (DFmode, operand1);
}")

(define_insn "*movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (match_operand:DF 1 "input_operand"    ""))]
  ""
  "movdf %1 -> %0")

\f
;;- zero extension instructions

(define_insn "zero_extendqihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(zero_extend:HI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqihi2 %1 -> %0")

(define_insn "zero_extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extend:SI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqisi2 %1 -> %0")

(define_insn "zero_extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extend:SI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendhisi2 %1 -> %0")

(define_insn "zero_extendqidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqidi2 %1 -> %0")

(define_insn "zero_extendhidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendhidi2 %1 -> %0")

(define_insn "zero_extendsidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendsidi2 %1 -> %0")


\f
;;- sign extension instructions

(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendhisi2 %1 -> %0")

(define_insn "extendqihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(sign_extend:HI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqihi2 %1 -> %0")

(define_insn "extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqisi2 %1 -> %0")

(define_insn "extendqidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqidi2 %1 -> %0")

(define_insn "extendhidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendhidi2 %1 -> %0")

(define_insn "extendsidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendsidi2 %1 -> %0")

(define_insn "extendpdidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendpdidi2 %1 -> %0")



(define_insn "truncdipdi2"
  [(set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncdipdi2 %1 -> %0")

(define_insn "truncdisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncdisi2 %1 -> %0")

(define_insn "truncsihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
        (truncate:HI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncsihi2 %1 -> %0")

(define_insn "trunchiqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "trunchiqi2 %1 -> %0")

(define_insn "truncsiqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncsiqi2 %1 -> %0")



\f

;; Conversions between float, double and long double.

(define_insn "extendsfdf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float_extend:DF
	 (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "extendsfdf2 %1 -> %0")

(define_insn "truncdfsf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float_truncate:SF
	 (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "truncdfsf2 %1 -> %0")



\f
;; Conversion between fixed point and floating point.

(define_insn "floatsisf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float:SF (match_operand:SI 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fitos\\t%1, %0")

(define_insn "floatsidf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float:DF (match_operand:SI 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fitod\\t%1, %0")

;; Now the same for 64 bit sources.

(define_insn "floatdisf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float:SF (match_operand:DI 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fxtos\\t%1, %0")

(define_insn "floatdidf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float:DF (match_operand:DI 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fxtod\\t%1, %0")



;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.

(define_insn "fix_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(fix:SI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fix_truncsfsi2 %1, %0")

(define_insn "fix_truncdfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(fix:SI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fix_truncdfsi2 %1, %0")

(define_insn "fix_truncsfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(fix:DI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fix_truncsfdi2 %1, %0")

(define_insn "fix_truncdfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(fix:DI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fix_truncdfdi2 %1, %0")


(define_insn "fixuns_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(unsigned_fix:SI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fixuns_truncsfsi2 %1, %0")

(define_insn "fixuns_truncdfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(unsigned_fix:SI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fixuns_truncdfsi2 %1, %0")

(define_insn "fixuns_truncsfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(unsigned_fix:DI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fixuns_truncsfdi2 %1, %0")

(define_insn "fixuns_truncdfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(unsigned_fix:DI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fixuns_truncdfdi2 %1, %0")


\f
;;- arithmetic instructions

(define_insn "adddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(plus:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "adddi3 %1, %2 -> %0")

(define_insn "addsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addsi3 %1, %2 -> %0")

(define_insn "addpdi3"
  [(set (match_operand:PDI 0 "register_operand" "=r")
	(plus:PDI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addpdi3 %1, %2 -> %0")

(define_insn "addhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(plus:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addhi3 %1, %2 -> %0")

(define_insn "addqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(plus:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addqi3 %1, %2 -> %0")

(define_insn "adddf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(plus:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		 (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "adddf3 %1, %2 -> %0")

(define_insn "addsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(plus:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		 (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "addsf3 %1, %2 -> %0")


;; Subtraction instructions

(define_insn "subdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(minus:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subdi %1, %2, %0")

(define_insn "subsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subsi %1, %2, %0")

(define_insn "subhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(minus:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subhi %1, %2, %0")

(define_insn "subqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(minus:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subqi %1, %2, %0")


(define_expand "subpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 5)
         (minus:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")


(define_insn "subdf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(minus:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		  (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "subdf3 %1, %2 -> %0")

(define_insn "subsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(minus:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		  (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "subsf3 %1, %2 -> %0")

\f
;; Integer Multiply/Divide.

(define_insn "mulqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(mult:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulqi3\\t%1, %2 -> %0")

(define_insn "mulhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(mult:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulhi3 %1, %2 -> %0")

(define_insn "mulsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mult:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulsi3 %1, %2 -> %0")

(define_insn "muldi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(mult:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "muldi3 %1, %2 -> %0")

(define_expand "mulpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 5)
         (mult:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")



(define_insn "muldf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(mult:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		 (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "muldf3 %1, %2 -> %0")

(define_insn "mulsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(mult:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		 (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "mulsf3 %1, %2 -> %0")

;; Division instructions

(define_insn "divqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(div:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divqi3 %1, %2 -> %0")

(define_insn "divhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(div:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divhi3 %1, %2 -> %0")

(define_insn "divsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(div:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divsi3 %1, %2 -> %0")

(define_insn "divdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(div:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divdi3 %1, %2 -> %0")

(define_insn "divsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(div:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divsf3 %1, %2 -> %0")

(define_insn "divdf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(div:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divdf3 %1, %2 -> %0")


;; Unsigned Division
(define_insn "udivqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(udiv:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivqi3 %1, %2 -> %0")

(define_insn "udivhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(udiv:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivhi3 %1, %2 -> %0")

(define_insn "udivsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(udiv:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivsi3 %1, %2 -> %0")

(define_insn "udivdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(udiv:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivdi3 %1, %2, %0")

(define_expand "udivpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 5)
        (udiv:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")



;; Modulus instructions

(define_insn "modqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(mod:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modqi3 %1, %2 -> %0")


(define_insn "modhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(mod:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modhi3 %1, %2 -> %0")


(define_insn "modsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mod:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modsi3 %1, %2 -> %0")


(define_insn "moddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(mod:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "moddi3 %1, %2 -> %0")

(define_insn "modsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(mod:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modsf3 %1, %2 -> %0")

(define_insn "moddf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(mod:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "moddf3 %1, %2 -> %0")


;; Unsigned Modulus
(define_insn "umodqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(umod:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodqi3 %1, %2 -> %0")

(define_insn "umodhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(umod:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodhi3 %1, %2 -> %0")

(define_insn "umodsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(umod:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodsi3 %1, %2 -> %0")

(define_insn "umoddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(umod:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umoddi3 %1, %2, %0")

;; LLVM doesn't have a NEG instruction, but it does have a SUB instruction.  Use
;; it instead.
;;

(define_expand "negpdi3"
  [(set (match_dup 2)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 3)
         (minus:DI (const_int 0) (match_dup 2)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 3)))]
  ""
  "
{
  operands[2] = gen_reg_rtx(DImode);
  operands[3] = gen_reg_rtx(DImode);
}")

(define_insn "negdi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(minus:DI (const_int 0)
                  (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (const_int 0)
                  (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "neghi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(minus:HI (const_int 0)
                  (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(minus:QI (const_int 0)
                  (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negdf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(minus:DF (const_int 0)
                  (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "")

(define_insn "negsf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(minus:SF (const_int 0)
                  (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "")


;;- Boolean instructions

(define_insn "anddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(and:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "anddi3 %1, %2, %0")

(define_insn "andsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andsi3 %1, %2, %0")

(define_insn "andhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(and:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andhi3 %1, %2, %0")

(define_insn "andqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(and:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andqi3 %1, %2, %0")



(define_insn "iordi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ior:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iordi3 %1, %2, %0")

(define_insn "iorsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorsi3 %1, %2, %0")

(define_insn "iorhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ior:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorhi3 %1, %2, %0")

(define_insn "iorqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ior:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorqi3 %1, %2, %0")


(define_insn "xordi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(xor:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xordi3 %1, %2, %0")

(define_insn "xorsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorsi3 %1, %2, %0")

(define_insn "xorhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(xor:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorhi3 %1, %2, %0")

(define_insn "xorqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(xor:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorqi3 %1, %2, %0")

;; LLVM doesn't have a NOT instruction, but it does have a XOR instruction.  Use
;; it instead.
;;
(define_expand "one_cmpldi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(xor:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplhi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(xor:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(xor:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")




;;- arithmetic shift instructions

(define_insn "ashlqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ashift:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlqi3 %1, %2 -> %0")

(define_insn "ashlhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ashift:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlhi3 %1, %2 -> %0")

(define_insn "ashlsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashift:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlsi3 %1, %2 -> %0")

(define_insn "ashldi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashift:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashldi3 %1, %2 -> %0")

(define_expand "ashlpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (ashift:DI (match_dup 3) 
                    (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")



;; ashr

(define_insn "ashrqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ashiftrt:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrqi3 %1, %2 -> %0")

(define_insn "ashrhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ashiftrt:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrhi3 %1, %2 -> %0")

(define_insn "ashrsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrsi3 %1, %2 -> %0")

(define_insn "ashrdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashiftrt:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrdi3 %1, %2 -> %0")

(define_expand "ashrpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (ashiftrt:DI (match_dup 3) 
                      (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")


(define_insn "lshrqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(lshiftrt:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrqi3 %1, %2 -> %0")

(define_insn "lshrhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(lshiftrt:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrhi3 %1, %2 -> %0")

(define_insn "lshrsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lshiftrt:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrsi3 %1, %2 -> %0")

(define_insn "lshrdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(lshiftrt:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrdi3 %1, %2 -> %0")

(define_expand "lshrpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (lshiftrt:DI (match_dup 3) 
                      (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")



\f
;; Unconditional and other jump instructions
;; On the Sparc, by setting the annul bit on an unconditional branch, the
;; following insn is never executed.  This saves us a nop.  Dbx does not
;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
  [(set (pc) (label_ref (match_operand 0 "" "")))]
  ""
  "*
{
  /* TurboSparc is reported to have problems with
     with
	foo: b,a foo
     i.e. an empty loop with the annul bit set.  The workaround is to use 
        foo: b foo; nop
     instead.  */

  return \"ba,pt%*\\t%%xcc, %l0%(\";
}")

;(define_expand "tablejump"
;  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
;	      (use (label_ref (match_operand 1 "" "")))])]
;  ""
;  "
;{
;  if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
;    abort ();
;}")

;(define_insn "*tablejump_sp"
;  [(set (pc) (match_operand:DI 0 "address_operand" "p"))
;   (use (label_ref (match_operand 1 "" "")))]
;  ""
;  "br %a0%#")

;;- jump to subroutine
(define_expand "call"
  ;; Note that this expression is not used for generating RTL.
  ;; All the RTL is generated explicitly below.
  [(call (match_operand 0 "call_operand" "")
	 (match_operand 3 "" "i"))]
  ;; operands[2] is next_arg_register
  ;; operands[3] is struct_value_size_rtx.
  ""
  "
{ emit_call_insn(gen_rtx_CALL(VOIDmode, operands[0], const0_rtx));
  DONE;
}")

;; We can't use the same pattern for these two insns, because then registers
;; in the address may not be properly reloaded.

(define_insn "*call_address_sp64"
  [(call (mem:PDI (match_operand:PDI 0 "address_operand" "p"))
	 (match_operand 1 "" ""))]
  ;;- Do not use operand 1 for most machines.
  ""
  "call %a0, %1%#")

(define_insn "*call_symbolic"
  [(call (mem:PDI (match_operand:PDI 0 "symbolic_operand" "s"))
	 (match_operand 1 "" ""))]
  ;;- Do not use operand 1 for most machines.
  ""
  "call %a0, %1%#")

(define_expand "call_value"
  ;; Note that this expression is not used for generating RTL.
  ;; All the RTL is generated explicitly below.
  [(set (match_operand 0 "nonmemory_nonsubreg_operand" "=rf")
	(call (match_operand 1 "" "")
	      (match_operand 4 "" "")))]
  ;; operand 2 is stack_size_rtx
  ;; operand 3 is next_arg_register
  ""
  "
{
  if (GET_MODE (operands[1]) != FUNCTION_MODE)
    abort ();
  emit_call_insn(gen_rtx_SET (VOIDmode, operands[0],
                              gen_rtx_CALL (VOIDmode, operands[1], const0_rtx)));
  DONE;
}")

(define_insn "*call_value_address"
  [(set (match_operand 0 "" "")
	(call (mem:PDI (match_operand:PDI 1 "address_operand" "p"))
	      (match_operand 2 "" "")))]
  ;;- Do not use operand 2 for most machines.
  ""
  "call\\t%a1, %2%#")

(define_insn "*call_value_symbolic"
  [(set (match_operand 0 "" "")
	(call (mem:PDI (match_operand:PDI 1 "symbolic_operand" "s"))
	      (match_operand 2 "" "")))]
  ;;- Do not use operand 2 for most machines.
  ""
  "call\\t%a1, %2%#")

(define_expand "untyped_call"
  [(parallel [(call (match_operand 0 "" "")
		    (const_int 0))
	      (match_operand 1 "" "")
	      (match_operand 2 "" "")])]
  ""
  "
{
  int i;

  /* Pass constm1 to indicate that it may expect a structure value, but
     we don't know what size it is.  */
  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));

  for (i = 0; i < XVECLEN (operands[2], 0); i++)
    {
      rtx set = XVECEXP (operands[2], 0, i);
      emit_move_insn (SET_DEST (set), SET_SRC (set));
    }

  DONE;
}")


;; Prepare to return any type including a structure value.

(define_expand "untyped_return"
  [(match_operand:BLK 0 "memory_operand" "")
   (match_operand 1 "" "")]
  ""
  "
{
  rtx valreg1 = gen_rtx_REG (DImode, 24);
  rtx valreg2 = gen_rtx_REG (DFmode, 32);
  rtx result = operands[0];

  /* Reload the function value registers.  */
  emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
  emit_move_insn (valreg2,
		  change_address (result, DFmode,
				  plus_constant (XEXP (result, 0), 8)));

  /* Put USE insns before the return.  */
  emit_insn (gen_rtx_USE (VOIDmode, valreg1));
  emit_insn (gen_rtx_USE (VOIDmode, valreg2));

  /* Construct the return.  */
  expand_null_return ();

  DONE;
}")

\f

(define_insn "nop"
  [(const_int 0)]
  ""
  "nop")

(define_expand "indirect_jump"
  [(set (pc) (match_operand 0 "address_operand" "p"))]
  ""
  "")

(define_insn "*branch_sp64"
  [(set (pc) (match_operand:PDI 0 "address_operand" "p"))]
  ""
  "br %a0%#
")

(define_expand "nonlocal_goto"
  [(match_operand:SI 0 "general_operand" "")
   (match_operand:SI 1 "general_operand" "")
   (match_operand:SI 2 "general_operand" "")
   (match_operand:SI 3 "" "")]
  ""
  "
{
  rtx fp = operands[1];
  rtx stack = operands[2];
  rtx lab = operands[3];
  rtx labreg;

  /* Load the fp value for the containing fn into %fp.  This is needed
     because STACK refers to %fp.  Note that virtual register instantiation
     fails if the virtual %fp isn't set from a register.  */
  if (GET_CODE (fp) != REG)
    fp = force_reg (Pmode, fp);
  emit_move_insn (virtual_stack_vars_rtx, fp);

  /* Find the containing function's current nonlocal goto handler,
     which will do any cleanups and then jump to the label.  */
  labreg = gen_rtx_REG (Pmode, 8);
  emit_move_insn (labreg, lab);

  /* Restore %fp from stack pointer value for containing function.
     The restore insn that follows will move this to %sp,
     and reload the appropriate value into %fp.  */
  emit_move_insn (frame_pointer_rtx, stack);

  /* USE of frame_pointer_rtx added for consistency; not clear if
     really needed.  */
  /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));

  emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
  emit_jump_insn (gen_goto_handler_and_restore (labreg));
  emit_barrier ();
  DONE;
}")

(define_insn "goto_handler_and_restore"
  [(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
  "GET_MODE (operands[0]) == Pmode"
  "jmp\\t%0+0\\n\\trestore")


;;; Special allocate_stack definition.  This causes alloca instructions to be
;;; turned into calls to __llvm_builtin_alloca, which is recognized by the LLVM
;;; backend, and turned into alloca instructions.
;;;
(define_expand "allocate_stack"
  [(match_operand:PDI 0 "register_operand" "=r")
   (match_operand:PDI 1 "register_operand" "")]
   ""
   "
{
  rtx Dest = operands[0], Amount = operands[1];
  emit_library_call_value(gen_rtx(SYMBOL_REF, Pmode, 
                          \"__llvm_builtin_alloca\"), Dest,
                          /*Pure fn call */ 2, PDImode, 1, Amount, DImode);
  DONE;
}")




;;(define_insn "*goto_handler_and_restore_v9_sp64"
;;  [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
;;		     (match_operand:DI 1 "register_operand" "=r,r")
;;		     (match_operand:SI 2 "const_int_operand" "n,n")] 3)]
;;  ""
;;  "@
;;   return\\t%0+0\\n\\tmov\\t%2, %Y1
;;   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1")

;; For __builtin_setjmp we need to flush register windows iff the function
;; calls alloca as well, because otherwise the register window might be
;; saved after %sp adjustement and thus setjmp would crash
(define_expand "builtin_setjmp_setup"
  [(match_operand 0 "register_operand" "r")]
  ""
  "
{
  emit_insn (gen_do_builtin_setjmp_setup ());
  DONE;
}")

(define_insn "do_builtin_setjmp_setup"
  [(unspec_volatile [(const_int 0)] 5)]
  ""
  "*
{
  if (!current_function_calls_alloca)
    return \"\";
  return \"flushw\";
}")

;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.

(define_expand "setjmp"
  [(const_int 0)]
  ""
  "
{
  emit_insn (gen_setjmp_64 ());
  DONE;
}")

(define_expand "setjmp_32"
  [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
   (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
  ""
  "
{ operands[0] = frame_pointer_rtx; }")

(define_expand "setjmp_64"
  [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
   (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
  ""
  "
{ operands[0] = frame_pointer_rtx; }")

\f

;;;; We need to reload %l7 for -mflat -fpic,
;;;; otherwise %l7 should be preserved simply
;;;; by loading the function's register window
;;(define_expand "exception_receiver"
;;  [(const_int 0)]
;;  "flag_pic"
;;  "
;;{
;;  load_pic_register ();
;;  DONE;
;;}")

;;;; Likewise
;;(define_expand "builtin_setjmp_receiver"
;;  [(label_ref (match_operand 0 "" ""))]
;;  "flag_pic"
;;  "
;;{
;;  load_pic_register ();
;;  DONE;
;;}")
\f
(define_insn "trap"
  [(trap_if (const_int 1) (const_int 5))]
  ""
  "ta\\t5")

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RTL to Simple Three instruction code
  2002-12-10 23:36 Chris Lattner
@ 2002-12-10 23:30 ` Chris Lattner
  0 siblings, 0 replies; 7+ messages in thread
From: Chris Lattner @ 2002-12-10 23:30 UTC (permalink / raw)
  To: aditya; +Cc: gcc

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1043 bytes --]


>>I'm working on a project which involves performing some optimizations
>>and annotating three-address code. We've been looking for some suitable
>>framework which can give us IR (in three-instruction format). We studied
>>many compiler infrastructures like SUIF, trimaran, zephyr and so on.

> I think it would be pretty easy to develop a GCC port to a three
> address architecture(TAA) paper machine.  In fact its probabaly easier
> to do that than any of the *real* chips that GCC has been ported to
> since there are little to *none* of the restrictions that real chips
> have(offset limitations, instruction/register scheduling, addressing
> restrictions, etc).

Here's the machine description file I wrote for the GCC frontend used by
the LLVM compiler infrastructure (http://llvm.cs.uiuc.edu/).  It is a very
abstract description which is used to export an IR from GCC.  It was
derived from the sparc.md file, but stripped down and simplified
drastically...

-Chris

-- 
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/

[-- Attachment #2: Type: TEXT/PLAIN, Size: 49848 bytes --]

;;- Machine description for LLVM "chip" for GNU C compiler -*- lisp -*-
;;  Copyright (C) 2001 Free Software Foundation, Inc.
;;  Contributed by Chris Lattner (sabre@nondot.org)

;; 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.

;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.

\f
;; Compare instructions.
;; This controls RTL generation and register allocation.

;; Now the compare DEFINE_INSNs.

(define_insn "cmpqi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:QI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpqi %0, %1")

(define_insn "cmphi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:HI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmphi %0, %1")

(define_insn "cmpsi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:SI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpsi %0, %1")

(define_insn "cmpdi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:DI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmpdi %0, %1")

(define_insn "cmppdi"
  [(set (reg:CC 100)
	(compare:CC (match_operand:PDI 0 "nonmemory_nonsubreg_operand" "")
		    (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "cmppdi %0, %1")

(define_insn "cmpsf"
  [(set (reg:CC 100)
	(compare:CC (match_operand:SF 0 "nonmemory_nonsubreg_operand" "f")
		    (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "cmpsf %0, %1")

(define_insn "cmpdf"
  [(set (reg:CC 100)
	(compare:CC (match_operand:DF 0 "nonmemory_nonsubreg_operand" "e")
		    (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "cmpdf %0, %1")

\f

;; Define setcc instructions...

(define_insn "seq"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (eq:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sne"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ne:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (gt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgtu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (gtu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "slt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (lt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sltu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ltu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sge"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ge:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sgeu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (geu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sle"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (le:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sleu"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (leu:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunordered"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unordered:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sordered"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ordered:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sungt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ungt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunlt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unlt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "suneq"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (uneq:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunge"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unge:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sunle"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (unle:QI (reg:CC 100) (const_int 0)))]
  ""
  "")
(define_insn "sltgt"
  [(set (match_operand:QI 0 "nonmemory_nonsubreg_operand" "=r")
        (ltgt:QI (reg:CC 100) (const_int 0)))]
  ""
  "")





;; These control RTL generation for conditional jump insns

(define_expand "beq"
  [(set (pc)
	(if_then_else (eq (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bne"
  [(set (pc)
	(if_then_else (ne (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgt"
  [(set (pc)
	(if_then_else (gt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgtu"
  [(set (pc)
	(if_then_else (gtu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "blt"
  [(set (pc)
	(if_then_else (lt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bltu"
  [(set (pc)
	(if_then_else (ltu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bge"
  [(set (pc)
	(if_then_else (ge (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bgeu"
  [(set (pc)
	(if_then_else (geu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "ble"
  [(set (pc)
	(if_then_else (le (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bleu"
  [(set (pc)
	(if_then_else (leu (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunordered"
  [(set (pc)
	(if_then_else (unordered (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bordered"
  [(set (pc)
	(if_then_else (ordered (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bungt"
  [(set (pc)
	(if_then_else (ungt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunlt"
  [(set (pc)
	(if_then_else (unlt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "buneq"
  [(set (pc)
	(if_then_else (uneq (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunge"
  [(set (pc)
	(if_then_else (unge (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bunle"
  [(set (pc)
	(if_then_else (unle (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")

(define_expand "bltgt"
  [(set (pc)
	(if_then_else (ltgt (reg:CC 100) (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "")
\f
;; Now match both normal and inverted jump.

(define_insn "*normal_branch"
  [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
                                      [(reg 100) (const_int 0)])
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
  ""
  "br %0 to %1
")

(define_insn "*inverted_branch"
  [(set (pc)
        (if_then_else (match_operator 0 "v9_regcmp_op"
                                      [(reg 100) (const_int 0)])
                      (pc)
                      (label_ref (match_operand 1 "" ""))))]
  ""
  "br %0 to %1 (inverted!)
")

\f
;; Load program counter insns.

;;(define_insn "get_pc"
;;  [(clobber (reg:SI 15))
;;   (set (match_operand 0 "register_operand" "=r")
;;	(unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
;;  "flag_pic && REGNO (operands[0]) == 23"
;;  "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0")

\f
;; Move instructions

(define_expand "movqi"
  [(set (match_operand:QI 0 "general_operand" "=rm")
	(match_operand:QI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, QImode)
      && !register_operand (operand1, QImode))
    operands[1] = copy_to_mode_reg (QImode, operand1);
}")

(define_insn "*movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
	(match_operand:QI 1 "input_operand"        "rim"))]
  ""
  "movqi %1 -> %0")


(define_expand "movhi"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(match_operand:HI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, HImode)
      && !register_operand (operand1, HImode))
    operands[1] = copy_to_mode_reg (HImode, operand1);
}")

;;[(set (match_operand:HI 0 "nonimmediate_operand" "=r,f,r,f,m,m")
;;	(match_operand:HI 1 "input_operand"        "ri,!f,m,!m,r,!f"))]
;;

(define_insn "*movhi"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
	(match_operand:HI 1 "input_operand"        "rim"))]
  ""
  "movhi %1 -> %0")


(define_expand "movsi"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(match_operand:SI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, SImode)
      && !register_operand (operand1, SImode))
    operands[1] = copy_to_mode_reg (SImode, operand1);
}")

(define_insn "*movsi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
	(match_operand:SI 1 "input_operand"        "rim"))]
  ""
  "movsi %1 -> %0")


(define_expand "movdi"
  [(set (match_operand:DI 0 "general_operand" "=rm")
	(match_operand:DI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, DImode)
      && !register_operand (operand1, DImode))
    operands[1] = copy_to_mode_reg (DImode, operand1);
}")

(define_insn "*movdi"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
	(match_operand:DI 1 "input_operand"        "rim"))]
  ""
  "movdi %1 -> %0")

(define_expand "movpdi"
  [(set (match_operand:PDI 0 "general_operand" "=rm")
	(match_operand:PDI 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, PDImode)
      && !register_operand (operand1, PDImode))
    operands[1] = copy_to_mode_reg (PDImode, operand1);
}")

(define_insn "*movpdi"
  [(set (match_operand:PDI 0 "nonimmediate_operand" "=rm")
	(match_operand:PDI 1 "input_operand"        "rim"))]
  ""
  "movpdi %1 -> %0")


;; mov_to_ret, mov_from_ret - These instructions are used to set the return
;; register for a function, or to read the value returned by a function.
;;
(define_insn "*mov_to_ret"
  [(set (reg 101) (match_operand 0 "input_operand" ""))]
  ""
  "movi %0 -> %%ret")

(define_insn "*mov_from_ret"
  [(set (match_operand 0 "register_operand" "")	(reg 101))]
  ""
  "movi %%ret -> %0")




\f
;; Floating point move insns

(define_expand "movsf"
  [(set (match_operand:SF 0 "general_operand" "")
	(match_operand:SF 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, SFmode)
      && !register_operand (operand1, SFmode))
    operands[1] = copy_to_mode_reg (SFmode, operand1);
}")

(define_insn "*movsf"
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
	(match_operand:SF 1 "input_operand"         ""))]
  ""
  "movsf %1 -> %0")

(define_expand "movdf"
  [(set (match_operand:DF 0 "general_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  ""
  "
{ /* One of the ops has to be in a register */
  if (!register_operand (operand0, DFmode)
      && !register_operand (operand1, DFmode))
    operands[1] = copy_to_mode_reg (DFmode, operand1);
}")

(define_insn "*movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (match_operand:DF 1 "input_operand"    ""))]
  ""
  "movdf %1 -> %0")

\f
;;- zero extension instructions

(define_insn "zero_extendqihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(zero_extend:HI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqihi2 %1 -> %0")

(define_insn "zero_extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extend:SI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqisi2 %1 -> %0")

(define_insn "zero_extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extend:SI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendhisi2 %1 -> %0")

(define_insn "zero_extendqidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendqidi2 %1 -> %0")

(define_insn "zero_extendhidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendhidi2 %1 -> %0")

(define_insn "zero_extendsidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(zero_extend:DI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "zero_extendsidi2 %1 -> %0")


\f
;;- sign extension instructions

(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendhisi2 %1 -> %0")

(define_insn "extendqihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(sign_extend:HI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqihi2 %1 -> %0")

(define_insn "extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqisi2 %1 -> %0")

(define_insn "extendqidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendqidi2 %1 -> %0")

(define_insn "extendhidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendhidi2 %1 -> %0")

(define_insn "extendsidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(sign_extend:DI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendsidi2 %1 -> %0")

(define_insn "extendpdidi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "extendpdidi2 %1 -> %0")



(define_insn "truncdipdi2"
  [(set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncdipdi2 %1 -> %0")

(define_insn "truncdisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (truncate:SI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncdisi2 %1 -> %0")

(define_insn "truncsihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
        (truncate:HI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncsihi2 %1 -> %0")

(define_insn "trunchiqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "trunchiqi2 %1 -> %0")

(define_insn "truncsiqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (truncate:QI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
   ""
   "truncsiqi2 %1 -> %0")



\f

;; Conversions between float, double and long double.

(define_insn "extendsfdf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float_extend:DF
	 (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "extendsfdf2 %1 -> %0")

(define_insn "truncdfsf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float_truncate:SF
	 (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "truncdfsf2 %1 -> %0")



\f
;; Conversion between fixed point and floating point.

(define_insn "floatsisf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float:SF (match_operand:SI 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fitos\\t%1, %0")

(define_insn "floatsidf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float:DF (match_operand:SI 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fitod\\t%1, %0")

;; Now the same for 64 bit sources.

(define_insn "floatdisf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(float:SF (match_operand:DI 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fxtos\\t%1, %0")

(define_insn "floatdidf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(float:DF (match_operand:DI 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fxtod\\t%1, %0")



;; Convert a float to an actual integer.
;; Truncation is performed as part of the conversion.

(define_insn "fix_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(fix:SI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fix_truncsfsi2 %1, %0")

(define_insn "fix_truncdfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(fix:SI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fix_truncdfsi2 %1, %0")

(define_insn "fix_truncsfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(fix:DI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fix_truncsfdi2 %1, %0")

(define_insn "fix_truncdfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(fix:DI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fix_truncdfdi2 %1, %0")


(define_insn "fixuns_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(unsigned_fix:SI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fixuns_truncsfsi2 %1, %0")

(define_insn "fixuns_truncdfsi2"
  [(set (match_operand:SI 0 "register_operand" "=f")
	(unsigned_fix:SI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fixuns_truncdfsi2 %1, %0")

(define_insn "fixuns_truncsfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(unsigned_fix:DI (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "fixuns_truncsfdi2 %1, %0")

(define_insn "fixuns_truncdfdi2"
  [(set (match_operand:DI 0 "register_operand" "=e")
	(unsigned_fix:DI (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "fixuns_truncdfdi2 %1, %0")


\f
;;- arithmetic instructions

(define_insn "adddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(plus:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "adddi3 %1, %2 -> %0")

(define_insn "addsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addsi3 %1, %2 -> %0")

(define_insn "addpdi3"
  [(set (match_operand:PDI 0 "register_operand" "=r")
	(plus:PDI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addpdi3 %1, %2 -> %0")

(define_insn "addhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(plus:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addhi3 %1, %2 -> %0")

(define_insn "addqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(plus:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "addqi3 %1, %2 -> %0")

(define_insn "adddf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(plus:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		 (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "adddf3 %1, %2 -> %0")

(define_insn "addsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(plus:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		 (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "addsf3 %1, %2 -> %0")


;; Subtraction instructions

(define_insn "subdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(minus:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subdi %1, %2, %0")

(define_insn "subsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subsi %1, %2, %0")

(define_insn "subhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(minus:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subhi %1, %2, %0")

(define_insn "subqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(minus:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		  (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "subqi %1, %2, %0")


(define_expand "subpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 5)
         (minus:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")


(define_insn "subdf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(minus:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		  (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "subdf3 %1, %2 -> %0")

(define_insn "subsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(minus:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		  (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "subsf3 %1, %2 -> %0")

\f
;; Integer Multiply/Divide.

(define_insn "mulqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(mult:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulqi3\\t%1, %2 -> %0")

(define_insn "mulhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(mult:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulhi3 %1, %2 -> %0")

(define_insn "mulsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mult:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "mulsi3 %1, %2 -> %0")

(define_insn "muldi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(mult:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "muldi3 %1, %2 -> %0")

(define_expand "mulpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 5)
         (mult:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")



(define_insn "muldf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(mult:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")
		 (match_operand:DF 2 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "muldf3 %1, %2 -> %0")

(define_insn "mulsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(mult:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")
		 (match_operand:SF 2 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "mulsf3 %1, %2 -> %0")

;; Division instructions

(define_insn "divqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(div:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divqi3 %1, %2 -> %0")

(define_insn "divhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(div:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divhi3 %1, %2 -> %0")

(define_insn "divsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(div:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divsi3 %1, %2 -> %0")

(define_insn "divdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(div:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divdi3 %1, %2 -> %0")

(define_insn "divsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(div:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divsf3 %1, %2 -> %0")

(define_insn "divdf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(div:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "divdf3 %1, %2 -> %0")


;; Unsigned Division
(define_insn "udivqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(udiv:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivqi3 %1, %2 -> %0")

(define_insn "udivhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(udiv:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivhi3 %1, %2 -> %0")

(define_insn "udivsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(udiv:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivsi3 %1, %2 -> %0")

(define_insn "udivdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(udiv:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "udivdi3 %1, %2, %0")

(define_expand "udivpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 4)
        (zero_extend:DI (match_operand:PDI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_dup 5)
        (udiv:DI (match_dup 3) (match_dup 4)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 5)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
  operands[5] = gen_reg_rtx(DImode);
}")



;; Modulus instructions

(define_insn "modqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(mod:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modqi3 %1, %2 -> %0")


(define_insn "modhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(mod:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modhi3 %1, %2 -> %0")


(define_insn "modsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mod:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modsi3 %1, %2 -> %0")


(define_insn "moddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(mod:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "moddi3 %1, %2 -> %0")

(define_insn "modsf3"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(mod:SF (match_operand:SF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "modsf3 %1, %2 -> %0")

(define_insn "moddf3"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(mod:DF (match_operand:DF 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DF 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "moddf3 %1, %2 -> %0")


;; Unsigned Modulus
(define_insn "umodqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(umod:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodqi3 %1, %2 -> %0")

(define_insn "umodhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(umod:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodhi3 %1, %2 -> %0")

(define_insn "umodsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(umod:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "" )
		 (match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umodsi3 %1, %2 -> %0")

(define_insn "umoddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(umod:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		 (match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "umoddi3 %1, %2, %0")

;; LLVM doesn't have a NEG instruction, but it does have a SUB instruction.  Use
;; it instead.
;;

(define_expand "negpdi3"
  [(set (match_dup 2)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 3)
         (minus:DI (const_int 0) (match_dup 2)))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 3)))]
  ""
  "
{
  operands[2] = gen_reg_rtx(DImode);
  operands[3] = gen_reg_rtx(DImode);
}")

(define_insn "negdi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(minus:DI (const_int 0)
                  (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (const_int 0)
                  (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "neghi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(minus:HI (const_int 0)
                  (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(minus:QI (const_int 0)
                  (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")))]
  ""
  "")

(define_insn "negdf2"
  [(set (match_operand:DF 0 "register_operand" "=e")
	(minus:DF (const_int 0)
                  (match_operand:DF 1 "nonmemory_nonsubreg_operand" "e")))]
  ""
  "")

(define_insn "negsf2"
  [(set (match_operand:SF 0 "register_operand" "=f")
	(minus:SF (const_int 0)
                  (match_operand:SF 1 "nonmemory_nonsubreg_operand" "f")))]
  ""
  "")


;;- Boolean instructions

(define_insn "anddi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(and:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "anddi3 %1, %2, %0")

(define_insn "andsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andsi3 %1, %2, %0")

(define_insn "andhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(and:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andhi3 %1, %2, %0")

(define_insn "andqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(and:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "andqi3 %1, %2, %0")



(define_insn "iordi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ior:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iordi3 %1, %2, %0")

(define_insn "iorsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorsi3 %1, %2, %0")

(define_insn "iorhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ior:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorhi3 %1, %2, %0")

(define_insn "iorqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ior:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "iorqi3 %1, %2, %0")


(define_insn "xordi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(xor:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:DI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xordi3 %1, %2, %0")

(define_insn "xorsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:SI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorsi3 %1, %2, %0")

(define_insn "xorhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(xor:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:HI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorhi3 %1, %2, %0")

(define_insn "xorqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(xor:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		(match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "xorqi3 %1, %2, %0")

;; LLVM doesn't have a NOT instruction, but it does have a XOR instruction.  Use
;; it instead.
;;
(define_expand "one_cmpldi2"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(xor:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplhi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(xor:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")

(define_expand "one_cmplqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(xor:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
                (const_int -1)))]
  ""
  "")




;;- arithmetic shift instructions

(define_insn "ashlqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ashift:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlqi3 %1, %2 -> %0")

(define_insn "ashlhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ashift:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlhi3 %1, %2 -> %0")

(define_insn "ashlsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashift:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashlsi3 %1, %2 -> %0")

(define_insn "ashldi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashift:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		   (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashldi3 %1, %2 -> %0")

(define_expand "ashlpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (ashift:DI (match_dup 3) 
                    (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")



;; ashr

(define_insn "ashrqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(ashiftrt:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrqi3 %1, %2 -> %0")

(define_insn "ashrhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(ashiftrt:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrhi3 %1, %2 -> %0")

(define_insn "ashrsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrsi3 %1, %2 -> %0")

(define_insn "ashrdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashiftrt:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "ashrdi3 %1, %2 -> %0")

(define_expand "ashrpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (ashiftrt:DI (match_dup 3) 
                      (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")


(define_insn "lshrqi3"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(lshiftrt:QI (match_operand:QI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrqi3 %1, %2 -> %0")

(define_insn "lshrhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(lshiftrt:HI (match_operand:HI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrhi3 %1, %2 -> %0")

(define_insn "lshrsi3"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lshiftrt:SI (match_operand:SI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrsi3 %1, %2 -> %0")

(define_insn "lshrdi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(lshiftrt:DI (match_operand:DI 1 "nonmemory_nonsubreg_operand" "")
		     (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))]
  ""
  "lshrdi3 %1, %2 -> %0")

(define_expand "lshrpdi3"
  [(set (match_dup 3)
        (zero_extend:DI (match_operand:PDI 1 "nonmemory_nonsubreg_operand" "")))
   (set  (match_dup 4)
         (lshiftrt:DI (match_dup 3) 
                      (match_operand:QI 2 "nonmemory_nonsubreg_operand" "")))
   (set (match_operand:PDI 0 "register_operand" "=r")
        (truncate:PDI (match_dup 4)))]
  ""
  "
{
  operands[3] = gen_reg_rtx(DImode);
  operands[4] = gen_reg_rtx(DImode);
}")



\f
;; Unconditional and other jump instructions
;; On the Sparc, by setting the annul bit on an unconditional branch, the
;; following insn is never executed.  This saves us a nop.  Dbx does not
;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
  [(set (pc) (label_ref (match_operand 0 "" "")))]
  ""
  "*
{
  /* TurboSparc is reported to have problems with
     with
	foo: b,a foo
     i.e. an empty loop with the annul bit set.  The workaround is to use 
        foo: b foo; nop
     instead.  */

  return \"ba,pt%*\\t%%xcc, %l0%(\";
}")

;(define_expand "tablejump"
;  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
;	      (use (label_ref (match_operand 1 "" "")))])]
;  ""
;  "
;{
;  if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
;    abort ();
;}")

;(define_insn "*tablejump_sp"
;  [(set (pc) (match_operand:DI 0 "address_operand" "p"))
;   (use (label_ref (match_operand 1 "" "")))]
;  ""
;  "br %a0%#")

;;- jump to subroutine
(define_expand "call"
  ;; Note that this expression is not used for generating RTL.
  ;; All the RTL is generated explicitly below.
  [(call (match_operand 0 "call_operand" "")
	 (match_operand 3 "" "i"))]
  ;; operands[2] is next_arg_register
  ;; operands[3] is struct_value_size_rtx.
  ""
  "
{ emit_call_insn(gen_rtx_CALL(VOIDmode, operands[0], const0_rtx));
  DONE;
}")

;; We can't use the same pattern for these two insns, because then registers
;; in the address may not be properly reloaded.

(define_insn "*call_address_sp64"
  [(call (mem:PDI (match_operand:PDI 0 "address_operand" "p"))
	 (match_operand 1 "" ""))]
  ;;- Do not use operand 1 for most machines.
  ""
  "call %a0, %1%#")

(define_insn "*call_symbolic"
  [(call (mem:PDI (match_operand:PDI 0 "symbolic_operand" "s"))
	 (match_operand 1 "" ""))]
  ;;- Do not use operand 1 for most machines.
  ""
  "call %a0, %1%#")

(define_expand "call_value"
  ;; Note that this expression is not used for generating RTL.
  ;; All the RTL is generated explicitly below.
  [(set (match_operand 0 "nonmemory_nonsubreg_operand" "=rf")
	(call (match_operand 1 "" "")
	      (match_operand 4 "" "")))]
  ;; operand 2 is stack_size_rtx
  ;; operand 3 is next_arg_register
  ""
  "
{
  if (GET_MODE (operands[1]) != FUNCTION_MODE)
    abort ();
  emit_call_insn(gen_rtx_SET (VOIDmode, operands[0],
                              gen_rtx_CALL (VOIDmode, operands[1], const0_rtx)));
  DONE;
}")

(define_insn "*call_value_address"
  [(set (match_operand 0 "" "")
	(call (mem:PDI (match_operand:PDI 1 "address_operand" "p"))
	      (match_operand 2 "" "")))]
  ;;- Do not use operand 2 for most machines.
  ""
  "call\\t%a1, %2%#")

(define_insn "*call_value_symbolic"
  [(set (match_operand 0 "" "")
	(call (mem:PDI (match_operand:PDI 1 "symbolic_operand" "s"))
	      (match_operand 2 "" "")))]
  ;;- Do not use operand 2 for most machines.
  ""
  "call\\t%a1, %2%#")

(define_expand "untyped_call"
  [(parallel [(call (match_operand 0 "" "")
		    (const_int 0))
	      (match_operand 1 "" "")
	      (match_operand 2 "" "")])]
  ""
  "
{
  int i;

  /* Pass constm1 to indicate that it may expect a structure value, but
     we don't know what size it is.  */
  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));

  for (i = 0; i < XVECLEN (operands[2], 0); i++)
    {
      rtx set = XVECEXP (operands[2], 0, i);
      emit_move_insn (SET_DEST (set), SET_SRC (set));
    }

  DONE;
}")


;; Prepare to return any type including a structure value.

(define_expand "untyped_return"
  [(match_operand:BLK 0 "memory_operand" "")
   (match_operand 1 "" "")]
  ""
  "
{
  rtx valreg1 = gen_rtx_REG (DImode, 24);
  rtx valreg2 = gen_rtx_REG (DFmode, 32);
  rtx result = operands[0];

  /* Reload the function value registers.  */
  emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
  emit_move_insn (valreg2,
		  change_address (result, DFmode,
				  plus_constant (XEXP (result, 0), 8)));

  /* Put USE insns before the return.  */
  emit_insn (gen_rtx_USE (VOIDmode, valreg1));
  emit_insn (gen_rtx_USE (VOIDmode, valreg2));

  /* Construct the return.  */
  expand_null_return ();

  DONE;
}")

\f

(define_insn "nop"
  [(const_int 0)]
  ""
  "nop")

(define_expand "indirect_jump"
  [(set (pc) (match_operand 0 "address_operand" "p"))]
  ""
  "")

(define_insn "*branch_sp64"
  [(set (pc) (match_operand:PDI 0 "address_operand" "p"))]
  ""
  "br %a0%#
")

(define_expand "nonlocal_goto"
  [(match_operand:SI 0 "general_operand" "")
   (match_operand:SI 1 "general_operand" "")
   (match_operand:SI 2 "general_operand" "")
   (match_operand:SI 3 "" "")]
  ""
  "
{
  rtx fp = operands[1];
  rtx stack = operands[2];
  rtx lab = operands[3];
  rtx labreg;

  /* Load the fp value for the containing fn into %fp.  This is needed
     because STACK refers to %fp.  Note that virtual register instantiation
     fails if the virtual %fp isn't set from a register.  */
  if (GET_CODE (fp) != REG)
    fp = force_reg (Pmode, fp);
  emit_move_insn (virtual_stack_vars_rtx, fp);

  /* Find the containing function's current nonlocal goto handler,
     which will do any cleanups and then jump to the label.  */
  labreg = gen_rtx_REG (Pmode, 8);
  emit_move_insn (labreg, lab);

  /* Restore %fp from stack pointer value for containing function.
     The restore insn that follows will move this to %sp,
     and reload the appropriate value into %fp.  */
  emit_move_insn (frame_pointer_rtx, stack);

  /* USE of frame_pointer_rtx added for consistency; not clear if
     really needed.  */
  /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));

  emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
  emit_jump_insn (gen_goto_handler_and_restore (labreg));
  emit_barrier ();
  DONE;
}")

(define_insn "goto_handler_and_restore"
  [(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
  "GET_MODE (operands[0]) == Pmode"
  "jmp\\t%0+0\\n\\trestore")


;;; Special allocate_stack definition.  This causes alloca instructions to be
;;; turned into calls to __llvm_builtin_alloca, which is recognized by the LLVM
;;; backend, and turned into alloca instructions.
;;;
(define_expand "allocate_stack"
  [(match_operand:PDI 0 "register_operand" "=r")
   (match_operand:PDI 1 "register_operand" "")]
   ""
   "
{
  rtx Dest = operands[0], Amount = operands[1];
  emit_library_call_value(gen_rtx(SYMBOL_REF, Pmode, 
                          \"__llvm_builtin_alloca\"), Dest,
                          /*Pure fn call */ 2, PDImode, 1, Amount, DImode);
  DONE;
}")




;;(define_insn "*goto_handler_and_restore_v9_sp64"
;;  [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
;;		     (match_operand:DI 1 "register_operand" "=r,r")
;;		     (match_operand:SI 2 "const_int_operand" "n,n")] 3)]
;;  ""
;;  "@
;;   return\\t%0+0\\n\\tmov\\t%2, %Y1
;;   sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1")

;; For __builtin_setjmp we need to flush register windows iff the function
;; calls alloca as well, because otherwise the register window might be
;; saved after %sp adjustement and thus setjmp would crash
(define_expand "builtin_setjmp_setup"
  [(match_operand 0 "register_operand" "r")]
  ""
  "
{
  emit_insn (gen_do_builtin_setjmp_setup ());
  DONE;
}")

(define_insn "do_builtin_setjmp_setup"
  [(unspec_volatile [(const_int 0)] 5)]
  ""
  "*
{
  if (!current_function_calls_alloca)
    return \"\";
  return \"flushw\";
}")

;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.

(define_expand "setjmp"
  [(const_int 0)]
  ""
  "
{
  emit_insn (gen_setjmp_64 ());
  DONE;
}")

(define_expand "setjmp_32"
  [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
   (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
  ""
  "
{ operands[0] = frame_pointer_rtx; }")

(define_expand "setjmp_64"
  [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
   (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
  ""
  "
{ operands[0] = frame_pointer_rtx; }")

\f

;;;; We need to reload %l7 for -mflat -fpic,
;;;; otherwise %l7 should be preserved simply
;;;; by loading the function's register window
;;(define_expand "exception_receiver"
;;  [(const_int 0)]
;;  "flag_pic"
;;  "
;;{
;;  load_pic_register ();
;;  DONE;
;;}")

;;;; Likewise
;;(define_expand "builtin_setjmp_receiver"
;;  [(label_ref (match_operand 0 "" ""))]
;;  "flag_pic"
;;  "
;;{
;;  load_pic_register ();
;;  DONE;
;;}")
\f
(define_insn "trap"
  [(trap_if (const_int 1) (const_int 5))]
  ""
  "ta\\t5")

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-12-11 16:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-10 23:20 RTL to Simple Three instruction code Aditya Kanade
2002-12-10 23:29 ` Peter Barada
2002-12-11  7:17 ` Diego Novillo
2002-12-11  7:59   ` Michael S. Zick
2002-12-11  9:00     ` Diego Novillo
2002-12-10 23:36 Chris Lattner
2002-12-10 23:30 ` Chris Lattner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).