;;- Machine description for the PDP-10.				-*- lisp -*-
;;  Copyright (C) 2001, 2002 Free Software Foundation, Inc.
;;  Contributed by Lars Brinkhoff <lars@nocrew.org>, funded by XKL, LLC.

;; For information about the PDP-10 archtecture, see the README file
;; in this directory.

;; This file is part of GCC.

;; GCC is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; GCC is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
;; License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING.  If not, write to the Free
;; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Index

;;   Front Page
;;   Index
;;   Constraints for Immediate Operands
;;   To-do List
;;   Instruction Wish-List
;;   Attributes
;;	length, skip, reorg_type
;;   Unspec Usage
;;	UNSPEC_ADJSP, UNSPEC_ADJBP, UNSPEC_ADDRESS, UNSPEC_FFO, UNSPEC_SUBBP,
;;	VUNSPEC_BLT, VUNSPEC_FSC, VUNSPEC_XBLT, VUNSPEC_MOVSLJ, VUNSPEC_MOVST
;;   Constants
;;      RIGHT_HALF, LEFT_HALF, SIGNBIT, SP_REGNUM
;;   Optimizations
;;   Data Movement
;;	LDB, ILDB, (LDBI), LDBE, ILDBE, (LDBEI), DPB, IDPB, (DPBI),
;;	HRR, HRL, HLR, HLL, HRRM, HRLM, HLRM, HLLM,
;;	HRRZ, HRLZ, HLRZ, HLLZ, HRRE, HRLE, HLRE, HLLE,
;;	SETZM, SETOM,
;;	MOVE, MOVEI, MOVSI, HRLOI, HRROI, MOVEM,
;;	MOVS, EXCH, SETZB,
;;	DMOVE, DMOVEM,
;;	BLT, XBLT, (MOVSLJ), (MOVST), (CMPS)
;;   Conditional Data Movement
;;	SKIPL, SKIPE, SKIPLE, SKIPGE, SKIPN, SKIPG,
;;	TDZA
;;   Integer Arithmetic
;;	AOS, SOS,
;;	ADD, ADDI, ADDM, ADDB, DADD,
;;	SUB, SUBI, SUBM, SUBB, DSUB,
;;	IMUL, IMULI, IMULM, IMULB, MUL, MULI, MULM, MULB, DMUL,
;;	IDIV, IDIVI, IDIVM, DIV, DIVI, DIVM, DDIV,
;;	UIDIV, UIDIVI, UIDIVM, UIMOD, UIMODI, UIMODM,
;;	MOVN, MOVNM, MOVNS, MOVNI, DMOVN, DMOVNM,
;;	MOVM, MOVMM, MOVMS,
;;	FFS
;;   Integer Conversions
;;	ANDI, HRRZ, SEXT, HRRE, ANDI, HRR
;;   Shifting and Rotating
;;	LSH, LSHC, ASH, ASHC, ROT, ROTC
;;   Logical Operations
;;	AND, ANDI, ANDM, ANDB, TLZ, ANDCMI,
;;	ANDCA, ANDCAI, ANDCAM, ANDCAB, ANDCBI,
;;	ANDCM, ANDCMM, ANDCMB,
;;	XOR, XORI, XORM, XORB, TLC, EQVI,
;;	IOR, IORI, IORM, IORB, TLO, ORCMI,
;;	ANDCB, ANDCBM, ANDCBB,
;;	EQV, EQVM, EQVB,
;;	SETCA, SETCAM, SETCAB,
;;	SETCM, SETCMM, SETCMB,
;;	ORCA, ORCAI, ORCAM, ORCAB, ORCBI,
;;	ORCM, ORCMM, ORCMB,
;;	ORCB, ORCBM, ORCBB
;;   Floating-point Arithmetic
;;	FADR, FADRI, FADRM, FADRB, DFAD, GFAD,
;;	FSBR, FSBRI, FSBRM, FSBRB, DFSB, GFSB,
;;	MOVM, MOVMM, MOVMS,
;;	MOVN, MOVNM, MOVNS, DMOVN, DMOVNM,
;;	FMPR, FMPRI, FMPRM, FMPRB, DFMP, GFMP,
;;	FDVR, FDVRI, FDVRM, FDVRB, DFDV, GFDV,
;;	SQRT, DSQRT, GSQRT,
;;	FSC, DFSC, GFSC
;;   Floating-point Conversions
;;	FIX, DFIX, GFIX, DDFIX, GDFIX,
;;	FLTR, DFLTR, GFLTR, DDFLTR, DGFLTR,
;;	GSNGL, GDBLE
;;   Pointer Arithmetic
;;	IBP, ADJBP, SUBBP
;;   Unconditional Jumps
;;	JFCL, JRST, PUSHJ
;;   Conditional Jumps
;;	TRNE, TLNE, TDNE, TRNN, TLNN, TDNN, TLZN,
;;	JUMP, SKIP, CAI, CAM,
;;	SOJ, SOS, AOJ, AOS,
;;	JFFO, CMPBP
;;   Function prologue and epilogue
;;	POPJ, ADJSP, PUSH, POP
;;   Peepholes
;;   Miscellaneous
;;
;; Instructions in parentheses are either commented out or not
;; generated by the compiler.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constraints for Immediate Operands

;;   'G'	Any valid immediate floating-point constant.
;;   'I'	0 .. 262143
;;   'J'	-262143 .. 0
;;   'K'	-131072 .. 131071
;;   'L'	xxxxxx,,000000 (MOVSI, TLN, TLO, TLC)
;;   'M'	-1
;;   'N'	xxxxxx,,777777 (HRLOI, TLZ)
;;   'O'	0
;;   'P'	777777,,xxxxxx (HRROI, ORCMI, ANDCBI, ANDCMI)
;;   'Q'	1
;;   'R'	Floating-point zero.
;;   'S'	Local symbol.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; To-do List

;; Unsigned multiplication.

;; TSC, TSO, TSZ.  TSNE, TSNN.

;; Ok to negate double-word integer with DMOVN?

;; Converting from double float to single float (truncdfsf2) needs
;; rounding.

;; ANDCMI really faster than TRZ?

;; Add `cmpdi' pattern?

;; `cmpdf' is broken.  Only the first word is examined in the
;; comparison.  Use do_jump_by_parts_{equality,greater}_rtx?

;; Revisit `casesi'.

;; *move_and_skipsi uses temporary accumulator 0.  Is it possible to
;; allocate a scratch register?

;; Peepholes for AOSA and SOSA.

;; "Self" half-word instructions.

;; AOBJP, AOBJN?

;; SUBREG of DImode causes bad register allocation:
;; divmodsi4, divmoddi4, expand_builtin_jffo, ffssi.

;; String instructions.  Avoid them for now.  REG: "None of these is
;; fast.  None of these is thoroughly tested.  They all require a lot
;; of registers for setup.  They are uncharacteristic of other PDP-10
;; instructions."

;; Test-modify-skip instructions?

;; In case anyone would like to play strange games, this could be
;; optimized to use a PUSHJ instruction:
;;   static
;;   foo (void **p, void *f)	FOO:
;;   {					PUSHJ 1,(2)
;;     *++p = &&label;			POPJ 17,
;;     goto *f;
;;    label:
;;     return;
;;   }
;; And POPJ:
;;   static void
;;   bar (void **p)		BAR:
;;   {					POPJ 1,
;;     goto *p--;
;;   }

;; Use JSP to call functions with __attribute__ ((fastcall)) or similar.

;; Historical: KA10 software double precision floating-point.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Instruction Wish-List

;; ILDBE, LDBE - (increment and) load sign-extended byte.

;; LDBI, LDBEI, DPBI - load/deposit byte, then increment.

;; SUBBP - subtract byte pointers.

;; CMPBP - compare byte pointers.

;; SEXT r,n - sign-extend n-bit byte in register r.

;; Clear/set byte.

;; Test byte >0 =0 <0.

;; UIDIV, UDIV, UDDIV - unsigned division (udivsi3, udivdi3).

;; UIMOD, UMOD, UDMOD - unsigned modulo (umodsi3, umoddi3).

;; UJUMP, USKIP, UCAI, UCAM - compare unsigned values.

;; MIN, MAX, UMIN, UMAX - min/max (minsi3, maxsi3, uminsi3, umaxsi3).

;; SQRT, DSQRT, GSQRT - square root (sqrtM2).

;; SIN, DSIN, GSIN - sine function (__builtin_sin).

;; COS, DCOS, GCOS - cosine function (__builtin_cos).

;; Any other mathematical function: TAN, ASIN, ACOS, ATAN, SINH, COSH,
;; TANH, ASINH, ACOSH, ATANH, EXP, LN, LOG2, LOG10, POW, ...  All
;; potentially in single, double, and giant versions.

;; FFS - find first set, counting least significant bit first (ffsM2).

;; ?DFIX, DFIXR - Double Floating to Integer (fix_truncdfsi2).
;; ?DFIX, DFIXR - Single Floating to Double Precision Integer (fix_truncsfdi2).
;; DDFIX, DDFIXR - Double Floating to Double Precision Integer (fix_truncdfdi2)

;; ?DFLTR - Double Float and Round (floatsidf2).
;; ?DFLTR - Float Double Precision Integer and Round (floatdisf2).
;; DDFLTR - Double Float Double Precision Integer and Round (floatdidf2).

;; UDFLTR, UGFLTR, ... - Unsigned Float and Round (floatuns...).

;; WAIT - wait for interrupt.

;; XPUSH, XPUSHJ, XPOP, XPOPJ - fast versions for use with a global
;; stack pointer only.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Attributes

;; Length of the instruction, in words.
(define_attr "length" "" (const_int 1))

;; The instruction is a skip instruction.
(define_attr "skip" "no,yes" (const_string "no"))

;; Instruction type used in the machine dependent reorg pass.
(define_attr "reorg_type" "none,ibp,ldb,dpb" (const_string "none"))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Unspec Usage

(define_constants
  [(UNSPEC_ADJSP	0)	; ADJSP operation (Pmode):
				;   Operand 0 is the stack pointer.
				;   Operand 1 is the adjustment.
   (UNSPEC_ADJBP	1)	; ADJBP operation (Pmode):
				;   Operand 0 is the byte pointer.
				;   Operand 1 is the adjustment.
   (UNSPEC_ADDRESS	2)	; Effective-address calculation (Pmode):
				;   Operand 0 is the memory operand.
   (UNSPEC_FFO		3)	; Find-first-one operation in FFO (SImode):
				;   Operand 0 is the register.
   (UNSPEC_FSC		4)	; FSC operation (SFmode, DFmode):
				;   Operand 0 is the floating-point value.
				;   Operand 1 is the scale factor.
   (UNSPEC_SHIFT	5)	; Left-shift operation (SImode, Pmode):
				;   Used to compensate for unnecessary
				;   shifts generated by pointer arithmetic.
				;   Operand 0 is the value.
				;   Operand 1 is the shift count.
   (UNSPEC_SHIFTRT	6)	; Right-shift operation (SImode, Pmode):
				;   Used to compensate for unnecessary
				;   shifts generated by pointer arithmetic.
				;   Operand 0 is the value.
				;   Operand 1 is the shift count.
   (UNSPEC_TLNE_TLZA_TLO	; TLNE-TLZA-TLO sequence (SImode):
			7)	;   Operand 0 is the register.
				;   Operand 1 is the TLNE operand.
				;   Operand 2 is the TLZA operand.
				;   Operand 3 is the TLO operand.
   (UNSPEC_SUBBP	8)	; Byte pointer difference (SImode):
				;   Operand 0 is the first pointer.
				;   Operand 1 is the second pointer.
   (UNSPEC_CMPBP	9)	; Prepare byte pointer for comparison (SImode):
				;   Operand 0 is the pointer.
   (UNSPEC_REAL_ASHIFT	10)	; Arithmetic left shift (SImode, DImode):
				;   Operand 0 is the value to shift.
				;   Operand 1 is the amount to shift by.
   (UNSPEC_ASH71	11)	; 71-bit arithmetic shift (DImode):
				;   Operand 0 is the value to shift.
				;   Operand 1 is the amount to shift by.
   (UNSPEC_MUL71	12)	; 71-bit multiplication (DImode):
				;   Operands 0 and 1 are the multiplicands.
   (UNSPEC_SIGN_EXTEND	13)	; Sign extension (SImode):
				;   Operand 0 is the value to extend.
				;   Operand 1 is the number of bits to extend.
   (UNSPEC_ZERO_EXTEND	14)	; Zero extension (SImode):
				;   Operand 0 is the value to extend.
				;   Operand 1 is the number of bits to extend.
   (UNSPEC_TRUNCATE	15)])	; Truncate (SImode):
				;   Operand 0 is the value to truncate.
				;   Operand 1 is the number of bits to trunc.

(define_constants
  [(VUNSPEC_BLOCKAGE	0)
   (VUNSPEC_BLT		1)	; BLT operation (BLKmode):
				;   Operand 0 is the source address.
				;   Operand 1 is the destination address.
				;   Operand 2 is the block length.
   (VUNSPEC_XBLT	2)	; XBLT operation (BLKmode):
				;   operand 0 is the block length
				;   operand 1 is the source address
				;   operand 2 is the destination address
   (VUNSPEC_MOVSLJ	3)	; MOVSLJ operation (BLKmode):
				;   operand 0 is the register block
   (VUNSPEC_MOVST	4)	; MOVST operation (BLKmode):
				;   operand 0 is the register block
   (VUNSPEC_CMPS	5)])	; CMPS operation (BLKmode):
				;   operand 0 is the register block


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants

(define_constants
  [(RIGHT_HALF	262143)		; 0000000777777
   (LEFT_HALF	-262144)	; 0777777000000
   (SIGNBIT	-34359738368)	; 0400000000000
   (FP_REGNUM	13)		; Frame pointer register.
   (SP_REGNUM	15)])		; Stack pointer register.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Optimizations

;; Adding a constant to a word pointer is done fastest by (X)MOVEI
;; op0,const(op1).  As a special case, recognize the stack pointer.
(define_insn "MOVEI_sp"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (reg:SI SP_REGNUM)
		 (match_operand:SI 1 "const_int_operand" "")))]
  ""
  {
    operands[1] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[1]);
    /* ADDRESS: ...  */
    return TARGET_EXTENDED ? "xmovei %0,%a1" : "movei %0,%a1";
  })

;; Moving from any word pointer is done fastest by (X)MOVEI op0,(op1).
;; As a special case, recognize the stack pointer.
(define_insn "*move_from_sp"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(reg:SI SP_REGNUM))]
  ""
  {
    /* ADDRESS: ...  */
    return TARGET_EXTENDED ? "xmovei %0,(17)" : "movei %0,(17)";
  })

;; Load scalar signed chars using HRRE.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI
	 (match_operand:QI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "MEM_SCALAR_P (operands[1])"
  "hrre %0,%W1")
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extract:SI
	 (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
	 (const_int 9)
	 (const_int 27)))]
  "MEM_SCALAR_P (operands[1])"
  "hrre %0,%1")

(define_insn ""
  [(set (match_operand:QI 0 "register_operand" "=r")
	(subreg:QI
	 (zero_extract:SI (match_operand: SI 1 "memory_operand" "m")
			  (const_int 9)
			  (const_int 27))
	 3))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%1")

(define_insn ""
  [(set (subreg:QI
	 (zero_extract:SI (match_operand:SI 0 "memory_operand" "+m")
			  (const_int 9)
			  (const_int 27))
	 3)
	(match_operand:QI 1 "register_operand" "r"))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%0")

(define_insn ""
  [(set (subreg:HI
	 (zero_extract:SI (match_operand:SI 0 "memory_operand" "+m")
			  (const_int 18)
			  (const_int 18))
	 2)
	(match_operand:HI 1 "register_operand" "r"))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%0")

;; Load scalar unsigned chars using MOVE.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI
	 (match_operand:QI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%W1")
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI
	 (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
	 (const_int 511)))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%W1")

;; Store scalar chars using MOVEM.
(define_insn ""
  [(set (match_operand:QI 0 "pdp10_maybe_volatile_memory_operand" "=m")
	(match_operand:QI 1 "register_operand" "r"))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%W0")
(define_insn ""
  [(set (match_operand:SI 0 "pdp10_maybe_volatile_memory_operand" "=m")
	(sign_extract:SI (match_operand:SI 1 "register_operand" "r")
			 (const_int 9)
			 (const_int 27)))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%0")
(define_insn ""
  [(set (zero_extract:SI
	 (match_operand:SI 0 "pdp10_maybe_volatile_memory_operand" "+m")
	 (const_int 9)
	 (const_int 27))
	(and:SI (match_operand:SI 1 "register_operand" "r")
		(const_int 511)))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%0")

;; Load scalar unsigned shorts using MOVE.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI
	 (match_operand:HI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%W1")
(define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
	 (subreg:HI
	  (zero_extract:SI
	   (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
	   (const_int 18)
	   (const_int 18))
	  2))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%W1")
(define_insn ""
   [(set (match_operand:SI 0 "register_operand" "=r")
	 (and:SI (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
		 (const_int RIGHT_HALF)))]
  "MEM_SCALAR_P (operands[1])"
  "move %0,%W1")

;; Load scalar signed shorts using HRRE.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI
	 (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
	 (const_int 18)
	 (const_int 18)))]
  "MEM_SCALAR_P (operands[1])"
  "hrre %0,%1")
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI
	 (match_operand:HI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "MEM_SCALAR_P (operands[1])"
  "hrre %0,%W1")

;; Store scalar shorts using MOVEM.
(define_insn ""
  [(set (match_operand:HI 0 "pdp10_maybe_volatile_memory_operand" "=m")
	(match_operand:HI 1 "register_operand" "r"))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%W0")
(define_insn ""
  [(set (zero_extract:SI
	 (match_operand:SI 0 "pdp10_maybe_volatile_memory_operand" "+m")
	 (const_int 18)
	 (const_int 18))
	(and:SI (match_operand:SI 1 "register_operand" "r")
		(const_int RIGHT_HALF)))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%0")

(define_insn "*compare_range_ge_0"
  [(set (pc)
	(if_then_else
	 (ge (xor:SI (match_operand:SI 0 "register_operand" "r")
		     (const_int SIGNBIT))
	     (match_operand:SI 1 "const_int_operand" "i"))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))]
  ""
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = GEN_INT (0);
    ops[2] = operands[1];
    ops[3] = operands[2];
    return pdp10_output_range_compare (insn, ops, 0);
  }
  [(set_attr "length" "3")])

(define_insn "*compare_range_ge"
  [(set (pc)
	(if_then_else
	 (ge (xor:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
			      (match_operand:SI 1 "const_int_operand" "i"))
		     (const_int SIGNBIT))
	     (match_operand:SI 2 "const_int_operand" "i"))
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
  ""
  "*return pdp10_output_range_compare (insn, operands, 0);"
  [(set_attr "length" "3")])

(define_insn "*compare_range_lt_0"
  [(set (pc)
	(if_then_else
	 (lt (xor:SI (match_operand:SI 0 "register_operand" "r")
		     (const_int SIGNBIT))
	     (match_operand:SI 1 "const_int_operand" "i"))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))]
  ""
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = GEN_INT (0);
    ops[2] = operands[1];
    ops[3] = operands[2];
    return pdp10_output_range_compare (insn, ops, 1);
  }
  [(set_attr "length" "4")])

(define_insn "*compare_range_lt"
  [(set (pc)
	(if_then_else
	 (lt (xor:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
			      (match_operand:SI 1 "const_int_operand" "i"))
		     (const_int SIGNBIT))
	     (match_operand:SI 2 "const_int_operand" "i"))
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
  ""
  "*return pdp10_output_range_compare (insn, operands, 1);"
  [(set_attr "length" "4")])

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
		     (match_operand:SI 2 "const_int_operand" "i")))]
  "INTVAL (operands[2]) != 4 && INTVAL (operands[2]) != 18
   && INTVAL (operands[2]) != 20"
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = operands[1];
    ops[2] = GEN_INT (BITS_PER_WORD - INTVAL (operands[2]));
    ops[3] = GEN_INT (0);
    if (get_attr_length (insn) == 1)
      output_asm_insn (pdp10_output_extzv (insn, ops), ops);
    else
      output_asm_insn (pdp10_output_extzv_sequence (ops), ops);
    return "";
  }
  [(set (attr "length")
	(if_then_else
	 (and (ne (symbol_ref "TARGET_LARGE") (const_int 0))
	      (match_operand:SI 1 "pdp10_constaddr_memory_operand" ""))
	 (const_int 1)
	 (const_int 2)))])

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(and:SI (match_dup 0) (const_int RIGHT_HALF)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(and:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		(const_int RIGHT_HALF)))]
  ""
  "hrrzs %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(and:SI (match_dup 0) (const_int LEFT_HALF)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(and:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		(const_int LEFT_HALF)))]
  ""
  "hllzs %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(ashift:SI (match_dup 0) (const_int 18)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(ashift:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		   (const_int 18)))]
  ""
  "hrlzs %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(lshiftrt:SI (match_dup 0) (const_int 18)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(lshiftrt:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		     (const_int 18)))]
  ""
  "hlrzs %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(ior:SI (match_dup 0) (const_int LEFT_HALF)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(ior:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		(const_int LEFT_HALF)))]
  ""
  "hrros %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(ior:SI (match_dup 0) (const_int RIGHT_HALF)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(ior:SI (match_operand:SI 2 "reg_or_mem_operand" "=0")
		(const_int RIGHT_HALF)))]
  ""
  "hllos %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (ashift:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")
			   (const_int 18))
		(const_int RIGHT_HALF)))]
  ""
  "hrlo %0,%1")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (lshiftrt:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")
			     (const_int 18))
		(const_int LEFT_HALF)))]
  ""
  "hlro %0,%1")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data Movement

(define_expand "movqi"
  [(set (match_operand:QI 0 "reg_or_mem_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
  ""
  "if (!no_new_pseudos)
     {
       if (GET_CODE (operands[0]) == SUBREG
	   && GET_CODE (SUBREG_REG (operands[0])) == ZERO_EXTRACT)
	 {
	   if (GET_CODE (XEXP (SUBREG_REG (operands[0]), 0)) == MEM
	       && SUBREG_BYTE (operands[0]) == 3
	       && GET_CODE (XEXP (SUBREG_REG (operands[0]), 1)) == CONST_INT
	       && INTVAL (XEXP (SUBREG_REG (operands[0]), 1)) == 9
	       && GET_CODE (XEXP (SUBREG_REG (operands[0]), 2)) == CONST_INT
	       && INTVAL (XEXP (SUBREG_REG (operands[0]), 2)) == 27
	       && MEM_SCALAR_P (XEXP (SUBREG_REG (operands[0]), 0)))
	     emit_move_insn (XEXP (SUBREG_REG (operands[0]), 0),
			     convert_to_mode (SImode, operands[1], 1));
	   else
	     emit_move_insn (SUBREG_REG (operands[0]),
			     convert_to_mode (SImode, operands[1], 1));
	   DONE;
	 }
       else if (GET_CODE (operands[1]) == SUBREG
		&& GET_CODE (SUBREG_REG (operands[1])) == ZERO_EXTRACT)
	 {
	   rtx temp = gen_reg_rtx (SImode);
	   emit_move_insn (temp, SUBREG_REG (operands[1]));
	   operands[1] = gen_rtx_SUBREG (QImode, temp, 3);
	 }
       else if (GET_CODE (operands[1]) == CONST_INT)
   	 {
   	   rtx temp = gen_reg_rtx (SImode);
   	   emit_insn (gen_movsi (temp, operands[1]));
   	   operands[1] = gen_rtx_SUBREG (QImode, temp, 3);
   	 }
       if (GET_CODE (operands[0]) == MEM)
   	 operands[1] = force_reg (QImode, operands[1]);
     }
   else /* no_new_pseudos */
     {
       if (REG_P (operands[0]) && GET_CODE (operands[1]) == CONST_INT)
         {
	   operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
         }
     }")

(define_insn "*movqi_reg"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(match_operand:QI 1 "register_operand" "r"))]
  ""
  "move %0,%1")

(define_insn "*LDBzqi_sequence"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m,>")))]
  "TARGET_EXTENDED
   && !CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
   && pdp10_pointer_alignment (XEXP (operands[1], 0)) >= UNITS_PER_WORD
   && (GET_CODE (XEXP (operands[1], 0)) == REG
       || (INTVAL (XEXP (XEXP (operands[1], 0), 1)) % UNITS_PER_WORD == 0))"
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = operands[1];
    ops[2] = GEN_INT (9);
    ops[3] = GEN_INT (0);
    output_asm_insn (pdp10_output_extzv_sequence (ops), ops);
    return "";
  }
  [(set_attr "length" "2")])

(define_insn "*LDBzqi"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
        (zero_extend:SI (match_operand:QI 1 "memory_operand" ">,m")))]
  ""
  "*return pdp10_output_load_unsigned_byte (insn, operands);"
  [(set_attr "reorg_type" "none,ldb")])

(define_insn "*LDBIzqi"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:QI 1 "memory_operand" "<")))]
  "TARGET_XKL2"
  "*return pdp10_output_load_unsigned_byte (insn, operands);")

(define_insn "*LDBEqi"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
        (sign_extend:SI (match_operand:QI 1 "memory_operand" ">,<,m")))]
  "TARGET_XKL2"
  "*return pdp10_output_load_signed_byte (insn, operands);"
  [(set_attr "reorg_type" "none,none,ldb")])

(define_insn "*LDBEqi_sequence"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
        (sign_extend:SI (match_operand:QI 1 "memory_operand" ">,m")))]
  "!TARGET_XKL2"
  {
    if (/*CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) || */
	pdp10_pointer_alignment (XEXP (operands[1], 0)) >= UNITS_PER_WORD)
      {
	rtx ops[4];
	int offset = pdp10_pointer_offset (XEXP (operands[1], 0));
	ops[0] = operands[0];
	ops[1] = operands[1];
	ops[2] = GEN_INT (9);
	ops[3] = GEN_INT (0);
	output_asm_insn (pdp10_output_extv_sequence (ops), ops);
	return "";
      }
    else
      {
	if (which_alternative == 0)
	  return "ildb %0,%1\;trne %0,400\;%_orcmi %0,777";
	else
	  return "ldb %0,%1\;trne %0,400\;%_orcmi %0,777";
      }
  }
  [(set_attr "length" "3")
   (set_attr "reorg_type" "none,ldb")])

(define_insn "*LDBqi"
  [(set (match_operand:QI 0 "register_operand" "=r,r")
        (match_operand:QI 1 "memory_operand" ">,m"))]
  ""
  "*return pdp10_output_load_unsigned_byte (insn, operands);"
  [(set_attr "reorg_type" "none,ldb")])
;   "@
;    ildb %0,%1
;    ldb %0,%1")

(define_insn "*LDBIqi"
  [(set (match_operand:QI 0 "register_operand" "=r")
        (match_operand:QI 1 "memory_operand" "<"))]
  "TARGET_XKL2"
  "*return pdp10_output_load_unsigned_byte (insn, operands);")

(define_insn "*DPBqi"
  [(set (match_operand:QI 0 "memory_operand" "=>,m")
	(match_operand:QI 1 "register_operand" "r,r"))]
  ""
  "*return pdp10_output_store_byte (insn, operands);"
  [(set_attr "reorg_type" "none,dpb")])

(define_insn "*DPBIqi"
  [(set (match_operand:QI 0 "memory_operand" "=<")
	(match_operand:QI 1 "register_operand" "r"))]
  "TARGET_XKL2"
  "*return pdp10_output_store_byte (insn, operands);")

(define_expand "movhi"
  [(set (match_operand:HI 0 "reg_or_mem_operand" "")
        (match_operand:HI 1 "general_operand" ""))]
  ""
  "if (!no_new_pseudos)
     {
       if (GET_CODE (operands[0]) == SUBREG
	   && GET_CODE (SUBREG_REG (operands[0])) == ZERO_EXTRACT)
	 {
	   if (GET_CODE (XEXP (SUBREG_REG (operands[0]), 0)) == MEM
	       && SUBREG_BYTE (operands[0]) == 2
	       && GET_CODE (XEXP (SUBREG_REG (operands[0]), 1)) == CONST_INT
	       && INTVAL (XEXP (SUBREG_REG (operands[0]), 1)) == 18
	       && GET_CODE (XEXP (SUBREG_REG (operands[0]), 2)) == CONST_INT
	       && INTVAL (XEXP (SUBREG_REG (operands[0]), 2)) == 18
	       && MEM_SCALAR_P (XEXP (SUBREG_REG (operands[0]), 0)))
	     emit_move_insn (XEXP (SUBREG_REG (operands[0]), 0),
			     convert_to_mode (SImode, operands[1], 1));
	   else
	     emit_move_insn (SUBREG_REG (operands[0]),
			     convert_to_mode (SImode, operands[1], 1));
	   DONE;
	 }
       else if (GET_CODE (operands[1]) == SUBREG
		&& GET_CODE (SUBREG_REG (operands[1])) == ZERO_EXTRACT)
	 {
	   rtx temp = gen_reg_rtx (SImode);
	   emit_move_insn (temp, XEXP (operands[1], 0));
	   operands[1] = gen_rtx_SUBREG (HImode, temp, 2);
	 }
       else if (GET_CODE (operands[1]) == CONST_INT)
   	 {
   	   rtx reg = gen_reg_rtx (SImode);
   	   emit_insn (gen_movsi (reg, operands[1]));
   	   operands[1] = gen_rtx_SUBREG (HImode, reg, 2);
   	 }
       if (GET_CODE (operands[0]) == MEM)
   	 operands[1] = force_reg (HImode, operands[1]);
     }")

(define_insn "*movhi"
  [(set (match_operand:HI 0 "register_operand" "=r")
        (match_operand:HI 1 "register_operand" "r"))]
  ""
  "move %0,%1")

; (define_insn "*halfword_move"
;   [(set (match_operand:SI 0 "pdp10_halfword_destination" "=")
; 	(match_operand:SI 1 "pdp10_halfword_source" ""))]
;   ""
;   "*pdp10_output_halfword_move (operands);")

(define_insn "*HLR"
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
			 (const_int 18)
			 (const_int 18))
	(subreg:SI (match_operand:HI 1 "memory_operand" "m") 0))]
  ""
  "hlr %0,%W1")

(define_insn "*HLL"
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
			 (const_int 18)
			 (const_int 0))
	(subreg:SI (match_operand:HI 1 "memory_operand" "m") 0))]
  ""
  "hll %0,%W1")

(define_insn "*HLLM"
  [(set (mem:SI (match_operand:SI 0 "address_operand" "p"))
	(ior:SI (and:SI (match_operand:SI 1 "register_operand" "r")
			(const_int LEFT_HALF))
		(zero_extend:SI (mem:HI (match_dup 0)))))]
  ""
  {
    if (GET_CODE (operands[0]) == CONST
        && TARGET_EXTENDED && !TARGET_SMALLISH)
      /* ADDRESS: ...  */
      return "hllm %1,@[%W0]";
    else
      return "hllm %1,%W0";
  })

(define_insn "*HRR"
  [(set (zero_extract:SI (match_operand:SI 0 "reg_or_mem_operand" "+r,m")
			 (const_int 18)
			 (const_int 18))
	(and:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int RIGHT_HALF)))]
  ""
  "@
   hrr %0,%1
   hrrm %1,%0")

(define_insn "*HRL"
  [(set (zero_extract:SI (match_operand:SI 0 "reg_or_mem_operand" "+r,m")
			 (const_int 18)
			 (const_int 0))
	(and:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int RIGHT_HALF)))]
  ""
  "@
   hrl %0,%1
   hrlm %1,%0")

; (define_insn "*HxR"
;   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
; 			 (const_int 18)
; 			 (const_int 18))
;         (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0))]
;   ""
;   "*return pdp10_output_halfword_insv (insn, operands, 18);")

(define_insn "*HxRM"
  [(set (subreg:SI (match_operand:HI 1 "memory_operand" "=m") 0)
	(zero_extract:SI (match_operand:SI 0 "register_operand" "r")
			 (const_int 18)
			 (const_int 18)))]
  ""
  "*return pdp10_output_halfword_extv (insn, operands, 18);")

; (define_insn "*HxL"
;   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
; 			 (const_int 18)
; 			 (const_int 0))
;         (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0))]
;   ""
;   "*return pdp10_output_halfword_insv (insn, operands, 0);")

(define_insn "*HxLM"
  [(set (match_operand:HI 1 "memory_operand" "=m")
	(subreg:HI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
				(const_int 18)) 2))]
  ""
  "*return pdp10_output_halfword_extv (insn, operands, 0);")

(define_insn "*HLR"
  [(set (zero_extract:SI (match_operand:SI 0 "reg_or_mem_operand" "+r,m")
			 (const_int 18)
			 (const_int 18))
        (lshiftrt:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		     (const_int 18)))]
  ""
  "@
   hlr %0,%W1
   hlrm %1,%W0")

(define_insn "HRRZ"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(and:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int RIGHT_HALF)))]
  ""
  {
    if (REG_P (operands[0]) && REG_P (operands[1])
	&& REGNO (operands[0]) == REGNO (operands[1])
	&& zero_extended_p (operands[0], 18, insn))
      return "";
    else
      {
        const char *insn[] = { "hrrz %0,%W1", "hrrzm %1,%W0" };
	if (which_alternative == 0 && REG_P (operands[1])
	    && REGNO (operands[1]) != 0)
	  return "hrrzi %0,(%1)";
	return insn[which_alternative];
      }
  })

(define_insn "*HRRO"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(ior:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int LEFT_HALF)))]
  ""
  "@
   hrro %0,%W1
   hrrom %1,%W0")

(define_insn "*HLLZ"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(and:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int LEFT_HALF)))]
  ""
  "@
   hllz %0,%W1
   hllzm %1,%W0")

(define_insn "*HLLO"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(ior:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		(const_int RIGHT_HALF)))]
  ""
  "@
   hllo %0,%W1
   hllom %1,%W0")

(define_insn "*HLL"
  [(set (zero_extract:SI (match_operand:SI 0 "reg_or_mem_operand" "+r,m")
			 (const_int 18)
			 (const_int 0))
        (lshiftrt:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		     (const_int 18)))]
  ""
  "@
   hll %0,%W1
   hllm %1,%W0")

(define_insn "HLRZ"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(lshiftrt:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		     (const_int 18)))]
  ""
  "@
   hlrz %0,%1
   hlrzm %1,%0")

(define_insn "HLRE"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(ashiftrt:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		     (const_int 18)))]
  ""
  "@
   hlre %0,%1
   hlrem %1,%0")

(define_insn "*HLRE_extract"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:HI 1 "memory_operand" "m")
			 (const_int 18)
			 (const_int 0)))]
  ""
  "hlre %0,%W1")

(define_insn "*HRLZ"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(ashift:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r")
		   (const_int 18)))]
  ""
  "@
   hrlz %0,%1
   hrlzm %1,%0")

(define_insn "*loadhi"
  [(set (match_operand:HI 0 "register_operand" "=r")
        (match_operand:HI 1 "memory_operand" "m>"))]
  ""
  "*return pdp10_output_movhi (operands, 0);")

(define_insn "*zloadhi"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m>")))]
  ""
  "*return pdp10_output_movhi (operands, 0);")

(define_insn "*sloadhi_1"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI
	 (match_operand:HI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "pdp10_pointer_alignment (XEXP (operands[1], 0)) >= UNITS_PER_WORD"
  "*return pdp10_output_movhi (operands, 1);")

(define_insn "*sloadhi_2"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI
	 (match_operand:HI 1 "pdp10_maybe_volatile_memory_operand" "m")))]
  "pdp10_pointer_alignment (XEXP (operands[1], 0)) < UNITS_PER_WORD"
  {
    output_asm_insn (pdp10_output_movhi (operands, 0), operands);
    return REGNO (operands[0]) == 0 ? "hrre %0,%0" : "hrrei %0,(%0)";
  }
  [(set_attr "length" "2")])

(define_insn "storehi"
  [(set (match_operand:HI 0 "memory_operand" "=m>")
	(match_operand:HI 1 "register_operand" "r"))]
  ""
  "*return pdp10_output_movhi (operands, 0);")

(define_insn "*zstorehi"
  [(set (match_operand:SI 0 "memory_operand" "=m")
        (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))]
  ""
  "hrrzm %1,%0")

(define_insn "*sstorehi"
  [(set (match_operand:SI 0 "memory_operand" "=m")
        (sign_extend:SI (match_operand:HI 1 "memory_operand" "r")))]
  ""
  "hrrem %1,%0")

(define_expand "extv"
  [(set (match_operand:SI 0 "register_operand" "")
	(sign_extract:SI (match_operand:SI 1 "reg_or_mem_operand" "")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  ""
  "if (INTVAL (operands[2]) + INTVAL (operands[3]) > BITS_PER_WORD)
     FAIL;
   if (!TARGET_XKL2)
     {
       if (pdp10_expand_extv (operands))
         DONE;
     }")

(define_insn "*extv_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:SI 1 "register_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "!TARGET_XKL2"
  "*return pdp10_output_extv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*extv_mem"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "!TARGET_XKL2"
  "*return pdp10_output_extv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*extv_memsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:SI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "!TARGET_XKL2"
  "*return pdp10_output_extv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*LDBE_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:SI 1 "register_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "TARGET_XKL2"
  "*return pdp10_output_extv (insn, operands);")

(define_insn "*LDBE_regqi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:QI 1 "register_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "TARGET_XKL2"
  "*return pdp10_output_extv (insn, operands);")

(define_insn "*LDBE_mem"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extract:SI (match_operand:QI 1 "memory_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "TARGET_XKL2"
  "*return pdp10_output_extv (insn, operands);")

(define_expand "extzv"
  [(set (match_operand:SI 0 "register_operand" "")
	(zero_extract:SI (match_operand:SI 1 "reg_or_mem_operand" "")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  ""
  "if (INTVAL (operands[2]) + INTVAL (operands[3]) > BITS_PER_WORD)
     FAIL;
   if (pdp10_expand_extzv (operands))
     DONE;")

(define_insn "*extzv_reg_sequence"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) == 16 || INTVAL (operands[3]) == 0"
  "*return pdp10_output_extzv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*extzv_memsi_sequence"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) == 16
   || (TARGET_EXTENDED
       && INTVAL (operands[3]) == 0
       && !CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
       && (GET_CODE (XEXP (operands[1], 0)) == REG
	   || (GET_CODE (XEXP (operands[1], 0)) == PLUS
	       && INTVAL (XEXP (XEXP (operands[1], 0), 1))
		  % UNITS_PER_WORD == 0)))"
  "*return pdp10_output_extzv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*extzv_mem_sequence"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) == 16
   || (TARGET_EXTENDED
       && INTVAL (operands[3]) == 0
       && !CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
       && (GET_CODE (XEXP (operands[1], 0)) == REG
	   || (GET_CODE (XEXP (operands[1], 0)) == PLUS
	       && INTVAL (XEXP (XEXP (operands[1], 0), 1))
		  % UNITS_PER_WORD == 0)))"
  "*return pdp10_output_extzv_sequence (operands);"
  [(set_attr "length" "3")])

(define_insn "*extzv_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) != 16"
  "*return pdp10_output_extzv (insn, operands);")

(define_insn "*extzv_mem"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) != 16"
  "*return pdp10_output_extzv (insn, operands);")

(define_insn "*extzv_memsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
			 (match_operand:SI 2 "const_int_operand" "")
			 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) != 16"
  "*return pdp10_output_extzv (insn, operands);")

(define_expand "insv"
  [(set (zero_extract:SI (match_operand:SI 0 "reg_or_mem_operand" "")
			 (match_operand:SI 1 "const_int_operand" "")
			 (match_operand:SI 2 "const_int_operand" ""))
	(match_operand:SI 3 "register_operand" ""))]
  ""
  "if (INTVAL (operands[1]) + INTVAL (operands[2]) > BITS_PER_WORD)
     FAIL;
   /* FIXME: is this necessary?  According to test/misc/array-loop.c, yes. */
   if (GET_CODE (operands[0]) == MEM
       && GET_CODE (XEXP (operands[0], 0)) == REG
       && INTVAL (operands[1]) == BITS_PER_WORD
       && INTVAL (operands[2]) == 0)
     {
       emit_move_insn (gen_rtx_MEM (SImode, XEXP (operands[0], 0)),
		       operands[3]);
       DONE;
     }")

; (define_insn ""
;   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
; 			 (const_int 18)
; 			 (const_int 18))
; 	(match_operand:SI 3 "register_operand" "r"))]
;   ""
;   "*return pdp10_output_insv (insn, operands);")

(define_insn "*insv_reg"
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
			 (match_operand:SI 1 "const_int_operand" "")
			 (match_operand:SI 2 "const_int_operand" ""))
	(match_operand:SI 3 "register_operand" "r"))]
  ""
  "*return pdp10_output_insv (insn, operands);")

(define_insn "*insv_mem"
  [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
			 (match_operand:SI 1 "const_int_operand" "")
			 (match_operand:SI 2 "const_int_operand" ""))
	(match_operand:SI 3 "register_operand" "r"))]
  ""
  "*return pdp10_output_insv (insn, operands);")

(define_insn "*insv_memsi"
  [(set (zero_extract:SI (match_operand:SI 0 "memory_operand" "+m")
			 (match_operand:SI 1 "const_int_operand" "")
			 (match_operand:SI 2 "const_int_operand" ""))
	(match_operand:SI 3 "register_operand" "r"))]
  ""
  "*return pdp10_output_insv (insn, operands);")

(define_expand "movsi"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
  ""
  "if (GET_CODE (operands[0]) == ZERO_EXTRACT)
     operands[1] = force_reg (SImode, operands[1]);")

;; Special version using SKIPA to load a full-word constant.  This is
;; beneficial on processors with a cache.  Note the 'x' constraint on
;; alternative 7.  Reload can fall back on the last alternative if
;; instisting on moving to register 0.
(define_insn "*movsi_cache"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,r,r,x,m,m,m,r")
	;; ADDRESS: the S constraint allows a symbol.
        (match_operand:SI 1 "general_operand" "rm,I,S,L,M,N,P,i,O,M,r,i"))]
  "TARGET_CACHE && !optimize_size"
  "*return pdp10_output_movsi (insn, which_alternative);"
  [(set_attr "length" "1,1,1,1,1,1,1,2,1,1,1,1")])

(define_insn "*movsi_nocache"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,r,r,r,m,m,m")
	;; ADDRESS: the S constraint allows a symbol.
        (match_operand:SI 1 "general_operand" "rm,I,S,L,M,N,P,i,O,M,r"))]
  ""
  "*return pdp10_output_movsi (insn, which_alternative);")

(define_insn "move_two_halves"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (ashift:SI (match_operand:SI 1 "immediate_operand" "p")
			   (const_int 18))
		(match_operand:SI 2 "immediate_operand" "p")))]
  ""
  "move %0,[%1,,%2]")

(define_insn "*MOVS"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(match_operator:SI 1 "pdp10_rotate_operator"
	 [(match_operand:SI 2 "reg_or_mem_operand" "rm,r") (const_int 18)]))]
  ""
  "@
   movs %0,%2
   movsm %2,%0")

(define_insn "*EXCH"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
        (match_operand:SI 1 "register_operand" "r"))
   (set (match_operand:SI 2 "register_operand" "=1")
	(match_dup 0))]
  ""
  "exch %1,%0")

(define_insn "*SETZB"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm") (const_int 0))
   (set (match_operand:SI 1 "register_operand" "=r") (const_int 0))]
  ""
  "setzb %1,%0")

(define_expand "movdi"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "")
        (match_operand:DI 1 "general_operand" ""))]
  ""
  "if (!HAVE_DMOVE && pdp10_expand_dmove (operands[0], operands[1]))
     DONE;")

;; TODO: if there's a REG_UNUSED note attached to this insn, avoid
;; moving the unused part of the DImode register.
(define_insn "DMOVE"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,r,r,r,r,o,m")
        (match_operand:DI 1 "general_operand" "rm,O,I,J,i,O,r"))]
  "TARGET_KI10up"
  "@
   dmove %0,%1
   setzb %0,%Z0
   movei %0,0\;movei %Z0,%1
   seto %0\;movni %Z0,%n1
   dmove %0,[%D1]
   setzm %0\;setzm %Z0
   dmovem %1,%0"
  [(set_attr "length" "1,1,2,2,1,2,1")])

(define_insn "*movdi"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,r,r,r,r,o,o")
        (match_operand:DI 1 "general_operand" "ro,O,I,J,i,O,r"))]
  "!TARGET_KI10up"
  "@
   move %0,%1\;move %Z0,%Z1
   setzb %0,%Z0
   movei %0,0\;movei %Z0,%1
   seto %0\;movni %Z0,%n1
   move %0,[%A1]\;move %Z0,[%B1]
   setzm %0\;setzm %Z0
   movem %1,%0\;movem %Z1,%Z0"
  [(set_attr "length" "2,1,2,2,2,2,2")])

(define_expand "movti"
  [(set (match_operand:TI 0 "reg_or_mem_operand" "")
        (match_operand:TI 1 "general_operand" ""))]
  "TARGET_KI10up"
  "if (pdp10_expand_move_4 (operands[0], operands[1]))
     DONE;")

(define_insn "movsf"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,r,r,r,m,m")
        (match_operand:SF 1 "general_operand" "rm,R,G,F,R,r"))]
  ""
  "@
   move %0,%1%; movsf
   movei %0,0%; movsf
   movsi %0,%G1%; movsf
   move %0,[%1]%; movsf
   setzm %0%; movsf
   movem %1,%0%; movsf")

(define_expand "movdf"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
  ""
  "if (!HAVE_DMOVE && pdp10_expand_dmove (operands[0], operands[1]))
     DONE;")

(define_insn "*movdf_KI10up"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "=r,r,r,r,o,m")
        (match_operand:DF 1 "general_operand" "rm,R,G,F,R,r"))]
  "TARGET_KI10up"
  "@
   dmove %0,%1
   setzb %0,%Z0%; movdf
   movsi %0,%G1%; movdf\;movei %Z0,0%; movdf
   dmove %0,[%1]
   setzm %0%; movdf\;setzm %Z0%; movdf
   dmovem %1,%0"
  [(set_attr "length" "1,1,2,1,2,1")])

(define_insn "*movdf_notKI10up"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "=r,r,r,r,o,o")
        (match_operand:DF 1 "general_operand" "ro,R,G,F,R,r"))]
  "!TARGET_KI10up"
  "@
   move %0,%1%; movdf\;move %Z0,%Z1%; movdf
   setzb %0,%Z0%; movdf
   movsi %0,%G1%; movdf\;movei %Z0,0%; movdf
   move %0,[%A1]%; movdf\;move %Z0,[%B1]%; movdf
   setzm %0%; movdf\;setzm %Z0%; movdf
   movem %1,%0%; movdf\;movem %Z1,%Z0%; movdf"
  [(set_attr "length" "2,1,2,2,2,2")])

(define_expand "movstrsi"
  [(match_operand:BLK 0 "general_operand" "")
   (match_operand:BLK 1 "general_operand" "")
   (match_operand:SI 2 "general_operand" "")
   (match_operand:SI 3 "const_int_operand" "")]
  ""
  "if (pdp10_expand_movstrsi (operands))
     DONE;
   FAIL;")

(define_expand "clrstrsi"
  [(match_operand:BLK 0 "general_operand" "")
   (match_operand:SI 1 "general_operand" "")
   (match_operand:SI 2 "const_int_operand" "")]
  ""
  "if (pdp10_expand_clrstrsi (operands))
     DONE;
   FAIL;")

; (define_expand "cmpstrsi"
;   [(set (match_operand:SI 0 "register_operand" "")
; 	(compare:SI (match_operand:BLK 1 "general_operand" "")
; 		    (match_operand:BLK 2 "general_operand" "")))
;    (use (match_operand:SI 3 "general_operand" ""))
;    (use (match_operand:SI 4 "const_int_operand" ""))]
;   "TARGET_KL10up && TARGET_STRING"
;   "if (pdp10_expand_cmpstrsi (operands))
;      DONE;
;    FAIL;")

(define_insn "BLT"
  [(unspec_volatile:BLK
    [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_BLT)
   (clobber (match_dup 0))
   (use (match_operand:BLK 1 "memory_operand" "m"))]
  ""
  "blt %0,%1")

(define_insn "XBLT"
  [(unspec_volatile:BLK
    [(match_operand:TI 0 "register_operand" "+r")] VUNSPEC_XBLT)
  (clobber (match_dup 0))]
  "TARGET_KL10up"
  "extend %0,[xblt]")

; (define_insn "MOVSLJ"
;   [(unspec_volatile:BLK [(match_operand:SI 0 "register_operand" "+r")]
; 			 VUNSPEC_MOVSLJ)]
;   "TARGET_KL10up && TARGET_STRING"
;   "extend %0,[movslj]")

; (define_insn "MOVST"
;   [(unspec_volatile:BLK [(match_operand:SI 0 "register_operand" "+r")]
; 			 VUNSPEC_MOVST)]
;   "TARGET_KL10up && TARGET_STRING"
;   "extend %0,[movst]")

; (define_insn "CMPS"
;   [(unspec_volatile:BLK [(match_operand:SI 0 "register_operand" "+r")]
;			  VUNSPEC_CMPS)]
;   "TARGET_KL10up && TARGET_STRING"
;   "extend %0,[cmps]")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Conditional Data Movement

;; (define_expand "cstoresi4" ...)
;; (define_expand "cstoresf4" ...)

(define_expand "seq"
  [(set (match_operand:SI 0 "register_operand" "")
	(eq (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "sne"
  [(set (match_operand:SI 0 "register_operand" "")
	(ne (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "slt"
  [(set (match_operand:SI 0 "register_operand" "")
	(lt (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "sgt"
  [(set (match_operand:SI 0 "register_operand" "")
	(gt (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "sle"
  [(set (match_operand:SI 0 "register_operand" "")
	(le (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "sge"
  [(set (match_operand:SI 0 "register_operand" "")
	(ge (match_dup 1) (match_dup 2)))]
  ""
  "if (GET_MODE (pdp10_compare_op0) == DFmode)
     FAIL;
   operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "sltu"
  [(set (match_operand:SI 0 "register_operand" "")
	(lt (match_dup 1) (match_dup 2)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "sgtu"
  [(set (match_operand:SI 0 "register_operand" "")
	(gt (match_dup 1) (match_dup 2)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "sleu"
  [(set (match_operand:SI 0 "register_operand" "")
	(le (match_dup 1) (match_dup 2)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "sgeu"
  [(set (match_operand:SI 0 "register_operand" "")
	(ge (match_dup 1) (match_dup 2)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_insn "*snesi"
  [(set (match_operand:SI 0 "register_operand" "=r,x")
	(ne (match_operand:SI 1 "reg_or_mem_operand" "0,rm")
	    (const_int 0)))]
  ""
  "@
   skipe %@%0\;%_movei %0,1
   skipe %0,%1\;%_movei %0,1"
  [(set_attr "length" "2")])

(define_insn "*sccsi"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(match_operator 1 "pdp10_comparison_operator"
	 [(match_operand:SI 2 "reg_or_mem_operand" "r,rm")
	  (match_operand:SI 3 "general_operand" "rm,O")]))]
  ""
  "@
   cam%1 %2,%3\;%_tdza %0,%0\;%_%_movei %0,1
   skip%1 %@%2\;%_tdza %0,%0\;%_%_movei %0,1"
  [(set_attr "length" "3")])

(define_insn "*snesf"
  [(set (match_operand:SI 0 "register_operand" "=r,x")
	(ne (match_operand:SF 1 "reg_or_mem_operand" "0,rm")
	    (match_operand:SF 2 "immediate_operand" "R,R")))]
  ""
  "@
   skipe %@%0\;%_movei %0,1
   skipe %0,%1\;%_movei %0,1"
  [(set_attr "length" "2")])

(define_insn "*sccsf"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(match_operator 1 "pdp10_comparison_operator"
	 [(match_operand:SF 2 "reg_or_mem_operand" "r,rm")
	  (match_operand:SF 3 "general_operand" "rm,R")]))]
  ""
  "@
   cam%1 %2,%3\;%_tdza %0,%0\;%_%_movei %0,1
   skip%1 %@%2\;%_tdza %0,%0\;%_%_movei %0,1"
  [(set_attr "length" "3")])

;; (define_expand "cmovsi6" ...)
;; (define_expand "cmovsf6" ...)

;; Reload can't handle JUMP_INSNs (such as this one) with spilled
;; register outputs.  Therefore, this pattern must have a memory
;; alternative for operand 3.
(define_insn "*move_and_skipsi"
  [(set (pc)
	(if_then_else (match_operator 0 "pdp10_comparison_operator"
		       [(match_operand:SI 1 "reg_or_mem_operand" "r,rm,rm")
		        (const_int 0)])
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   ;; The predicate is "register_operand" even though the constraint
   ;; allows a memory operand.  The memory constraint is just there as
   ;; a last resort when operand 3 is spilled to stack.  The "r"
   ;; constraint is there to allow accumulator 0.
   (set (match_operand:SI 3 "register_operand" "=1,x,rm")
	(match_dup 1))]
  ""
  {
    if (which_alternative == 0)
      return "jump%0 %1,%l2";
    pdp10_remove_unnecessary_label (insn, operands[2]);
    switch (get_attr_length (insn))
      {
      case 1:
	return "skip%0 %3,%1";
      case 2:
	if (REGNO (operands[3]) == 0)
	  return "move %3,%1\;jump%0 %3,%l2";
	else
	  {
	    output_asm_insn ("skip%R0 %3,%1", operands);
	    return pdp10_output_jrst (insn, operands[2]);
	  }
      /* FIXME: is the use of a fixed scratch register avoidable?  */
      case 3:
	return "move 0,%1\;movem 0,%3\;jump%0 0,%l2";
      default:
	abort ();
      }
  }
  [(set (attr "length")
	(cond [(eq_attr "alternative" "0") (const_int 1)
	       (eq_attr "alternative" "2") (const_int 3)
	       (eq (minus (match_dup 2) (pc)) (const_int 1)) (const_int 1)]
	       (const_int 2)))
   (set_attr "skip" "yes")])

;; Reload can't handle JUMP_INSNs (such as this one) with spilled
;; register outputs.  Therefore, this pattern must have a memory
;; alternative for operand 4.
(define_insn "*move_and_skipsf"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "pdp10_comparison_operator"
	  [(match_operand:SF 1 "reg_or_mem_operand" "rm,rm,rm")
	   (match_operand:SF 2 "pdp10_const_double_0_operand" "")])
	  (label_ref (match_operand 3 "" ""))
	  (pc)))
   ;; The predicate is "register_operand" even though the constraint
   ;; allows a memory operand.  The memory constraint is just there as
   ;; a last resort when operand 4 is spilled to stack.  The "r"
   ;; constraint is there to allow accumulator 0.
   (set (match_operand:SF 4 "register_operand" "=1,x,rm")
	(match_dup 1))]
  ""
  {
    if (which_alternative == 0)
      return "jump%0 %1,%l3";
    pdp10_remove_unnecessary_label (insn, operands[3]);
    switch (get_attr_length (insn))
      {
      case 1:
	return "skip%0 %4,%1";
      case 2:
	if (REGNO (operands[3]) == 0)
	  return "move %4,%1\;jump%0 %4,%l3";
	else
	  {
	    output_asm_insn ("skip%R0 %4,%1", operands);
	    return pdp10_output_jrst (insn, operands[3]);
	  }
      /* FIXME: is the use of a fixed scratch register avoidable?  */
      case 3:
	return "move 0,%1\;movem 0,%4\;jump%0 0,%l3";
      default:
	abort ();
      }
  }
  [(set (attr "length")
	(cond [(eq_attr "alternative" "0") (const_int 1)
	       (eq_attr "alternative" "2") (const_int 3)
	       (eq (minus (match_dup 3) (pc)) (const_int 1)) (const_int 1)]
	       (const_int 2)))
   (set_attr "skip" "yes")])


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Integer Arithmetic

(define_insn "addsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,m,m,m")
	(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,0,0,0,0")
		 ;; ADDRESS: an S constraint for the addi case would allow
		 ;; a symbol.
		 (match_operand:SI 2 "general_operand" "rm,I,J,i,r,Q,M")))]
  ""
  "@
   add %0,%2
   addi %0,%2
   subi %0,%N2
   add %0,[%X2]
   addm %2,%0
   aos %@%0
   sos %@%0")

(define_insn "*ADDB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(plus:SI (match_dup 0) (match_dup 1)))]
  ""
  "addb %1,%0")
(define_insn "*ADDB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(plus:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(plus:SI (match_dup 1) (match_dup 0)))]
  ""
  "addb %1,%0")

(define_insn "*AOS_and_move"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(plus:SI (match_dup 0) (const_int 1)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(plus:SI (match_dup 0) (const_int 1)))]
  ""
  "aos %1,%0")

(define_insn "adddi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(plus:DI (match_operand:DI 1 "register_operand" "%0,0")
		 (match_operand:DI 2 "general_operand" "rm,i")))]
  ;; 71-bit arithmetic.
  "0 && TARGET_KL10up"
  "@
   dadd %0,%2
   dadd %0,[%D2]")

(define_expand "subsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(minus:SI (match_operand:SI 1 "register_operand" "")
		  (match_operand:SI 2 "general_operand" "")))]
  ""
  "if (!register_operand (operands[1], SImode))
     operands[1] = force_reg (SImode, operands[1]);")

(define_insn "*subsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(minus:SI (match_operand:SI 1 "register_operand" "0,r")
		  (match_operand:SI 2 "general_operand" "rm,0")))]
  ""
  "@
   sub %0,%2
   subm %1,%0")

(define_insn "*SUBB"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(minus:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(minus:SI (match_dup 1) (match_dup 0)))]
  ""
  "subb %1,%0")

(define_insn "*SOS_and_move"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(plus:SI (match_dup 0) (const_int -1)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(plus:SI (match_dup 0) (const_int -1)))]
  ""
  "sos %1,%0")

(define_insn "subdi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(minus:DI (match_operand:DI 1 "register_operand" "0,0")
		  (match_operand:DI 2 "reg_or_mem_operand" "rm,i")))]
  ;; 71-bit arithmetic.
  "0 && TARGET_KL10up"
  "@
   dsub %0,%2
   dsub %0,[%D2]")

(define_insn "mulsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,m")
	(mult:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,0")
		 (match_operand:SI 2 "general_operand" "rm,I,i,r")))]
  ""
  "@
   imul %0,%2
   imuli %0,%2
   imul %0,[%2]
   imulm %2,%0")

(define_insn "*IMULB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(mult:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(mult:SI (match_dup 0) (match_dup 1)))]
  ""
  "imulb %1,%0")
(define_insn "*IMULB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(mult:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(mult:SI (match_dup 1) (match_dup 0)))]
  ""
  "imulb %1,%0")

(define_insn "mulsidi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(mult:DI
	 (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,0,0"))
	 (sign_extend:DI (match_operand:SI 2 "general_operand" "rm,I,i"))))]
  ;; 71-bit arithmetic.
  "0"
  "@
   mul %0,%2
   muli %0,%2
   mul %0,[%2]")

(define_insn "MUL"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(unspec:DI
	 [(sign_extend:DI (match_operand:SI 1 "register_operand" "%0,0,0"))
	  (sign_extend:DI (match_operand:SI 2 "general_operand" "rm,I,i"))]
	 UNSPEC_MUL71))]
  ""
  "@
   mul %0,%2
   muli %0,%2
   mul %0,[%2]")

(define_expand "smulsi3_highpart"
  [(set (match_dup 3)
	(truncate:SI
	 (lshiftrt:DI
	  (mult:DI
	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
	   (sign_extend:DI (match_operand:SI 2 "reg_or_mem_operand" "0")))
	  (const_int 35))))
   (set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(ashiftrt:SI (match_dup 3) (neg:SI (const_int -1))))]
  ;; 71-bit arithmetic.
  "0"
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "*smulsi3_highpart"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(subreg:SI
	 (lshiftrt:DI
	  (mult:DI
	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
	   (sign_extend:DI (match_operand:SI 2 "reg_or_mem_operand" "0")))
	  (const_int 35))
	 4))]
  ;; 71-bit arithmetic.
  "0"
  "mulm %1,%0")

(define_insn "mulditi3"
  [(set (match_operand:TI 0 "register_operand" "=r,r")
	(mult:TI
	 (sign_extend:TI (match_operand:DI 1 "register_operand" "%0,0"))
	 (sign_extend:TI (match_operand:DI 2 "general_operand" "rm,i"))))]
  ;; 71-bit arithmetic.
  "0 && TARGET_KL10up"
  "@
   dmul %0,%2
   dmul %0,[%D2]")

(define_insn "IDIV"
  [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r,r,r") 0)
        (div:SI (match_operand:SI 1 "register_operand" "0,0,0")
                (match_operand:SI 2 "general_operand" "rm,I,i")))
   (set (subreg:SI (match_dup 0) 4)
        (mod:SI (match_dup 1) (match_dup 2)))]
  ""
  "@
   idiv %0,%2
   idivi %0,%2
   idiv %0,[%2]")

(define_insn "IDIVM"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
        (div:SI (match_operand:SI 1 "register_operand" "r")
                (match_operand:SI 2 "reg_or_mem_operand" "0")))]
  ""
  "idivm %1,%0")

;; IDIVB missing.

(define_expand "divsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(div:SI (match_operand:SI 1 "register_operand" "")
		(match_operand:SI 2 "general_operand" "")))]
  ""
  "if (immediate_operand (operands[2], SImode))
     {
       rtx temp = gen_reg_rtx (DImode);
       rtx temp0 = gen_rtx_SUBREG (SImode, temp, 0);

       emit_move_insn (temp0, operands[1]);
       emit_insn (gen_IDIV (temp, temp0, operands[2]));
       emit_move_insn (operands[0], temp0);
     }
   else
     emit_insn (gen_IDIVM (operands[0], operands[1], operands[2]));
   DONE;")

(define_expand "modsi3"
  [(set (match_operand:SI 0 "register_operand" "")
	(mod:SI (match_operand:SI 1 "register_operand" "")
		(match_operand:SI 2 "general_operand" "")))]
  ""
  "{
     rtx temp = gen_reg_rtx (DImode);
     rtx temp0 = gen_rtx_SUBREG (SImode, temp, 0);
     rtx temp1 = gen_rtx_SUBREG (SImode, temp, 4);

     emit_move_insn (temp0, operands[1]);
     emit_insn (gen_IDIV (temp, temp0, operands[2]));
     emit_move_insn (operands[0], temp1);
     DONE;
   }")

;; This is disabled, since it doesn't seem to have any advantages over
;; the `divsi3' and `modsi3' patterns.
(define_expand "_divmodsi4"
  [(parallel [(set (match_operand:SI 0 "reg_or_mem_operand" "")
		   (div:SI (match_operand:SI 1 "reg_or_mem_operand" "")
			   (match_operand:SI 2 "general_operand" "")))
	      (set (match_operand:SI 3 "reg_or_mem_operand" "")
		   (mod:SI (match_dup 1) (match_dup 2)))])]
  "0"
  "{
     rtx temp = gen_reg_rtx (DImode);
     rtx temp0 = gen_rtx_SUBREG (SImode, temp, 0);
     rtx temp1 = gen_rtx_SUBREG (SImode, temp, 4);

     emit_move_insn (temp0, operands[1]);
     emit_insn (gen_IDIV (temp, temp0, operands[2]));
     emit_move_insn (operands[0], temp0);
     emit_move_insn (operands[3], temp1);
     DONE;
   }")

(define_insn "*DIV"
  [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r,r,r") 0)
        (truncate:SI
	 (div:DI
	  (match_operand:DI 1 "register_operand" "0,0,0")
	  (sign_extend:DI (match_operand:SI 2 "general_operand" "rm,I,i")))))
   (set (subreg:SI (match_dup 0) 4)
        (truncate:SI (mod:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))]
  ;; 71-bit arithmetic.
  "0"
  "@
   div %0,%2
   divi %0,%2
   div %0,[%2]")

(define_insn "*DIVM"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(truncate:SI
	 (div:DI
	  (match_operand:DI 1 "register_operand" "r")
	  (sign_extend:DI (match_operand:SI 2 "memory_operand" "0")))))]
  ;; 71-bit arithmetic.
  "0"
  "divm %1,%0")

;; DIVB missing.

(define_insn "DDIV"
  [(set (subreg:DI (match_operand:TI 0 "register_operand" "=r,r") 0)
        (truncate:DI
	 (div:TI
	  (match_operand:TI 1 "register_operand" "0,0")
	  (sign_extend:TI (match_operand:DI 2 "general_operand" "rm,i")))))
   (set (subreg:DI (match_dup 0) 8)
        (truncate:DI (mod:TI (match_dup 1) (sign_extend:TI (match_dup 2)))))]
  ;; 71-bit arithmetic.
  "0"
  "@
   ddiv %0,%2
   ddiv %0,[%D2]")

(define_expand "divmoddi4"
  [(parallel [(set (match_operand:DI 0 "reg_or_mem_operand" "")
		   (div:DI (match_operand:DI 1 "register_operand" "")
			   (match_operand:DI 2 "general_operand" "")))
	      (set (match_operand:DI 3 "register_operand" "")
		   (mod:DI (match_dup 1) (match_dup 2)))])]
  ;; 71-bit arithmetic.
  "0"
  "{
     rtx temp = gen_reg_rtx (TImode);
     emit_move_insn (gen_rtx_SUBREG (DImode, temp, 0), operands[1]);
     emit_insn (gen_DDIV (temp, temp, operands[2]));
     emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, temp, 0));
     emit_move_insn (operands[3], gen_rtx_SUBREG (DImode, temp, 8));
     DONE;
   }")

(define_insn "udivsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,m")
	(udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,r")
		 (match_operand:SI 2 "general_operand" "I,i,rm,0")))]
  "TARGET_XKL2"
  "@
   extend %0,[uidivi %2]
   extend %0,[uidiv [%2]]
   extend %0,[uidiv %2]
   extend %1,[uidivm %0]")

;; UIDIVB missing.

(define_insn "umodsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,m")
	(umod:SI (match_operand:SI 1 "register_operand" "0,0,0,r")
		 (match_operand:SI 2 "general_operand" "I,i,rm,0")))]
  "TARGET_XKL2"
  "@
   extend %0,[uimodi %2]
   extend %0,[uimod [%2]]
   extend %0,[uimod %2]
   extend %1,[uimodm %0]")

;; UIMODB missing.

(define_insn "negsi2"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m,r,m")
	(neg:SI (match_operand:SI 1 "general_operand" "rm,r,I,0")))]
  ""
  "@
   movn %0,%1
   movnm %1,%0
   movni %0,%N1
   movns %0")

(define_insn "*MOVNS"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(neg:SI (match_dup 0)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(neg:SI (match_dup 0)))]
  ""
  "movns %1,%0")

(define_insn "negdi2"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,m")
	(neg:DI (match_operand:DI 1 "reg_or_mem_operand" "rm,r")))]
  ;; 71-bit arithmetic.
  "0 && TARGET_KI10up"
  "@
   dmovn %0,%1
   dmovnm %1,%0")

(define_insn "abssi2"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m,m")
	(abs:SI (match_operand:SI 1 "reg_or_mem_operand" "rm,r,0")))]
  ""
  "@
   movm %0,%1
   movmm %1,%0
   movms %0")

(define_insn "*MOVMS"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "+rm")
	(abs:SI (match_dup 0)))
   (set (match_operand:SI 1 "register_operand" "=x")
	(abs:SI (match_dup 0)))]
  ""
  "movms %1,%0")

(define_insn "smaxsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,x,x,x")
        (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,r,r,r,r")
		 (match_operand:SI 2 "general_operand" "rm,I,M,i,0,O,I,rm")))]
  ""
  "@
   camge %1,%2\;%_move %0,%2
   caige %1,%2\;%_movei %0,%2
   camge %1,[%2]\;%_seto %0,
   camge %1,[%2]\;%_move %0,[%2]
   camle %1,%2\;%_move %0,%1
   skipge %0,%1\;%_movei %0,0
   caile %1,%2\;%_skipa %0,%1\;%_%_movei %0,%2
   camle %1,%2\;%_skipa %0,%1\;%_%_move %0,%2"
  [(set_attr "length" "2,2,2,2,2,2,3,3")])

(define_expand "umaxsi3"
  [(set (match_dup 3)
	(xor:SI (match_operand:SI 1 "reg_or_mem_operand" "")
                (const_int SIGNBIT)))
   (set (match_dup 4)
	(xor:SI (match_operand:SI 2 "reg_or_mem_operand" "")
                (const_int SIGNBIT)))
   (set (match_operand:SI 0 "register_operand" "")
	(if_then_else:SI
	 (ge (match_dup 3) (match_dup 4))
	 (match_dup 1)
	 (match_dup 2)))]
  ""
  "operands[3] = gen_reg_rtx (SImode);
   operands[4] = gen_reg_rtx (SImode);")

(define_insn "*umaxsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,x")
	(if_then_else:SI
	 (ge (match_operand:SI 3 "register_operand" "r,r,r")
	     (match_operand:SI 4 "reg_or_mem_operand" "rm,rm,rm"))
	 (match_operand:SI 1 "reg_or_mem_operand" "0,rm,rm")
	 (match_operand:SI 2 "reg_or_mem_operand" "rm,0,rm")))]
  ""
  "@
   camge %3,%4\;%_move %0,%2
   camle %3,%4\;%_move %0,%1
   camle %3,%4\;%_skipa %0,%1\;%_%_move %0,%2"
  [(set_attr "length" "2,2,3")])

(define_insn "sminsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,x,x,x")
        (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,r,r,r,r")
		 (match_operand:SI 2 "general_operand" "rm,I,M,i,0,O,I,rm")))]
  ""
  "@
   camle %1,%2\;%_move %0,%2
   caile %1,%2\;%_movei %0,%2
   camle %1,[%2]\;%_seto %0,
   camle %1,[%2]\;%_move %0,[%2]
   camge %1,%2\;%_move %0,%1
   skiple %0,%1\;%_movei %0,0
   caige %1,%2\;%_skipa %0,%1\;%_%_movei %0,%2
   camge %1,%2\;%_skipa %0,%1\;%_%_move %0,%2"
  [(set_attr "length" "2,2,2,2,2,2,3,3")])

(define_expand "uminsi3"
  [(set (match_dup 3)
	(xor:SI (match_operand:SI 1 "reg_or_mem_operand" "")
                (const_int SIGNBIT)))
   (set (match_dup 4)
	(xor:SI (match_operand:SI 2 "reg_or_mem_operand" "")
                (const_int SIGNBIT)))
   (set (match_operand:SI 0 "register_operand" "")
	(if_then_else:SI
	 (le (match_dup 3) (match_dup 4))
	 (match_dup 1)
	 (match_dup 2)))]
  ""
  "operands[3] = gen_reg_rtx (SImode);
   operands[4] = gen_reg_rtx (SImode);")

(define_insn "*uminsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,x")
	(if_then_else:SI
	 (le (match_operand:SI 3 "register_operand" "r,r,r")
	     (match_operand:SI 4 "reg_or_mem_operand" "rm,rm,rm"))
	 (match_operand:SI 1 "reg_or_mem_operand" "0,rm,rm")
	 (match_operand:SI 2 "reg_or_mem_operand" "rm,0,rm")))]
  ""
  "@
   camle %3,%4\;%_move %0,%2
   camge %3,%4\;%_move %0,%1
   camge %3,%4\;%_skipa %0,%1\;%_%_move %0,%2"
  [(set_attr "length" "2,2,3")])

;; The JFFO instruction searches from the most significant bit while
;; FFS searches from the least significant bit.  The bit index and
;; treatment of zero also differ.
(define_expand "ffssi2"
  [(set (match_operand:SI 0 "register_operand" "")
	(ffs:SI (match_operand:SI 1 "register_operand" "")))]
  "TARGET_KA10up"
  "if (!TARGET_XKL2)
     {
       rtx t1 = gen_reg_rtx (SImode);
       rtx t2 = gen_reg_rtx (SImode);
       rtx t3 = gen_reg_rtx (DImode);
       rtx t4 = gen_reg_rtx (SImode);
       rtx label = gen_label_rtx ();
       extern int pdp10_expand_ffs;

       pdp10_expand_ffs++;

       emit_insn (gen_negsi2 (t1, operands[1]));
       emit_insn (gen_andsi3 (t2, operands[1], t1));
       emit_move_insn (gen_rtx_SUBREG (SImode, t3, 0), t2);
       emit_jump_insn (gen_JFFO (t3, gen_rtx_LABEL_REF (Pmode, label)));
       emit_move_insn (gen_rtx_SUBREG (SImode, t3, 4),
		       GEN_INT (36));
       emit_label (label);
       emit_insn (gen_subsi3 (t4,
			      gen_rtx_SUBREG (SImode, t3, 4),
			      GEN_INT (36)));
       emit_insn (gen_negsi2 (operands[0], t4));
       DONE;
     }")

(define_insn "*FFS"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ffs:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2"
  "ffs %0,%1")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Integer Conversions

; (define_insn "zero_extendqisi2"
;   [(set (match_operand:SI 0 "register_operand" "=r")
;         (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))]
;   ""
;   ""
;   [(set_attr "length" "0")])
(define_insn "zero_extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
  ""
  {
    if (zero_extended_p (operands[0], 27, insn))
      return "";
    else
      return "andi %0,777%; zero_extendqisi2";
  })

(define_insn "zero_extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))]
  ""
  {
    if (zero_extended_p (operands[0], 18, insn)
	&& REGNO (operands[0]) == REGNO (operands[1]))
      return "";
    else
      return REGNO (operands[1]) == 0
        ? "hrrz %0,%1%; zero_extendhisi2"
        : "hrrzi %0,(%1)%; zero_extendhisi2";
  })

(define_insn "*extendqisi2_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (sign_extend:SI
	 (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)))]
  ""
  {
    if (REGNO (operands[0]) == REGNO (operands[1]))
      return "";
    else
      return "move %0,%1%; extendqisi2_reg";
  })

(define_expand "extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "")
	(sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
  ""
  "")
;   "if (!TARGET_XKL2)
;      {
;        rtx op1 = operands[1];
;        if (GET_CODE (op1) == SUBREG && SUBREG_BYTE (op1) == 3)
; 	op1 = SUBREG_REG (op1);
;        emit_insn (gen_ashlsi3 (operands[0],
; 			       gen_rtx_SUBREG (SImode, op1, 0),
; 			       GEN_INT (27)));
;        emit_insn (gen_ASH_right (operands[0], operands[0], GEN_INT (-27)));
;        DONE;
;      }")


(define_insn "*extendqisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
  "!TARGET_XKL2"
  {
    if (sign_extended_p (operands[0], 27, insn))
      return "";
    else if (zero_extended_p (operands[0], 27, insn))
      return "trne %0,400\;%_orcmi %0,777";
    else
      return "lsh %0,33\;ash %0,-33";
  }
  [(set_attr "length" "2")])

(define_insn "*extendqisi2_xkl2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
  "TARGET_XKL2"
  "extend %0,[sext 9]")

(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
  ""
  {
    if (sign_extended_p (operands[1], 18, insn)
	&& REGNO (operands[0]) == REGNO (operands[1]))
      return "";
    else
      return REGNO (operands[1]) == 0
        ? "hrre %0,%1%; extendhisi2"
        : "hrrei %0,(%1)%; extendhisi2";
  })

(define_insn "truncsiqi2"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(truncate:QI (match_operand:SI 1 "register_operand" "0")))]
  ""
  "andi %0,777%; truncsiqi2")

(define_insn "truncsihi2"
  [(set (match_operand:HI 0 "register_operand" "=r")
	(truncate:HI (match_operand:SI 1 "register_operand" "r")))]
  ""
  "hrr %0,%1%; truncsihi2")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Shifting and Rotating

(define_insn "real_ashlsi3"
 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
       (unspec:SI
	[(match_operand:SI 1 "register_operand" "0,0,0")
	 (match_operand:SI 2 "general_operand" "x,K,m")]
	UNSPEC_REAL_ASHIFT))]
 ""
 "@
  ash %0,(%2)
  ash %0,%2
  ash %0,@%2")

(define_insn "*ASH_left_plus"
 [(set (match_operand:SI 0 "register_operand" "=r")
       (unspec:SI
	[(match_operand:SI 1 "register_operand" "0")
	 (plus:SI (match_operand:SI 2 "register_operand" "x")
		  (match_operand:SI 3 "immediate_operand" "K"))]
	UNSPEC_REAL_ASHIFT))]
 ""
 "ash %0,%3(%2)")

(define_expand "lshrsi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:SI 0 "register_operand" "")
	(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ""
  "if (GET_CODE (operands[2]) == CONST_INT)
     {
       emit_insn (gen_LSH_right (operands[0], operands[1],
				 GEN_INT (-INTVAL (operands[2]))));
       DONE;
     }
   else
     operands[3] = gen_reg_rtx (SImode);")

(define_insn "LSH_right"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  ""
  "@
   lsh %0,(%2)
   lsh %0,%2
   lsh %0,@%2")

(define_insn "*LSH_right_plus"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lshiftrt:SI
	 (match_operand:SI 1 "register_operand" "0")
	 (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "const_int_operand" "K")))))]
  ""
  "lsh %0,%3(%2)")

(define_insn "real_ashldi3"
 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
       (unspec:DI
	[(match_operand:DI 1 "register_operand" "0,0,0")
	 (match_operand:SI 2 "general_operand" "x,K,m")]
	UNSPEC_REAL_ASHIFT))]
 ;; 71-bit arithmetic.
 "0"
 "@
  ashc %0,(%2)
  ashc %0,%2
  ashc %0,@%2")

(define_insn "*ASHC"
 [(set (match_operand:DI 0 "register_operand" "=r")
       (unspec:DI
	[(match_operand:DI 1 "register_operand" "0")
	 (plus:SI (match_operand:SI 2 "register_operand" "x")
		  (match_operand:SI 3 "immediate_operand" "K"))]
	UNSPEC_REAL_ASHIFT))]
 ;; 71-bit arithmetic.
 "0"
 "ashc %0,%3(%2)")

(define_expand "lshrdi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:DI 0 "register_operand" "")
	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ""
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "*LSHC_right"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  ""
  "@
   lshc %0,(%2)
   lshc %0,%2
   lshc %0,@%2")

(define_insn "*LSHC_right_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(lshiftrt:DI
	 (match_operand:DI 1 "register_operand" "0")
	 (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "immediate_operand" "K")))))]
  ""
  "lshc %0,%3(%2)")

(define_insn "ashlsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
	(ashift:SI (match_operand:SI 1 "register_operand" "0,0,0")
		   (match_operand:SI 2 "general_operand" "x,K,m")))]
  ""
  "@
   lsh %0,(%2)
   lsh %0,%2
   lsh %0,@%2")

(define_insn "*LSH_left_plus"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashift:SI (match_operand:SI 1 "register_operand" "0")
		   (plus:SI (match_operand:SI 2 "register_operand" "x")
			    (match_operand:SI 3 "immediate_operand" "K"))))]
  ""
  "lsh %0,%3(%2)")

(define_expand "ashrsi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:SI 0 "register_operand" "")
	(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ""
  "if (GET_CODE (operands[2]) == CONST_INT)
     {
       emit_insn (gen_ASH_right (operands[0], operands[1],
				 GEN_INT (-INTVAL (operands[2]))));
       DONE;
     }
   else
     operands[3] = gen_reg_rtx (SImode);")

(define_insn "ASH_right"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  ""
  "@
   ash %0,(%2)
   ash %0,%2
   ash %0,@%2")

(define_insn "*ASH_right_plus"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI
	 (match_operand:SI 1 "register_operand" "0")
	 (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "immediate_operand" "K")))))]
  ""
  "ash %0,%3(%2)")

(define_insn "ashldi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(ashift:DI (match_operand:DI 1 "register_operand" "0,0,0")
		   (match_operand:SI 2 "general_operand" "x,K,m")))]
  ""
  "@
   lshc %0,(%2)
   lshc %0,%2
   lshc %0,@%2")

(define_insn "*LSHC_left_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashift:DI (match_operand:DI 1 "register_operand" "0")
		   (plus:SI (match_operand:SI 2 "register_operand" "x")
			    (match_operand:SI 3 "immediate_operand" "K"))))]
  ""
  "lshc %0,%3(%2)")

(define_expand "ashrdi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:DI 0 "register_operand" "")
	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ;; 71-bit arithmetic.
  "0"
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "ASHC_right"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(unspec:DI [(match_operand:DI 1 "register_operand" "0,0,0")
		    (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))]
		   UNSPEC_ASH71))]
  ""
  "@
   ashc %0,(%2)
   ashc %0,%2
   ashc %0,@%2")

(define_insn "*ASHC_right_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(unspec:DI
	 [(match_operand:DI 1 "register_operand" "0")
	  (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			   (match_operand:SI 3 "immediate_operand" "K")))]
	 UNSPEC_ASH71))]
  ""
  "ashc %0,%3(%2)")

(define_insn "rotlsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
	(rotate:SI (match_operand:SI 1 "register_operand" "0,0,0")
		   (match_operand:SI 2 "general_operand" "x,K,m")))]
  ""
  "@
   rot %0,(%2)
   rot %0,%Y2
   rot %0,@%2")

(define_insn "*ROT_left_plus"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(rotate:SI (match_operand:SI 1 "register_operand" "0")
		   (plus:SI (match_operand:SI 2 "register_operand" "x")
			    (match_operand:SI 3 "immediate_operand" "K"))))]
  ""
  "rot %0,%Y3(%2)")

(define_expand "rotrsi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:SI 0 "register_operand" "")
	(rotatert:SI (match_operand:SI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ""
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "*ROT_right"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
	(rotatert:SI (match_operand:SI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  ""
  "@
   rot %0,(%2)
   rot %0,%Y2
   rot %0,@%2")

(define_insn "*ROT_right_plus"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(rotatert:SI
	 (match_operand:SI 1 "register_operand" "0")
	 (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "immediate_operand" "K")))))]
  ""
  "rot %0,%Y3(%2)")

(define_insn "rotldi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(rotate:DI (match_operand:DI 1 "register_operand" "0,0,0")
		   (match_operand:SI 2 "general_operand" "x,K,m")))]
  ""
  "@
   rotc %0,(%2)
   rotc %0,%V2
   rotc %0,@%2")

(define_insn "*ROTC_left_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(rotate:DI (match_operand:DI 1 "register_operand" "0")
		   (plus:SI (match_operand:SI 2 "register_operand" "x")
			    (match_operand:SI 3 "immediate_operand" "K"))))]
  ""
  "rotc %0,%V3(%2)")

(define_expand "rotrdi3"
  [(set (match_dup 3) (neg:SI (match_operand:SI 2 "general_operand" "")))
   (set (match_operand:DI 0 "register_operand" "")
	(rotatert:DI (match_operand:DI 1 "register_operand" "")
		     (neg:SI (match_dup 3))))]
  ""
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "*ROTC_right"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(rotatert:DI (match_operand:DI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  ""
  "@
   rotc %0,(%2)
   rotc %0,%V2
   rotc %0,@%2")

(define_insn "*ROTC_right_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(rotatert:DI
	 (match_operand:DI 1 "register_operand" "0")
	 (neg:SI (plus:SI (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "immediate_operand" "K")))))]
  ""
  "rotc %0,%V3(%2)")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Logical Operations

;; SETZ -- in Data Movement

;; AND -- andsi3

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (subreg:SI (match_operand:QI 1 "memory_operand" "m") 0)
		(const_int 63)))]
  ""
  "*return pdp10_output_extzv_foo (insn, operands);")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (match_operand:SI 1 "memory_operand" "m")
		(match_operand:SI 2 "const_int_operand" "i")))]
  "TARGET_LARGE && CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
   && (INTVAL (operands[2]) == 077 || INTVAL (operands[2]) == 0777)"
  {
    rtx ops[4];
    int bitsize = exact_log2 (INTVAL (operands[2]) + 1);
    ops[0] = operands[0];
    ops[1] = operands[1];
    ops[2] = GEN_INT (bitsize);
    ops[3] = GEN_INT (BITS_PER_WORD - bitsize);
    output_asm_insn (pdp10_output_extzv (insn, ops), ops);
    return "";
  })

(define_expand "andsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
        (and:SI (match_operand:SI 1 "reg_or_mem_operand" "")
                (match_operand:SI 2 "general_operand" "")))]
  ""
  "")

(define_insn "*andsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,m")
        (and:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,0,0,0")
                (match_operand:SI 2 "general_operand" "rm,I,N,P,i,r")))]
  ""
  "@
   and %0,%2
   andi %0,%2
   tlz %0,%T2
   andcmi %0,%C2
   and %0,[%2]
   andm %2,%0")

(define_insn "*ANDB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (match_dup 0) (match_dup 1)))]
  ""
  "andb %1,%0")
(define_insn "*ANDB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (match_dup 1) (match_dup 0)))]
  ""
  "andb %1,%0")

;; ANDCA, ANDCM

(define_insn "ANDCx"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,m,m")
        (and:SI
	 (not:SI (match_operand:SI 1 "reg_or_mem_operand" "0,rm,0,0,r,0"))
	 (match_operand:SI 2 "general_operand" "rm,0,I,P,0,r")))]
  ""
  "@
   andca %0,%2
   andcm %0,%1
   andcai %0,%2
   andcbi %0,%C2
   andcam %1,%0
   andcmm %2,%0")

(define_insn "*ANDCAB"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
		(match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (not:SI (match_dup 1)) (match_dup 0)))]
  ""
  "andcab %1,%0")

(define_insn "*ANDCMB"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (not:SI (match_dup 0))
		(match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (not:SI (match_dup 0)) (match_dup 1)))]
  ""
  "andcmb %1,%0")
; (define_insn "*ANDCMB"
;   [(set (match_operand:SI 0 "register_operand" "=r")
; 	(and:SI (not:SI (match_operand:SI 1 "memory_operand" "+m"))
; 		(match_operand:SI 2 "register_operand" "0")))
;    (set (match_dup 1)
; 	(and:SI (not:SI (match_dup 1)) (match_dup 2)))]
;   ""
;   "andcmb %0,%1")

;; SETM -- not useful

;; SETA -- not useful

;; XOR -- xorsi3

(define_insn "xorsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,m")
        (xor:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,0,0,0")
                (match_operand:SI 2 "general_operand" "rm,I,L,P,i,r")))]
  ""
  "@
   xor %0,%2
   xori %0,%2
   tlc %0,%S2
   eqvi %0,%C2
   xor %0,[%2]
   xorm %2,%0")

(define_insn "*XORB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(xor:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(xor:SI (match_dup 0) (match_dup 1)))]
  ""
  "xorb %1,%0")
(define_insn "*XORB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(xor:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(xor:SI (match_dup 1) (match_dup 0)))]
  ""
  "xorb %1,%0")

;; IOR -- iorsi3

(define_insn "iorsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,m")
        (ior:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,0,0,0")
                (match_operand:SI 2 "general_operand" "rm,I,L,P,i,r")))]
  ""
  "@
   ior %0,%2
   iori %0,%2
   tlo %0,%S2
   orcmi %0,%C2
   ior %0,[%2]
   iorm %2,%0")

(define_insn "*IORB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (match_dup 0) (match_dup 1)))]
  ""
  "iorb %1,%0")
(define_insn "*IORB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (match_operand:SI 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (match_dup 1) (match_dup 0)))]
  ""
  "iorb %1,%0")

;; ANDCB

(define_insn "*ANCDB"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
        (and:SI (not:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0"))
                (not:SI (match_operand:SI 2 "reg_or_mem_operand" "rm,r"))))]
  ""
  "@
   andcb %0,%2
   andcbm %2,%0")

(define_insn "*ANDCBB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (not:SI (match_dup 0))
		(not:SI (match_operand:SI 1 "register_operand" "r"))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (not:SI (match_dup 0)) (not:SI (match_dup 1))))]
  ""
  "andcbb %1,%0")
(define_insn "*ANDCBB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
		(not:SI (match_dup 0))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(and:SI (not:SI (match_dup 1)) (not:SI (match_dup 0))))]
  ""
  "andcbb %1,%0")

(define_insn "*ANDCBB"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (not:SI (match_operand:SI 1 "register_operand" "%0"))
		(not:SI (match_operand:SI 2 "memory_operand" "+m"))))
   (set (match_dup 2)
	(and:SI (not:SI (match_dup 1)) (not:SI (match_dup 2))))]
  ""
  "andcbb %0,%2")

;; EQV

(define_insn "*EQV"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
	(not:SI (xor:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0")
			(match_operand:SI 2 "reg_or_mem_operand" "rm,r"))))]
  ""
  "@
   eqv %0,%2
   eqvm %2,%0")

(define_insn "*EQVB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(not:SI (xor:SI (match_dup 0)
			(match_operand:SI 1 "register_operand" "r"))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(not:SI (xor:SI (match_dup 0) (match_dup 1))))]
  ""
  "eqvb %1,%0")
(define_insn "*EQVB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
			(match_dup 0))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(not:SI (xor:SI (match_dup 1) (match_dup 0))))]
  ""
  "eqvb %1,%0")

;; SETCA, SETCM -- one_cmplsi2

(define_insn "one_cmplsi2"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,m,m")
        (not:SI (match_operand:SI 1 "reg_or_mem_operand" "0,rm,r,0")))]
  ""
  "@
   setca %0,
   setcm %0,%1
   setcam %1,%0
   setcmm %0")

(define_insn "*SETCAB"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(not:SI (match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(not:SI (match_dup 1)))]
  ""
  "setcab %1,%0")

(define_insn "*SETCMB"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(not:SI (match_dup 0)))
   (set (match_operand:SI 1 "register_operand" "=r")
	(not:SI (match_dup 0)))]
  ""
  "setcmb %0,%1")

;; ORCA, ORCM

(define_insn "*ORCx"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,m,m")
        (ior:SI
	 (not:SI (match_operand:SI 1 "reg_or_mem_operand" "0,rm,0,0,r,0"))
	 (match_operand:SI 2 "general_operand" "rm,0,I,P,0,r")))]
  ""
  "@
   orca %0,%2
   orcm %0,%1
   orcai %0,%2
   orcbi %0,%C2
   orcam %1,%0
   orcmm %2,%0")

(define_insn "*ORCAB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (match_dup 0)
		(not:SI (match_operand:SI 1 "register_operand" "r"))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (match_dup 0) (not:SI (match_dup 1))))]
  ""
  "orcab %1,%0")
(define_insn "*ORCAB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
		(match_dup 0)))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (not:SI (match_dup 1)) (match_dup 0)))]
  ""
  "orcab %1,%0")

(define_insn "*ORCMB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (not:SI (match_dup 0))
		(match_operand:SI 1 "register_operand" "r")))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (not:SI (match_dup 0)) (match_dup 1)))]
  ""
  "orcmb %1,%0")
(define_insn "*ORCMB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (match_operand:SI 1 "register_operand" "r")
		(not:SI (match_dup 0))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (match_dup 1) (not:SI (match_dup 0))))]
  ""
  "orcmb %1,%0")

;; ORCB

(define_insn "*ORCB"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,m")
        (ior:SI (not:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0"))
                (not:SI (match_operand:SI 2 "reg_or_mem_operand" "rm,r"))))]
  ""
  "@
   orcb %0,%2
   orcbm %2,%0")

(define_insn "*ORCMB1"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (not:SI (match_dup 0))
		(not:SI (match_operand:SI 1 "register_operand" "r"))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (not:SI (match_dup 0)) (not:SI (match_dup 1))))]
  ""
  "orcbb %1,%0")
(define_insn "*ORCMB2"
  [(set (match_operand:SI 0 "memory_operand" "+m")
	(ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
		(not:SI (match_dup 0))))
   (set (match_operand:SI 2 "register_operand" "=1")
	(ior:SI (not:SI (match_dup 1)) (not:SI (match_dup 0))))]
  ""
  "orcbb %1,%0")

;; SETO -- in Data Movement


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Floating-point Arithmetic

(define_insn "addsf3"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,r,r,m")
	(plus:SF (match_operand:SF 1 "reg_or_mem_operand" "%0,0,0,0")
		 (match_operand:SF 2 "general_operand" "rm,G,F,r")))]
  ""
  "@
   fadr %0,%2
   fadri %0,%G2
   fadr %0,[%2]
   fadrm %2,%0")

(define_insn "*FADRB1"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(plus:SF (match_dup 0) (match_operand:SF 1 "register_operand" "r")))
   (set (match_operand:SF 2 "register_operand" "=1")
	(plus:SF (match_dup 0) (match_dup 1)))]
  ""
  "fadrb %1,%0")
(define_insn "*FADRB2"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(plus:SF (match_operand:SF 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SF 2 "register_operand" "=1")
	(plus:SF (match_dup 1) (match_dup 0)))]
  ""
  "fadrb %1,%0")

(define_expand "adddf3"
  [(set (match_operand:DF 0 "register_operand" "")
	(plus:DF (match_operand:DF 1 "register_operand" "")
		 (match_operand:DF 2 "general_operand" "")))]
  "(TARGET_KI10up && !TARGET_GFLOAT) || (TARGET_KL10up && TARGET_GFLOAT)"
  "")

(define_insn "DFAD"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(plus:DF (match_operand:DF 1 "register_operand" "%0,0")
		 (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KI10up && !TARGET_GFLOAT"
  "@
   dfad %0,%2
   dfad %0,[%2]")

(define_insn "*GFAD"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(plus:DF (match_operand:DF 1 "register_operand" "%0,0")
		 (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "@
   gfad %0,%2
   gfad %0,[%2]")

(define_insn "subsf3"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,r,r,m")
	(minus:SF (match_operand:SF 1 "register_operand" "0,0,0,r")
		  (match_operand:SF 2 "general_operand" "rm,G,F,0")))]
  ""
  "@
   fsbr %0,%2
   fsbri %0,%G2
   fsbr %0,[%2]
   fsbrm %1,%0")

(define_insn "*FSBRB"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(minus:SF (match_operand:SF 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SF 2 "register_operand" "=1")
	(minus:SF (match_dup 1) (match_dup 0)))]
  ""
  "fsbrb %1,%0")

(define_expand "subdf3"
  [(set (match_operand:DF 0 "register_operand" "")
	(minus:DF (match_operand:DF 1 "register_operand" "")
		  (match_operand:DF 2 "general_operand" "")))]
  "TARGET_KI10up"
  "")

(define_insn "*DFSB"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(minus:DF (match_operand:DF 1 "register_operand" "0,0")
		  (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KI10up && !TARGET_GFLOAT"
  "@
   dfsb %0,%2
   dfsb %0,[%2]")

(define_insn "*GFSB"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(minus:DF (match_operand:DF 1 "register_operand" "0,0")
		  (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "@
   gfsb %0,%2
   gfsb %0,[%2]")

(define_insn "abssf2"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,m,m")
	(abs:SF (match_operand:SF 1 "reg_or_mem_operand" "rm,r,0")))]
  ""
  "@
   movm %0,%1
   movmm %1,%0
   movms %0")

(define_insn "*MOVMSsf"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "+rm")
	(abs:SF (match_dup 0)))
   (set (match_operand:SF 1 "register_operand" "=x")
	(abs:SF (match_dup 0)))]
  ""
  "movms %1,%0")

(define_insn "negsf2"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,m,m")
	(neg:SF (match_operand:SF 1 "reg_or_mem_operand" "rm,r,0")))]
  ""
  "@
   movn %0,%1
   movnm %1,%0
   movns %0")

(define_insn "*MOVNS"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=rm")
	(neg:SF (match_dup 0)))
   (set (match_operand:SF 1 "register_operand" "+x")
	(neg:SF (match_dup 0)))]
  ""
  "movns %1,%0")

(define_insn "negdf2"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "=r,m")
	(neg:DF (match_operand:DF 1 "reg_or_mem_operand" "rm,r")))]
  "TARGET_KI10up"
  "@
   dmovn %0,%1
   dmovnm %1,%0")

(define_insn "mulsf3"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,r,r,m")
	(mult:SF (match_operand:SF 1 "reg_or_mem_operand" "%0,0,0,0")
		 (match_operand:SF 2 "general_operand" "rm,G,F,r")))]
  ""
  "@
   fmpr %0,%2
   fmpri %0,%G2
   fmpr %0,[%2]
   fmprm %2,%0")

(define_insn "*FMPRB1"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(mult:SF (match_dup 0) (match_operand:SF 1 "register_operand" "r")))
   (set (match_operand:SF 2 "register_operand" "=1")
	(mult:SF (match_dup 0) (match_dup 1)))]
  ""
  "fmprb %1,%0")
(define_insn "*FMPRB2"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(mult:SF (match_operand:SF 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SF 2 "register_operand" "=1")
	(mult:SF (match_dup 1) (match_dup 0)))]
  ""
  "fmprb %1,%0")

(define_expand "muldf3"
  [(set (match_operand:DF 0 "register_operand" "")
	(mult:DF (match_operand:DF 1 "register_operand" "")
		 (match_operand:DF 2 "general_operand" "")))]
  "TARGET_KI10up"
  "")

(define_insn "*DFMP"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(mult:DF (match_operand:DF 1 "register_operand" "%0,0")
		 (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KI10up && !TARGET_GFLOAT"
  "@
   dfmp %0,%2
   dfmp %0,[%2]")

(define_insn "*GFMP"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(mult:DF (match_operand:DF 1 "register_operand" "%0,0")
		 (match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "@
   gfmp %0,%2
   gfmp %0,[%2]")

(define_insn "divsf3"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,r,r,m")
	(div:SF (match_operand:SF 1 "register_operand" "0,0,0,r")
		(match_operand:SF 2 "general_operand" "rm,G,F,0")))]
  ""
  "@
   fdvr %0,%2
   fdvri %0,%G2
   fdvr %0,[%2]
   fdvrm %1,%0")

(define_insn "*FDVRB2"
  [(set (match_operand:SF 0 "memory_operand" "+m")
	(div:SF (match_operand:SF 1 "register_operand" "r") (match_dup 0)))
   (set (match_operand:SF 2 "register_operand" "=1")
	(div:SF (match_dup 1) (match_dup 0)))]
  ""
  "fdvrb %1,%0")

(define_expand "divdf3"
  [(set (match_operand:DF 0 "register_operand" "")
	(div:DF (match_operand:DF 1 "register_operand" "")
		(match_operand:DF 2 "general_operand" "")))]
  "TARGET_KI10up"
  "")

(define_insn "*DFDV"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(div:DF (match_operand:DF 1 "register_operand" "0,0")
		(match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KI10up && !TARGET_GFLOAT"
  "@
   dfdv %0,%2
   dfdv %0,[%2]")

(define_insn "*GFDV"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(div:DF (match_operand:DF 1 "register_operand" "0,0")
		(match_operand:DF 2 "general_operand" "rm,F")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "@
   gfdv %0,%2
   gfdv %0,[%2]")

(define_insn "sqrtsf2"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(sqrt:SF (match_operand:SF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2"
  "extend %0,[sqrt %1]")

(define_expand "sqrtdf2"
  [(set (match_operand:DF 0 "register_operand" "")
	(sqrt:DF (match_operand:DF 1 "reg_or_mem_operand" "")))]
  "TARGET_XKL2"
  "")

(define_insn "*DSQRT"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(sqrt:DF (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[dsqrt %1]")

(define_insn "*GSQRT"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(sqrt:DF (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && TARGET_GFLOAT"
  "extend %0,[gsqrt %1]")

(define_insn "FSC"
  [(set (match_operand:SF 0 "register_operand" "=r,r")
	(unspec:SF
	 [(match_operand:SF 1 "register_operand" "0,0")
	  (match_operand:SI 2 "nonmemory_operand" "K,x")]
	 UNSPEC_FSC))]
  ""
  "@
   fsc %0,%2
   fsc %0,(%2)")

(define_expand "DFSC"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(unspec:DF
	 [(match_operand:DF 1 "register_operand" "0,0")
	  (match_operand:SI 2 "nonmemory_operand" "K,r")]
	 UNSPEC_FSC))]
  "!TARGET_GFLOAT"
  "if (!TARGET_XKL2)
     {
       rtx x = gen_rtx_REG (SFmode, REGNO (operands[0]));
       emit_insn (gen_DFAD (operands[0], operands[1], CONST0_RTX (DFmode)));
       emit_insn (gen_FSC (x, x, operands[2]));
       DONE;
     }")

(define_insn "*DFSC"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(unspec:DF
	 [(match_operand:DF 1 "register_operand" "0,0")
	  (match_operand:SI 2 "nonmemory_operand" "K,x")]
	 UNSPEC_FSC))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "@
   extend %0,[dfsc %2]
   extend %0,[dfsc (%2)]")

(define_insn "GFSC"
  [(set (match_operand:DF 0 "register_operand" "=r,r")
	(unspec:DF
	 [(match_operand:DF 1 "register_operand" "0,0")
	  (match_operand:SI 2 "nonmemory_operand" "K,x")]
	 UNSPEC_FSC))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "@
   extend %0,[gfsc %2]
   extend %0,[gfsc (%2)]")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;   Floating-point Conversions

(define_expand "fix_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "")
	(fix:SI (match_operand:SF 1 "reg_or_mem_operand" "")))]
  ""
  "if (!TARGET_KI10up)
     {
       rtx temp = gen_reg_rtx (DImode);
       rtx temp0 = gen_rtx_SUBREG (SImode, temp, 0);
       rtx temp1 = gen_rtx_SUBREG (SImode, temp, 4);

       /* Sequence taken from KCC.  */
       emit_insn (gen_MUL (temp,
			   gen_rtx_SUBREG (SImode, operands[1], 0),
			   GEN_INT (0400)));
       emit_insn (gen_TSC (temp0, temp0));
       /*emit_insn (gen_ashrsi3 (operands[0], temp1,
			     gen_rtx_PLUS (SImode, temp0, GEN_INT (-0243))));*/
       emit_insn
	 (gen_rtx_SET
	    (VOIDmode,
	     operands[0],
	     gen_rtx_ASHIFTRT
	       (SImode,
		temp0,
		gen_rtx_NEG
		  (SImode,
		   gen_rtx_PLUS
		     (SImode,
		      temp1,
		      GEN_INT (-0243))))));
					     
       DONE;
     }")

(define_insn "*fix_truncsfsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(fix:SI (match_operand:SF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KI10up"
  "fix %0,%1")

; (define_insn "fix_truncsfdi2" ...)

(define_expand "fix_truncdfsi2"
  [(set (match_operand:SI 0 "register_operand" "")
	(fix:SI (match_operand:DF 1 "reg_or_mem_operand" "")))]
  "(TARGET_KL10up && TARGET_GFLOAT) || (TARGET_XKL2 && !TARGET_GFLOAT)"
  "")

(define_insn "*DFIX"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(fix:SI (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[dfix %1]")

(define_insn "*GFIX"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(fix:SI (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[gfix %1]")

(define_expand "fix_truncdfdi2"
  [(set (match_operand:DI 0 "register_operand" "")
	(fix:DI (match_operand:DF 1 "reg_or_mem_operand" "")))]
  "(TARGET_KL10up && TARGET_GFLOAT) || (TARGET_XKL2 && !TARGET_GFLOAT)"
  "")

(define_insn "*DDFIX"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(fix:DI (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[ddfix %1]")

(define_insn "*GDFIX"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(fix:DI (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[gdfix %1]")

(define_insn "floatunsqisf2"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(unsigned_float:SF (match_operand:QI 1 "register_operand" "0")))]
  ""
  "fsc %0,233")

(define_insn "floatunshisf2"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(unsigned_float:SF (match_operand:HI 1 "register_operand" "0")))]
  ""
  "fsc %0,233")

(define_insn "floatsisf2"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(float:SF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KI10up"
  "fltr %0,%1")

(define_insn "floatunssisf2"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(unsigned_float:SF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KI10up"
  {
    if (TARGET_XKL2)
      return "ufltr %0,%1";
    else
      /* Sequence taken from KCC.  */
      return "skipge %0,%1\;%_lsh %0,1\;fltr %0,%0\;skipge %@%1\;%_fsc %0,1";
  }
  [(set (attr "length")
	(if_then_else (ne (symbol_ref "TARGET_XKL2") (const_int 0))
		      (const_int 1)
		      (const_int 5)))])

; (define_insn "floatdisf2" ...)

(define_insn "floatunsqidf2"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(unsigned_float:DF (match_operand:QI 1 "register_operand" "0")))]
  "!TARGET_GFLOAT"
  "fsc %0,233\;movei %Z0,0"
  [(set_attr "length" "2")])

(define_insn "floatunshidf2"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(unsigned_float:DF (match_operand:HI 1 "register_operand" "0")))]
  "!TARGET_GFLOAT"
  "fsc %0,233\;movei %Z0,0"
  [(set_attr "length" "2")])

(define_expand "floatsidf2"
  [(set (match_operand:DF 0 "register_operand" "")
	(float:DF (match_operand:SI 1 "reg_or_mem_operand" "")))]
  "TARGET_KL10up || (TARGET_KI10 && !TARGET_GFLOAT)"
  "if (TARGET_KI10up && !TARGET_XKL2 && !TARGET_GFLOAT)
     {
       rtx temp = gen_rtx_SUBREG (DImode, operands[0], 0);
       rtx temp0 = gen_rtx_SUBREG (SImode, operands[0], 0);
       rtx temp1 = gen_rtx_SUBREG (SImode, operands[0], 4);

       /* Sequence taken from KCC.  */
       emit_move_insn (temp0, operands[1]);
       emit_move_insn (temp1, const0_rtx);
       emit_insn (gen_ASHC_right (temp, temp, GEN_INT (8)));
       emit_insn (gen_xorsi3 (temp0, temp0,
			      GEN_INT ((HOST_WIDE_INT)0243 << 27)));
       if (!flag_unsafe_math_optimizations)
	 emit_insn (gen_adddf3 (operands[0], operands[0],
				CONST0_RTX (DFmode)));
       DONE;
     }")

(define_insn "*DFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(float:DF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[dfltr %1]")

(define_insn "*GFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(float:DF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[gfltr %1]")

(define_expand "floatunssidf2"
  [(set (match_operand:DF 0 "register_operand" "")
	(unsigned_float:DF (match_operand:SI 1 "reg_or_mem_operand" "")))]
  ""
  "if (!TARGET_XKL2)
     {
       rtx temp = gen_rtx_SUBREG (DImode, operands[0], 0);
       rtx temp0 = gen_rtx_SUBREG (SImode, operands[0], 0);
       rtx temp1 = gen_rtx_SUBREG (SImode, operands[0], 4);

       /* Sequence taken from KCC.  */
       emit_move_insn (temp0, operands[1]);
       emit_move_insn (temp1, const0_rtx);
       emit_insn (gen_lshrdi3 (temp, temp, GEN_INT (9)));
       emit_insn (gen_lshrsi3 (temp1, temp1, GEN_INT (1)));
       emit_insn (gen_xorsi3 (temp0, temp0,
			      TARGET_GFLOAT
			      ? GEN_INT ((HOST_WIDE_INT)02743 << 24)
			      : GEN_INT ((HOST_WIDE_INT)0243 << 27)));
       if (!flag_unsafe_math_optimizations)
	 emit_insn (gen_adddf3 (operands[0], operands[0],
				CONST0_RTX (DFmode)));
       DONE;
     }")

(define_insn "*UDFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(unsigned_float:DF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[udfltr %1]")

(define_insn "*UGFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(unsigned_float:DF (match_operand:SI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && TARGET_GFLOAT"
  "extend %0,[ugfltr %1]")

(define_expand "floatdidf2"
  [(set (match_operand:DF 0 "register_operand" "")
	(float:DF (match_operand:DI 1 "reg_or_mem_operand" "")))]
  "(TARGET_KL10up && TARGET_GFLOAT) || (TARGET_XKL2 && !TARGET_GFLOAT)"
  "")

(define_insn "*DDFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(float:DF (match_operand:DI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_XKL2 && !TARGET_GFLOAT"
  "extend %0,[ddfltr %1]")

(define_insn "*DGFLTR"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(float:DF (match_operand:DI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[dgfltr %1]")

(define_expand "extendsfdf2"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "")
	(float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "")))]
  "!TARGET_GFLOAT || TARGET_KL10up"
  "")

;; Extend to D-float by moving the high-order word (if necessary) and
;; zeroing the low-order word.
(define_insn "*extendsfdf2"
  [(set (match_operand:DF 0 "reg_or_mem_operand" "=r,o,r,o")
	(float_extend:DF
	 (match_operand:SF 1 "reg_or_mem_operand" "0,0,rm,r")))]
  "!TARGET_GFLOAT"
  "@
   movei %Z0,0%; extendsfdf2
   setzm %Z0%; extendsfdf2
   move %0,%1%; extendsfdf2\;movei %Z0,0%; extendsfdf2
   movem %1,%0%; extendsfdf2\;setzm %Z0%; extendsfdf2"
  [(set (attr "length")
	(if_then_else (eq_attr "alternative" "0,1")
		      (const_int 1)
		      (const_int 2)))])

(define_insn "*GSNGL"
  [(set (match_operand:DF 0 "register_operand" "=r")
	(float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[gsngl %1]")

(define_expand "truncdfsf2"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "")
	(float_truncate:SF (match_operand:DF 1 "reg_or_mem_operand" "")))]
  "!TARGET_GFLOAT || TARGET_KL10up"
  "")

;; Truncate from D-float by just dropping the low-order word.
;; FIXME: this is not good enough, rounding needed.  Or is it??
(define_insn "*truncdfsf2"
  [(set (match_operand:SF 0 "reg_or_mem_operand" "=r,m,r,m")
	(float_truncate:SF
	 (match_operand:DF 1 "reg_or_mem_operand" "0,0,rm,r")))]
  "!TARGET_GFLOAT"
  "@
   \\t%; truncdfsf2
   \\t%; truncdfsf2
   move %0,%1%; truncdfsf2
   movem %1,%0%; truncdfsf2"
  [(set (attr "length")
	(if_then_else (eq_attr "alternative" "0,1") 
		      (const_int 0)
		      (const_int 1)))])

(define_insn "*GDBLE"
  [(set (match_operand:SF 0 "register_operand" "=r")
	(float_truncate:SF (match_operand:DF 1 "reg_or_mem_operand" "rm")))]
  "TARGET_KL10up && TARGET_GFLOAT"
  "extend %0,[gdble %1]")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pointer Arithmetic

(define_insn "*ADJBP_0"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm,r,m")
	(unspec:SI
	 [(match_operand:SI 1 "reg_or_mem_operand" "0,rm,r")
	  (const_int 0)]
	 UNSPEC_ADJBP))]
  ""
  "@
   %; nothing
   move %0,%1
   movem %1,%0"
  [(set_attr "length" "0,1,1")])

(define_insn "IBP"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(unspec:SI
	 [(match_operand:SI 1 "reg_or_mem_operand" "0")
	  (const_int 1)]
	 UNSPEC_ADJBP))]
  "!TARGET_KL10up"
  "ibp %0"
  [(set_attr "reorg_type" "ibp")])

(define_insn "ADJBP"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm,x,x")
	(unspec:SI
	 [(match_operand:SI 1 "general_operand" "0,rm,i")
	  (match_operand:SI 2 "general_operand" "Q,0,0")]
	 UNSPEC_ADJBP))]
  "TARGET_KL10up"
  "@
   ibp %0
   adjbp %0,%1
   adjbp %0,[%1]"
  [(set_attr "reorg_type" "ibp,none,none")])

(define_insn "MOVEI"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "address_operand" "p")]
		    UNSPEC_ADDRESS))]
  ""
  {
    if (TARGET_EXTENDED)
      {
	/* ADDRESS: ... */
        if (GET_CODE (operands[1]) == CONST_INT
	    && !pdp10_const_ok_for_letter_p (INTVAL (operands[1]), 'I'))
	  return "move %0,[%1]";
	else
          return "xmovei %0,%a1";
      }
    else
      return "movei %0,%a1";
  })

(define_insn "MOVSI"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(ashift:SI (unspec:SI [(match_operand:SI 1 "address_operand" "r,p")]
			      UNSPEC_ADDRESS)
		   (const_int 18)))]
  ""
  "@
   movs %0,%1
   movsi %0,%a1")

(define_insn "HRRI"
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r")
			 (const_int 18)
			 (const_int 18))
	(unspec:SI [(match_operand:SI 1 "address_operand" "r,p")]
		   UNSPEC_ADDRESS))]
  ""
  "@
   hrr %0,%1
   hrri %0,%a1")

(define_insn "HRLI"
  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r")
			 (const_int 18)
			 (const_int 0))
	(unspec:SI [(match_operand:SI 1 "address_operand" "r,p")]
		   UNSPEC_ADDRESS))]
  ""
  "@
   hrl %0,%1
   hrli %0,%a1")

(define_insn "ADDI"
  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
	(unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0,0,0,0")
			     (match_operand:SI 2 "address_operand" "r,I,i,p"))]
		   UNSPEC_ADDRESS))]
  ""
  "@
   add %0,%2
   addi %0,%2
   add %0,[%2]
   addi %0,%a2")

(define_insn "ashrsi3_pointer"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "immediate_operand" "K")]
		   UNSPEC_SHIFTRT))]
  ""
  "ash %0,%N2%; ashrsi3_pointer")

(define_insn "ashlsi3_pointer"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "immediate_operand" "K")]
		   UNSPEC_SHIFT))]
  ""
  "ash %0,%2%; ashlsi3_pointer")

(define_insn "SUBBP"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "reg_or_mem_operand" "rm")]
		   UNSPEC_SUBBP))]
  "TARGET_XKL2"
  "extend %0,[subbp %2]")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Unconditional Jumps

(define_insn "nop"
  [(const_int 0)]
  ""
  ;; TODO: this is the traditional NOP instruction.  On KL10, TRN is
  ;; faster.
  "jfcl%; nop")

(define_insn "jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  ""
  {
    return pdp10_output_jrst (insn, operands[0]);
  })

(define_expand "indirect_jump"
  [(set (pc)
	(match_operand:SI 0 "general_operand" ""))]
  ""
  "/* Strip off any byte pointer fields, leaving only the word address.
      TODO: do this earlier, before conversion to 'void *'?  */
   if (GET_CODE (operands[0]) == CONST_INT)
     {
       HOST_WIDE_INT address = INTVAL (operands[0]);
       address &= TARGET_EXTENDED ? 07777777777 : 0777777;
       operands[0] = GEN_INT (address);
     }
   else if (GET_CODE (operands[0]) == CONST
	    && GET_CODE (XEXP (operands[0], 0)) == PLUS
	    && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == SYMBOL_REF
	    && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
     {
       HOST_WIDE_INT offset = INTVAL (XEXP (XEXP (operands[0], 0), 1));
       offset &= TARGET_EXTENDED ? 07777777777 : 0777777;
       operands[0] = plus_constant (XEXP (XEXP (operands[0], 0), 0), offset);
     }")

(define_insn "*indirect_jump"
  [(set (pc)
	;; ADDRESS: the S constraint allows a symbol.
	(match_operand:SI 0 "general_operand" "x,IS,i,rm"))]
  ""
  "@
   jrst (%0)
   jrst %0
   jrst @[%0]
   jrst @%0")

(define_expand "call"
  [(call (match_operand 0 "memory_operand" "")
	 (match_operand 1 "general_operand" ""))]
  ""
  "")

(define_insn "*call_reg"
  [(call (mem:SI (match_operand:SI 0 "register_operand" "x"))
         (match_operand 1 "" "g"))]
  ""
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst (%0)";
    else
      return "pushj 17,(%0)";
  })

(define_insn "*call_mem1"
  [(call (mem:SI (match_operand:SI 0 "memory_operand" "o"))
	 (match_operand:SI 1 "general_operand" "g"))]
  ""
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst @%0";
    else
      return "pushj 17,@%0";
  })

(define_insn "*call_mem2"
  [(call (mem:SI (match_operand 0 "immediate_operand" "i"))
	 (match_operand 1 "general_operand" "g"))]
  "GET_CODE (operands[0]) != SYMBOL_REF"
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst %a0";
    else
      return "pushj 17,%a0";
  })

(define_insn "*call_symbol"
  [(call (mem:SI (match_operand:SI 0 "" "X"))
	 (match_operand:SI 1 "general_operand" "g"))]
  "GET_CODE (operands[0]) == SYMBOL_REF"
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst %L0";
    else
      return "pushj 17,%L0";
  })

(define_expand "call_value"
  [(set (match_operand 0 "" "")
	(call (match_operand 1 "memory_operand" "")
	      (match_operand 2 "general_operand" "")))]
  ""
  "")

(define_insn "*call_value_reg"
  [(set (match_operand 0 "" "=r")
        (call (mem:SI (match_operand:SI 1 "register_operand" "x"))
	      (match_operand:SI 2 "general_operand" "g")))]
  ""
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst (%1)";
    else
      return "pushj 17,(%1)";
  })

(define_insn "*call_value_mem1"
  [(set (match_operand 0 "" "=r")
	(call (mem:SI (match_operand 1 "memory_operand" "o"))
	      (match_operand 2 "general_operand" "g")))]
  "CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst @%1";
    else
      return "pushj 17,@%1";
  })

(define_insn "*call_value_mem2"
  [(set (match_operand 0 "register_operand" "=r")
	(call (mem:SI (match_operand 1 "immediate_operand" "i"))
	      (match_operand 2 "general_operand" "g")))]
  "GET_CODE (operands[1]) != SYMBOL_REF"
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst %a1";
    else
      return "pushj 17,%a1";
  })

(define_insn "*call_value_mem3"
  [(set (match_operand 0 "register_operand" "=r")
	(call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
	      (match_operand:SI 2 "general_operand" "g")))]
  ""
  {
    operands[1] = gen_rtx_MEM (SImode, operands[1]);
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst %1";
    else
      return "pushj 17,%1";
  })

(define_insn "*call_value_symbol"
  [(set (match_operand 0 "register_operand" "=r")
	(call (mem:SI (match_operand:SI 1 "" "X"))
	      (match_operand:SI 2 "general_operand" "g")))]
  "GET_CODE (operands[1]) == SYMBOL_REF"
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst %L1";
    else if (pdp10_output_call_as_jsp_p (operands[1]))
      return "jsp ?,%L1";
    else
      return "pushj 17,%L1";
  })

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

     emit_call_insn (gen_call (operands[0], const0_rtx));

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

     /* The optimizer does not know that the call sets the function value
	registers we stored in the result block.  We avoid problems by
	claiming that all hard registers are used and clobbered at this
	point.  */
     emit_insn (gen_blockage ());
 
     DONE;
   }")

(define_insn "*PUSHJ"
  [(parallel
    [(call (match_operand:SI 0 "memory_operand" "m")
	   (match_operand:SI 1 "" ""))
     (use (match_operand:SI 2 "register_operand" "+r"))])]
  ""
  "pushj %2,%0")

; (define_insn "trap"
;   [(trap_if (const_int 1) (const_int 0))]
;   ""
;   "<trap 0>%; trap")

(define_expand "casesi"
  [(set (match_dup 5)
	(minus:SI (match_operand:SI 0 "register_operand" "")
		  (match_operand:SI 1 "general_operand" "")))
   (set (pc)
        (if_then_else (lt (match_dup 5) (const_int 0))
		      (label_ref (match_operand 4 "" ""))
		      (pc)))
   (set (pc)
        (if_then_else (gt (match_dup 5)
			  (match_operand:SI 2 "general_operand" ""))
		      (label_ref (match_dup 4))
		      (pc)))
;;; This is too general.  The jump table label will always be local.
;;; Unless TARGET_HUGE?
;  (set (match_dup 6)
;	(plus:SI (match_dup 5) (label_ref (match_operand 3 "" ""))))
;  (parallel [(set (pc) (if_then_else (const_int 1)
;				      (mem:SI (match_dup 6))
;				      (label_ref (match_dup 4))))
;	      (use (label_ref (match_dup 3)))])]
   (parallel [(set (pc)
		   (if_then_else
		    (const_int 1)
		    (mem:SI (plus:SI (match_dup 5)
				     (label_ref (match_operand 3 "" ""))))
		    (label_ref (match_dup 4))))
	      (use (label_ref (match_dup 3)))])]
  ""
  "operands[5] = gen_reg_rtx (SImode);
   /*operands[6] = gen_reg_rtx (SImode);*/")

;; This is the bare minimum of how an acceptable casesi dispatch
;; instruction must look like.
(define_insn ""
  [(parallel [(set (pc)
		   (if_then_else (const_int 1)
				 (match_operand:SI 0 "address_operand" "p")
				 (label_ref (match_operand 1 "" ""))))
	      (use (label_ref (match_operand 2 "" "")))])]
  ""
  "jrst %a0")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Conditional Jumps

(define_expand "cmpsi"
  [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
                       (match_operand:SI 1 "general_operand" "")))]
  ""
  "pdp10_compare_op0 = operands[0];
   pdp10_compare_op1 = operands[1];
   DONE;")

(define_expand "cmpsf"
  [(set (cc0) (compare (match_operand:SF 0 "register_operand" "")
                       (match_operand:SF 1 "general_operand" "")))]
  ""
  "pdp10_compare_op0 = operands[0];
   pdp10_compare_op1 = operands[1];
   DONE;")

(define_expand "cmpdf"
  [(set (cc0) (compare (match_operand:DF 0 "register_operand" "")
                       (match_operand:DF 1 "general_operand" "")))]
  ""
  "if (pdp10_const_double_0_operand (operands[1], DFmode))
     pdp10_compare_op0 = operands[0];
   else
     {
       pdp10_compare_op0 = gen_reg_rtx (DFmode);
       gen_subdf3 (pdp10_compare_op0, operands[0], operands[1]);
     }
   pdp10_compare_op1 = CONST0_RTX (DFmode);
   DONE;")

(define_insn "test_and_skip"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "pdp10_equality_operator"
	  [(and:SI (match_operand:SI 1 "register_operand" "r")
		   (match_operand:SI 2 "general_operand" "g"))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
  ""
  "*pdp10_remove_unnecessary_label (insn, operands[3]);
    return pdp10_output_test_and_skip (insn, operands);"
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 3) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

;; Equality comparisons of a contigous group of bits with zero will be
;; written using zero_extract rather than the equivalent AND operations.
(define_insn "test_extract_skip"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "pdp10_equality_operator"
	  [(zero_extract:SI
	    (match_operand:SI 1 "register_operand" "r")
	    (match_operand:SI 2 "const_int_operand" "")
	    (match_operand:SI 3 "const_int_operand" ""))
	   (const_int 0)])
	 (label_ref (match_operand 4 "" ""))
	 (pc)))]
  ""
  {
    int len = INTVAL (operands[2]), pos = INTVAL (operands[3]);
    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1 << len) - 1) << (36 - pos - 1);
    /* Must assign operands[2] and operands[3], since
       pdp10_output_test_and_skip use those to output the
       instruction.  */
    operands[2] = gen_int_mode (mask, SImode);
    operands[3] = operands[4];
    pdp10_remove_unnecessary_label (insn, operands[3]);
    return pdp10_output_test_and_skip (insn, operands);
  }
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 4) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

(define_insn "TLZN"
  [(set (pc)
	(if_then_else
	 (ne (and:SI (match_operand:SI 0 "register_operand" "+r")
		     (match_operand:SI 1 "const_int_operand" ""))
	     (const_int 0))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   (set (match_dup 0) (and:SI (match_dup 0) (not:SI (match_dup 1))))]
  ""
  {
    pdp10_remove_unnecessary_label (insn, operands[2]);
    if (get_attr_length (insn) == 1)
      return "tlzn %0,%1";
    else
      return "tlze %0,%1\;jump %2";
  }
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 2) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

(define_insn "TLNE_TLZA_TLO"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_dup 0)
		    (match_operand:SI 1 "const_int_operand" "")
		    (match_operand:SI 2 "const_int_operand" "")
		    (match_operand:SI 3 "const_int_operand" "")]
		   UNSPEC_TLNE_TLZA_TLO))]
  ""
  "tlne %0,%1\;%_tlza %0,%2\;%_%_tlo %0,%3"
  [(set_attr "length" "3")])

(define_expand "bne"
  [(set (pc)
	(if_then_else (ne (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "beq"
  [(set (pc)
	(if_then_else (eq (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "bge"
  [(set (pc)
	(if_then_else (ge (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "bgt"
  [(set (pc)
	(if_then_else (gt (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "ble"
  [(set (pc)
	(if_then_else (le (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "blt"
  [(set (pc)
	(if_then_else (lt (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_compare_op0;
   operands[2] = pdp10_compare_op1;")

(define_expand "bgeu"
  [(set (pc)
	(if_then_else (ge (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "bgtu"
  [(set (pc)
	(if_then_else (gt (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "bleu"
  [(set (pc)
	(if_then_else (le (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

(define_expand "bltu"
  [(set (pc)
	(if_then_else (lt (match_dup 1) (match_dup 2))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "operands[1] = pdp10_flip_sign_bit (pdp10_compare_op0);
   operands[2] = pdp10_flip_sign_bit (pdp10_compare_op1);")

; (define_insn "cbranchsi4" ...)

(define_insn "cbranchsi"
  [(set (pc)
	(if_then_else (match_operator 3 "comparison_operator"
		       [(match_operand:SI 1 "reg_or_mem_operand" "r,m,r,r,r")
		        ;; ADDRESS: an S constraint for the cai case
		        ;; (alternative 2) would allow a symbol.
		        (match_operand:SI 2 "general_operand" "O,O,I,i,rm")])
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  {
    static const char *asms[] =
    { "jump%3 %1,%l0",
      "skip%3 %@%1",
      "cai%3 %1,%2",
      "cam%3 %1,[%X2]",
      "cam%3 %1,%2" };
    if (which_alternative != 0)
      pdp10_remove_unnecessary_label (insn, operands[0]);
    /* ADDRESS: unextended code can store the symbol in the immediate
       field.  */
    if (which_alternative == 3 && !TARGET_EXTENDED
	&& GET_CODE (operands[2]) == CONST)
      which_alternative = 2;
    if (get_attr_length (insn) == 1)
      return asms[which_alternative];
    else
      {
	/* Reverse the skip condition and output a JRST.  */
	operands[3] = gen_rtx_fmt_ee (reverse_condition
				      (GET_CODE (operands[3])),
				      VOIDmode, NULL_RTX, NULL_RTX);
	output_asm_insn (asms[which_alternative], operands);
	return pdp10_output_jrst (insn, operands[0]);
      }
  }
  [(set (attr "length")
	(if_then_else (ior (eq_attr "alternative" "0")
			   (eq (minus (match_dup 0) (pc)) (const_int 1)))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "no,yes,yes,yes,yes")])

(define_insn "*cbranchsf"
  [(set (pc)
	(if_then_else (match_operator 3 "pdp10_comparison_operator"
		       [(match_operand:SF 1 "reg_or_mem_operand" "r,m,r,r,r")
		        (match_operand:SF 2 "general_operand" "O,O,I,i,rm")])
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  {
    /* TODO: Copy from cbranchsi.  Maybe create an output function for
       both?  */
    const char *asms[][2] =
    { { "jump%3 %1,%l0",	0 },
      { "skip%3 %@%1",		"skip%R3 %@%1\;jrst %l0" },
      { "cai%3 %1,%2",		"cai%R3 %1,%2\;jrst %l0" },
      { "cam%3 %1,[%2]",	"cam%R3 %1,[%2]\;jrst %l0" },
      { "cam%3 %1,%2",		"cam%R3 %1,%2\;jrst %l0" } };
    if (which_alternative != 0)
      pdp10_remove_unnecessary_label (insn, operands[0]);
    return asms[which_alternative][get_attr_length (insn) - 1];
  }
  [(set (attr "length")
	(if_then_else (ior (eq_attr "alternative" "0")
			   (eq (minus (match_dup 0) (pc)) (const_int 1)))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "no,yes,yes,yes,yes")])

(define_insn "*cbranchdf"
  [(set (pc)
	(if_then_else
	 (match_operator 3 "pdp10_comparison_operator"
          [(match_operand:DF 1 "reg_or_mem_operand" "r,m")
	   (match_operand:DF 2 "pdp10_const_double_0_operand" "")])
	 (label_ref (match_operand 0 "" ""))
	 (pc)))]
  ""
  {
    if (which_alternative == 0)
      return "jump%3 %1,%l0";
    pdp10_remove_unnecessary_label (insn, operands[0]);
    if (get_attr_length (insn) == 1)
      return "skip%3 %@%1";
    else
      {
	output_asm_insn ("skip%R3 %@%1", operands);
	return pdp10_output_jrst (insn, operands[0]);
      }
  }
  [(set (attr "length")
	(if_then_else (ior (eq_attr "alternative" "0")
			   (eq (minus (match_dup 0) (pc)) (const_int 1)))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "no,yes")])

(define_insn "doloop_end"
  [(set (pc)
	(if_then_else
	 (ge (plus:SI (match_operand:SI 0 "reg_or_mem_operand" "+r")
		      (const_int -1))
	     (const_int 0))
	 (label_ref (match_operand 4 "" ""))
	 (pc)))
   (set (match_dup 0)
	(plus:SI (match_dup 0) (const_int -1)))
   (use (match_operand 1 "" ""))	; iterations; zero if unknown
   (use (match_operand 2 "" ""))	; max iterations
   (use (match_operand 3 "" ""))]	; loop level
  ""
  "sojge %0,%l4%; doloop_end")

(define_insn "decrement_and_branch_until_zero"
  [(set (pc)
	(if_then_else
	 (match_operator 2 "pdp10_comparison_operator"
	  [(plus:SI (match_operand:SI 0 "reg_or_mem_operand" "+r,m")
		    (const_int -1))
	   (const_int 0)])
	 (label_ref (match_operand 1 "" ""))
	 (pc)))
   (set (match_dup 0)
	(plus:SI (match_dup 0) (const_int -1)))]
  ""
  {
    if (which_alternative == 0)
      return "soj%2 %0,%l1%; decrement_and_branch_until_zero";
    pdp10_remove_unnecessary_label (insn, operands[1]);
    if (get_attr_length (insn) == 1)
      return "sos%2 %@%0%; decrement_and_branch_until_zero";
    else
      {
	output_asm_insn ("sos%R2 %@%0%; decrement_and_branch_until_zero",
			 operands);
	return pdp10_output_jrst (insn, operands[1]);
      }
  }
  [(set (attr "length")
	(if_then_else (ior (eq_attr "alternative" "0")
			   (eq (minus (match_dup 1) (pc)) (const_int 1)))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "no,yes")])

(define_insn "*AOJ"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "pdp10_comparison_operator"
	  [(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "+r,m")
		    (const_int 1))
	   (const_int 0)])
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   (set (match_dup 1)
	(plus:SI (match_dup 1) (const_int 1)))]
  ""
  {
    if (which_alternative == 0)
      return "aoj%0 %1,%l2";
    pdp10_remove_unnecessary_label (insn, operands[2]);
    if (get_attr_length (insn) == 1)
      return "aos%0 %@%1";
    else
      {
	output_asm_insn ("aos%R0 %@%1", operands);
	return pdp10_output_jrst (insn, operands[2]);
      }
  }
  [(set (attr "length")
	(if_then_else (ior (eq_attr "alternative" "0")
			   (eq (minus (match_dup 2) (pc)) (const_int 1)))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "no,yes")])

(define_insn "*SOJA"
  [(set (pc)
	(label_ref (match_operand 2 "" "")))
   (set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (match_operand:SI 1 "register_operand" "0")
		 (const_int -1)))]
  ""
  {
    rtx next = next_nonnote_insn (insn);
    if (next == operands[2]
	|| (GET_CODE (next) == BARRIER
	    && next_nonnote_insn (next) == operands[2]))
      {
	pdp10_remove_unnecessary_label (insn, operands[1]);
	return "subi %0,1";
      }
    else
      return "soja %0,%l2";
  })

(define_insn "*AOJA"
  [(set (pc)
	(label_ref (match_operand 2 "" "")))
   (set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (match_operand:SI 1 "register_operand" "0")
		 (const_int 1)))]
  ""
  {
    rtx next = next_nonnote_insn (insn);
    if (next == operands[2]
	|| (GET_CODE (next) == BARRIER
	    && next_nonnote_insn (next) == operands[2]))
      {
	pdp10_remove_unnecessary_label (insn, operands[1]);
	return "addi %0,1";
      }
    else
      return "aoja %0,%l2";
  })

(define_insn "*SOSx_and_move"
  [(set (pc)
	(if_then_else
	 (match_operator 2 "pdp10_comparison_operator"
	  [(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "+rm")
		    (const_int -1))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (set (match_dup 1)
	(plus:SI (match_dup 1) (const_int -1)))
   (set (match_operand:SI 0 "register_operand" "=x")
	(plus:SI (match_dup 1) (const_int -1)))]
  ""
  {
    pdp10_remove_unnecessary_label (insn, operands[3]);
    if (get_attr_length (insn) == 1)
      return "sos%2 %0,%1";
    else
      {
	output_asm_insn ("sos%R2 %0,%1", operands);
	return pdp10_output_jrst (insn, operands[3]);
      }
  }
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 3) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

(define_insn "*AOSx_and_move"
  [(set (pc)
	(if_then_else
	 (match_operator 2 "pdp10_comparison_operator"
	  [(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "+rm")
		    (const_int 1))
	   (const_int 0)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))
   (set (match_dup 1)
	(plus:SI (match_dup 1) (const_int 1)))
   (set (match_operand:SI 0 "register_operand" "=x")
	(plus:SI (match_dup 1) (const_int 1)))]
  ""
  {
    pdp10_remove_unnecessary_label (insn, operands[3]);
    if (get_attr_length (insn) == 1)
      return "aos%2 %0,%1";
    else
      {
	output_asm_insn ("aos%R2 %0,%1", operands);
	return pdp10_output_jrst (insn, operands[3]);
      }
  }
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 3) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

(define_insn "JFFO"
  [(set (pc)
	(if_then_else (ne (subreg:SI
			   (match_operand:DI 0 "register_operand" "+r") 0)
			  (const_int 0))
		      (match_operand 1 "address_operand" "")
		      (pc)))
   (set (subreg:SI (match_dup 0) 4)
	(unspec:SI [(subreg:SI (match_dup 0) 0)] UNSPEC_FFO))]
  "TARGET_KA10up"
  {
    if (GET_CODE (operands[1]) == LABEL_REF)
      return "jffo %0,%l1";
    else
      return "jffo %0,%1";
  })

(define_insn "CMPBP"
  [(set (pc)
	(if_then_else
	 (match_operator 0 "comparison_operator"
	  [(unspec:SI
	    [(match_operand:SI 1 "register_operand" "r")] UNSPEC_CMPBP)
	   (unspec:SI
	    [(match_operand:SI 2 "reg_or_mem_operand" "rm")] UNSPEC_CMPBP)])
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
  "TARGET_XKL2"
  {
    pdp10_remove_unnecessary_label (insn, operands[3]);
    if (get_attr_length (insn) == 1)
      return "extend %1,[cmpbp%0 %2]";
    else
      return "extend %1,[cmpbp%C0 %2]\;jump %3";
  }
  [(set (attr "length")
	(if_then_else (eq (minus (match_dup 3) (pc)) (const_int 1))
		      (const_int 1)
		      (const_int 2)))
   (set_attr "skip" "yes")])

; (define_expand "conditional_trap"
;   [(trap_if (match_operator 0 "pdp10_comparison_operator" 
;              [(match_dup 2) (const_int 0)])
;             (match_operand 1 "const_int_operand" ""))]
;   ""
;   "operands[2] = pdp10_compare_op0;")

; (define_insn "*trap"
;   [(trap_if (match_operator 0 "pdp10_comparison_operator" 
;              [(match_operand 2 "memory_operand" "m") (const_int 0)])
;             (match_operand 1 "const_int_operand" "i"))]
;   ""
;   "skip%R0 %2\;%_<trap %1>%; conditional_trap"
;   [(set_attr "length" "2")])


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Function Prologue and Epilogue

(define_expand "prologue"
  [(const_int 2)]
  ""
  "pdp10_expand_prologue ();
   DONE;")

(define_expand "epilogue"
  [(return)]
  ""
  "pdp10_expand_epilogue (1);
   DONE;")

(define_expand "sibcall_epilogue"
  [(const_int 3)]
  ""
  "pdp10_expand_epilogue (0);
   DONE;")

(define_insn "POPJ"
  [(set (pc) (match_operand:SI 0 "pdp10_pop_operand" ""))]
  ""
  "popj %P0,")

(define_insn "POPJ_17"
  [(return)]
  ""
  {
    return pdp10_output_return ();
  })

(define_expand "allocate_stack"
  [(set (match_operand:SI 0 "register_operand" "")
	(unspec:SI [(plus:SI (reg:SI SP_REGNUM) (const_int 1))]
		   UNSPEC_ADDRESS))
   (set (reg:SI SP_REGNUM)
	(unspec:SI
	 [(reg:SI SP_REGNUM)
	  (match_operand:SI 1 "general_operand" "")]
	 UNSPEC_ADJSP))]
  ""
  "{
     rtx x = plus_constant (stack_pointer_rtx, REAL_UNITS_PER_WORD);
     if (GET_CODE (operands[1]) == CONST_INT)
       operands[1] = GEN_INT (INTVAL (operands[1]) / UNITS_PER_WORD);
     else
       emit_insn (gen_ASH_right (operands[1], operands[1], GEN_INT (-2)));
     emit_move_insn (operands[0],
		     gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_ADDRESS));
     emit_insn (pdp10_gen_stack_adjust (operands[1]));
     DONE;
   }")

(define_expand "ADJSP"
  [(set (match_operand:SI 0 "register_operand" "")
	(unspec:SI [(match_dup 0) (match_operand:SI 1 "general_operand" "")]
		   UNSPEC_ADJSP))]
  ""
  "")

(define_insn "*ADJSP_KL10up"
  [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
	(unspec:SI [(match_dup 0)
		    (match_operand:SI 1 "general_operand" "K,i,x,m")]
		   UNSPEC_ADJSP))]
  "TARGET_KL10up"
  "@
   adjsp %0,%1
   adjsp %0,[%1]
   adjsp %0,(%1)
   adjsp %0,@%1")

(define_insn "*ADJSP_noKL10up"
  [(set (match_operand:SI 0 "register_operand" "+r")
	(unspec:SI [(match_dup 0)
		    (match_operand:SI 1 "immediate_operand" "K")]
		   UNSPEC_ADJSP))]
  "!TARGET_KL10up && !TARGET_EXTENDED"
  "add %0,[%1,,%1]")

(define_insn "PUSH"
  [(set (match_operand:SI 0 "pdp10_push_operand" "=m")
	(match_operand:SI 1 "reg_or_mem_operand" "rm"))]
  ""
  "push %P0,%1")

(define_insn "*pushsi_combine"
  [(parallel
    [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
			   (const_int 1)))
	  ;; FIXME: empty predicate allowed?
	  (match_operand:SI 1 "" "rm"))
     (set (match_operand:SI 2 "register_operand" "=0")
	  (plus:SI (match_dup 0) (const_int 1)))])]
  "optimize_size && TARGET_EXTENDED"
  "push %0,%1")

(define_insn "*pushsf_combine"
  [(parallel
    [(set (mem:SF (plus:SI (match_operand:SI 0 "register_operand" "r")
			   (const_int 1)))
	  (match_operand:SF 1 "reg_or_mem_operand" "rm"))
     (set (match_operand:SI 2 "register_operand" "=0")
	  (plus:SI (match_dup 0) (const_int 1)))])]
  "optimize_size && TARGET_EXTENDED"
  "push %0,%1")

(define_insn "POP"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(match_operand:SI 1 "pdp10_pop_operand" "m"))]
  ""
  "pop %P1,%0")

(define_insn "*popsi_combine"
  [(parallel
    [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
     (set (match_operand:SI 2 "reg_or_mem_operand" "=1")
	  (plus:SI (match_dup 1) (const_int -1)))])]
  "optimize_size && TARGET_EXTENDED"
  "pop %1,%0")

(define_insn "*popsf_combine"
  [(parallel
    [(set (match_operand:SF 0 "reg_or_mem_operand" "=rm")
	  (mem:SF (match_operand:SI 1 "register_operand" "+r")))
     (set (match_dup 1)
	  (plus:SI (match_dup 1) (const_int -1)))])]
  "optimize_size && TARGET_EXTENDED"
  "pop %1,%0")


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Peepholes

;; The following four insns compensate for unnecessary shifts
;; generated by pointer arithmetic.
(define_insn "*combine_nop_shift_left_right"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI
	 [(ashift:SI (match_operand:SI 1 "register_operand" "0")
		     (match_operand:SI 2 "const_int_operand" ""))
	  (match_operand:SI 3 "const_int_operand" "")]
	 UNSPEC_SHIFTRT))]
  "INTVAL (operands[2]) == INTVAL (operands[3])"
  ""
  [(set_attr "length" "0")])
(define_insn "*combine_shift_left_right"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI
	 [(ashift:SI (match_operand:SI 1 "register_operand" "0")
		     (match_operand:SI 2 "const_int_operand" ""))
	  (match_operand:SI 3 "const_int_operand" "")]
	 UNSPEC_SHIFTRT))]
  ""
  {
    operands[2] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[3]));
    return "ash %0,%2";
  })
(define_insn "*combine_nop_shift_right_left"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI
	 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
		     (match_operand:SI 2 "const_int_operand" "")]
		    UNSPEC_SHIFT)
	 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) == INTVAL (operands[3])"
  ""
  [(set_attr "length" "0")])
(define_insn "*combine_shift_right_left"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI
	 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
		     (match_operand:SI 2 "const_int_operand" "")]
		    UNSPEC_SHIFT)
	 (match_operand:SI 3 "const_int_operand" "")))]
  ""
  {
    operands[2] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[3]));
    return "ash %0,%2";
  })

;; Remove unnecessary shifts generated by pointer arithmetic.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(unspec:SI
	 [(truncate:SI
	   (ashift:SI (match_operand:SI 1 "register_operand" "")
		      (match_operand:SI 2 "const_int_operand" "")))
	  (match_operand:SI 3 "const_int_operand" "")]
	 UNSPEC_SHIFTRT))]
  "INTVAL (operands[2]) == INTVAL (operands[3])"
  [(set (match_dup 0) (truncate:SI (match_dup 1)))])
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(ashiftrt:SI
	 (unspec:SI [(match_operand:SI 1 "register_operand" "")
		     (match_operand:SI 2 "const_int_operand" "")]
		    UNSPEC_SHIFT)
	 (match_operand:SI 3 "const_int_operand" "")))]
  "INTVAL (operands[2]) == INTVAL (operands[3])"
  [(set (match_dup 0) (match_dup 1))])

;; Generate EXCH instructions.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(match_operand:SI 1 "reg_or_mem_operand" ""))
   (set (match_dup 1)
	(match_operand:SI 2 "reg_or_mem_operand" ""))
   (set (match_dup 2)
	(match_dup 0))]
  "find_reg_note (next_nonnote_insn (next_nonnote_insn (insn)),
		  REG_DEAD, operands[0])
   && (register_operand (operands[1], SImode)
       || register_operand (operands[2], SImode))"
  [(parallel [(set (match_dup 1) (match_dup 2))
	      (set (match_dup 2) (match_dup 1))])]
  "if (register_operand (operands[1], SImode))
     {
       rtx tmp = operands[1];
       operands[1] = operands[2];
       operands[2] = tmp;
     }")

;; Generate SETZB instructions.
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "") (const_int 0))
   (set (match_operand:SI 1 "reg_or_mem_operand" "") (const_int 0))]
  "register_operand (operands[0], SImode)
   || register_operand (operands[1], SImode)"
  [(parallel [(set (match_dup 0) (const_int 0))
	      (set (match_dup 1) (const_int 0))])]
  "if (register_operand (operands[0], SImode))
     {
       rtx tmp = operands[0];
       operands[0] = operands[1];
       operands[1] = tmp;
     }")

;; Remove an unneccesary MOVEI instruction.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
        (unspec:SI
	 [(plus:SI (match_dup 0) (match_operand 1 "const_int_operand" ""))]
	 UNSPEC_ADDRESS))
   (parallel [(unspec_volatile:BLK
	       [(match_operand:SI 2 "register_operand" "")]
	       VUNSPEC_BLT)
	      (use (mem:BLK (match_dup 0)))])]
  "dead_or_set_p (insn, operands[0])"
  [(parallel [(unspec_volatile:BLK [(match_dup 2)] VUNSPEC_BLT)
	      (use (mem:BLK (plus:SI (match_dup 0) (match_dup 1))))])])

;; Optimize a block-copy operation with constant addresses.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(unspec:SI
	 [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_ADDRESS))
   (set (zero_extract:SI (match_dup 0) (const_int 18) (const_int 0))
	(unspec:SI
	 [(match_operand:SI 2 "immediate_operand" "")] UNSPEC_ADDRESS))]
  ""
  [(set (match_dup 0)
	(ior:SI (ashift:SI (match_dup 2) (const_int 18))
		 (match_dup 1)))])

;; Optimize a block-clear operation with a constant address.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(match_operand:SI 1 "immediate_operand" ""))
   (set (match_operand:SI 2 "register_operand" "")
	(ashift:SI (unspec:SI [(match_dup 0)] UNSPEC_ADDRESS)
		    (const_int 18)))
   (set (zero_extract:SI (match_dup 2) (const_int 18) (const_int 18))
	;; FIXME: (const_int 4) -> (const_int 1)?
	(unspec:SI [(plus:SI (match_dup 0) (const_int 4))] UNSPEC_ADDRESS))]
  "dead_or_set_p (insn, operands[0])"
  [(set (match_dup 2)
	(ior:SI (ashift:SI (match_dup 1) (const_int 18))
		 (const:SI (plus:SI (match_dup 1) (const_int 1)))))])

;; Generate a PUSHJ instruction from an equivalent sequence of
;; instructions.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(label_ref (match_operand 1 "" "")))
   (parallel
    [(set (mem:SI (plus:SI (match_operand:SI 2 "register_operand" "")
			   (const_int 1)))
	  (match_operand:SI 3 "" ""))
     (set (match_dup 2)
	  (plus:SI (match_dup 2) (const_int 1)))])
   (set (pc)
	(match_operand:SI 4 "" ""))]
  ;; TODO: find code_label corresponding to operands[1].
  "0 && TARGET_EXTENDED"
  [(parallel
    [(call (mem:SI (match_dup 4)) (const_int 0))
     (use (match_dup 2))])])

;; Generate a POP instruction from an equivalent sequence of
;; instructions.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(mem:SI (match_operand:SI 1 "register_operand" "")))
   (set (match_operand:SI 2 "reg_or_mem_operand" "")
	(match_dup 0))
   (set (match_dup 1)
	(plus:SI (match_dup 1) (const_int -1)))]
  "optimize_size && TARGET_EXTENDED"
  [(parallel
    [(set (match_dup 2)
	  (mem:SI (match_dup 1)))
     (set (match_dup 1)
	  (plus:SI (match_dup 1) (const_int -1)))])])
(define_peephole2
  [(set (match_operand:SF 0 "register_operand" "")
	(mem:SF (match_operand:SI 1 "register_operand" "")))
   (set (match_operand:SF 2 "reg_or_mem_operand" "")
	(match_dup 0))
   (set (match_dup 1)
	(plus:SI (match_dup 1) (const_int -1)))]
  "optimize_size && TARGET_EXTENDED"
  [(parallel
    [(set (match_dup 2)
	  (mem:SF (match_dup 1)))
     (set (match_dup 1)
	  (plus:SI (match_dup 1) (const_int -1)))])])

;; XMOVEI AC1,OFFSET(17)
;; MOVE AC2,AC1			->	MOVE AC2,OFFSET(17)
;; AC1 is dead
(define_peephole2
  [(set (match_operand:SI 1 "register_operand" "")
        (plus:SI (reg:SI SP_REGNUM)
		 (match_operand:SI 2 "const_int_operand" "")))
   (set (match_operand:SI 0 "register_operand" "")
        (match_dup 1))]
  ;"dead_or_set_p (insn, operands[1])"
  "find_regno_note (next_real_insn (insn), REG_DEAD, REGNO (operands[1]))"
  [(set (match_dup 0)
        (plus:SI (reg:SI SP_REGNUM) (match_dup 2)))])

;; XMOVEI AC1,(17)
;; ADDI AC1,OFFSET		->	XMOVEI AC1,OFFSET(17)
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(reg:SI SP_REGNUM))
   (set (match_dup 0)
	(plus:SI (match_dup 0)
		 (match_operand:SI 1 "const_int_operand" "")))]
  ""
  [(set (match_dup 0)
	(plus:SI (reg:SI SP_REGNUM) (match_dup 1)))])

;; XMOVEI AC1,OFFSET1(17)
;; ADDI AC1,OFFSET2		->	XMOVEI AC1,OFFSET1+OFFSET2(17)
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(plus:SI (reg:SI SP_REGNUM)
		 (match_operand:SI 1 "const_int_operand" "")))
   (set (match_dup 0)
	(plus:SI (match_dup 0)
		 (match_operand:SI 2 "const_int_operand" "")))]
  ""
  [(set (match_dup 0)
	(plus:SI (reg:SI SP_REGNUM) (match_dup 3)))]
  "operands[3] = gen_int_mode (INTVAL (operands[1]) + INTVAL (operands[2]),
			       Pmode);")

;; AOS m
;; MOVE a,m			->	AOS a,m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int 1)))
   (set (match_operand:SI 1 "register_operand" "")
	(match_dup 0))]
  "REGNO (operands[1]) != 0"
  [(parallel
    [(set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int 1)))
     (set (match_dup 1)
	  (plus:SI (match_dup 0) (const_int 1)))])])

;; SOS m
;; MOVE a,m			->	SOS a,m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int -1)))
   (set (match_operand:SI 1 "register_operand" "")
	(match_dup 0))]
  "REGNO (operands[1]) != 0"
  [(parallel
    [(set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int -1)))
     (set (match_dup 1)
	  (plus:SI (match_dup 0) (const_int -1)))])])

;; AOS a,m
;; CAILE a,0			->	AOSLE a,m
;;  MOVEI a,0				 MOVEI a,0
(define_peephole
  [(parallel [(set (match_operand:SI 0 "memory_operand" "")
		   (plus:SI (match_dup 0) (const_int 1)))
	      (set (match_operand:SI 1 "register_operand" "")
		   (plus:SI (match_dup 0) (const_int 1)))])
   (set (match_dup 1)
	(smin:SI (match_dup 1) (match_operand 2 "const_int_operand" "")))]
  "REGNO (operands[1]) != 0
   && (INTVAL (operands[2]) >= -1 || INTVAL (operands[2]) <= 1)"
  {
    if (INTVAL (operands[2]) == 0)
      return "aosle %1,%0\;%_movei %1,0";
    else if (INTVAL (operands[2]) == 1)
      return "aosle %1,%0\;%_movei %1,1";
    else
      return "aosl %1,%0\;%_seto %1,";
  })

;; SOS a,m
;; CAILE a,0			->	SOSLE a,m
;;  MOVEI a,0				 MOVEI a,0
(define_peephole
  [(parallel [(set (match_operand:SI 0 "memory_operand" "")
		   (plus:SI (match_dup 0) (const_int -1)))
	      (set (match_operand:SI 1 "register_operand" "")
		   (plus:SI (match_dup 0) (const_int -1)))])
   (set (match_dup 1)
	(smin:SI (match_dup 1) (match_operand 2 "const_int_operand" "")))]
  "REGNO (operands[1]) != 0
   && (INTVAL (operands[2]) >= -1 || INTVAL (operands[2]) <= 1)"
  {
    if (INTVAL (operands[2]) == 0)
      return "sosle %1,%0\;%_movei %1,0";
    else if (INTVAL (operands[2]) == 1)
      return "sosle %1,%0\;%_movei %1,1";
    else
      return "sosl %1,%0\;%_seto %1,";
  })

;; AOS a,m
;; CAIGE a,0			->	AOSGE a,m
;;  MOVEI a,0				 MOVEI a,0
(define_peephole
  [(parallel [(set (match_operand:SI 0 "memory_operand" "")
		   (plus:SI (match_dup 0) (const_int 1)))
	      (set (match_operand:SI 1 "register_operand" "")
		   (plus:SI (match_dup 0) (const_int 1)))])
   (set (match_dup 1)
	(smax:SI (match_dup 1) (match_operand 2 "const_int_operand" "")))]
  "REGNO (operands[1]) != 0
   && (INTVAL (operands[2]) >= -1 || INTVAL (operands[2]) <= 1)"
  {
    if (INTVAL (operands[2]) == 0)
      return "aosge %1,%0\;%_movei %1,0";
    else if (INTVAL (operands[2]) == 1)
      return "aosg %1,%0\;%_movei %1,1";
    else
      return "aosge %1,%0\;%_seto %1,";
  })

;; SOS a,m
;; CAIGE a,0			->	SOSGE a,m
;;  MOVEI a,0				 MOVEI a,0
(define_peephole
  [(parallel [(set (match_operand:SI 0 "memory_operand" "")
		   (plus:SI (match_dup 0) (const_int -1)))
	      (set (match_operand:SI 1 "register_operand" "")
		   (plus:SI (match_dup 0) (const_int -1)))])
   (set (match_dup 1)
	(smax:SI (match_dup 1) (match_operand 2 "const_int_operand" "")))]
  "REGNO (operands[1]) != 0
   && (INTVAL (operands[2]) >= -1 || INTVAL (operands[2]) <= 1)"
  {
    if (INTVAL (operands[2]) == 0)
      return "sosge %1,%0\;%_movei %1,0";
    else if (INTVAL (operands[2]) == 1)
      return "sosg %1,%0\;%_movei %1,1";
    else
      return "sosge %1,%0\;%_seto %1,";
  })

;; AOS m
;; SKIPx m			->	AOSx m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int 1)))
    (set (pc)
	 (if_then_else
	  (match_operator 2 "pdp10_comparison_operator"
	   [(match_dup 0)
	    (const_int 0)])
	  (label_ref (match_operand 1 "" ""))
	  (pc)))]
  ""
  [(parallel
    [(set (pc)
	  (if_then_else
	   (match_op_dup 2
	    [(plus:SI (match_dup 0) (const_int 1))
	     (const_int 0)])
	   (label_ref (match_dup 1))
	   (pc)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int 1)))])])

;; SOS m
;; SKIPx m			->	SOSx m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int -1)))
    (set (pc)
	 (if_then_else
	  (match_operator 2 "pdp10_comparison_operator"
	   [(match_dup 0)
	    (const_int 0)])
	  (label_ref (match_operand 1 "" ""))
	  (pc)))]
  ""
  [(parallel
    [(set (pc)
	  (if_then_else
	   (match_op_dup 2
	    [(plus:SI (match_dup 0) (const_int -1))
	     (const_int 0)])
	   (label_ref (match_dup 1))
	   (pc)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int -1)))])])

;; AOS m
;; SKIPx a,m			->	AOSx a,m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int 1)))
   (parallel
    [(set (pc)
	  (if_then_else
	   (match_operator 3 "pdp10_comparison_operator"
	    [(match_dup 0)
	     (const_int 0)])
	   (label_ref (match_operand 1 "" ""))
	   (pc)))
     (set (match_operand:SI 2 "register_operand" "")
	  (match_dup 0))])]
  "REGNO (operands[2]) != 0"
  [(parallel
    [(set (pc)
	  (if_then_else
	   (match_op_dup 3
	    [(plus:SI (match_dup 0) (const_int 1))
	     (const_int 0)])
	   (label_ref (match_dup 1))
	   (pc)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int 1)))
     (set (match_dup 2)
	  (plus:SI (match_dup 0) (const_int 1)))])])

;; SOS m
;; SKIPx a,m			->	SOSx a,m
(define_peephole2
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_dup 0)
		 (const_int -1)))
   (parallel
    [(set (pc)
	  (if_then_else
	   (match_operator 3 "pdp10_comparison_operator"
	    [(match_dup 0)
	     (const_int 0)])
	   (label_ref (match_operand 1 "" ""))
	   (pc)))
     (set (match_operand:SI 2 "register_operand" "")
	  (match_dup 0))])]
  "REGNO (operands[2]) != 0"
  [(parallel
    [(set (pc)
	  (if_then_else
	   (match_op_dup 3
	    [(plus:SI (match_dup 0) (const_int -1))
	     (const_int 0)])
	   (label_ref (match_dup 1))
	   (pc)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0) (const_int -1)))
     (set (match_dup 2)
	  (plus:SI (match_dup 0) (const_int -1)))])])

;; ADDI a,1
;; JRST m			->	AOJA a,m
;; The traditional peephole is needed to detect sequences after basic
;; block reordering.  peephole2 is run before that.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(plus:SI (match_dup 0)
		 (const_int 1)))
   (set (pc)
	(label_ref (match_operand 1 "" "")))]
  ""
  [(parallel
    [(set (pc)
	  (label_ref (match_dup 1)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0)
		   (const_int 1)))])])
(define_peephole
  [(set (match_operand:SI 0 "register_operand" "")
	(plus:SI (match_dup 0)
		 (const_int 1)))
   (set (pc)
	(label_ref (match_operand 1 "" "")))]
  ""
  "aoja %0,%l1")

;; SUBI a,1
;; JRST m			->	SOJA a,m
;; The traditional peephole is needed to detect sequences after basic
;; block reordering.  peephole2 is run before that.
(define_peephole2
  [(set (match_operand:SI 0 "register_operand" "")
	(plus:SI (match_dup 0)
		 (const_int -1)))
   (set (pc)
	(label_ref (match_operand 1 "" "")))]
  ""
  [(parallel
    [(set (pc)
	  (label_ref (match_dup 1)))
     (set (match_dup 0)
	  (plus:SI (match_dup 0)
		   (const_int -1)))])])
(define_peephole
  [(set (match_operand:SI 0 "register_operand" "")
	(plus:SI (match_dup 0)
		 (const_int -1)))
   (set (pc)
	(label_ref (match_operand 1 "" "")))]
  ""
  "soja %0,%l1")

;; AOS m1
;; JRST m2			->	AOSA m1,m2 (if possible)
;; TODO.

;; SOS m1
;; JRST m2			->	SOSA m1,m2 (if possible)
;; TODO.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Miscellaneous

;; UNSPEC_VOLATILE is considered to use and clobber all hard registers
;; and all of memory.  This blocks insns from being moved across this
;; point.
(define_insn "blockage"
  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
  ""
  ""
  [(set_attr "length" "0")])

(define_insn "*movqi_subreg"
  [(set (match_operand:QI 0 "register_operand" "=r")
	(subreg:QI (match_operand:SI 1 "register_operand" "r") 3))]
  ""
  "move %0,%1%; (set (reg:QI %0) (subreg:QI (reg:SI %1) 3)")

(define_insn ""
  [(set (subreg:QI (match_operand:SI 0 "register_operand" "=r") 3)
	(match_operand:QI 1 "register_operand" "r"))]
  ""
  "move %0,%1%; (set (subreg:QI (reg:SI %0) 3) (reg:QI %1)")

(define_insn ""
  [(set (match_operand:QI 0 "register_operand" "=r")
	(subreg:QI (match_operand:SI 1 "register_operand" "0") 0))]
  ""
  "lsh %0,-33%; (set (reg:QI %0) (subreg:QI (reg:SI %1) 0))")

(define_insn ""
  [(set (match_operand:HI 0 "register_operand" "=r")
	(subreg:HI (match_operand:SI 1 "register_operand" "r") 0))]
  ""
  "hlrz %0,%1%; (set (reg:HI %0) (subreg:HI (reg:SI %1) 0))")

(define_insn ""
  [(set (match_operand:HI 0 "register_operand" "=r")
	(subreg:HI (match_operand:SI 1 "register_operand" "r") 2))]
  ""
  "hrrz %0,%1%; (set (reg:HI %0) (subreg:HI (reg:SI %1) 2))")

(define_insn ""
  [(set (match_operand:HI 0 "register_operand" "=r")
	(subreg:HI (zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
				    (const_int 18)
				    (const_int 18))
		   0))]
  ""
  "hrrz %0,%1%; (set (reg:HI %0) (subreg:HI (zero_extr:SI %1 18 18) 0))")

(define_insn ""
  [(set (match_operand:QI 0 "register_operand" "=r")
	(subreg:QI (zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
				    (const_int 9)
				    (const_int 27))
		   0))]
  ""
  ;; FIXME: will this do?
  "move %0,%1"
  [(set_attr "length" "3")])

;; Only used in KA10 expansion of FIX.
(define_insn "TSC"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (xor:SI
	 (match_dup 0)
	 (ior:SI
	  (ashift:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")
		     (const_int 18))
	  (lshiftrt:SI (match_dup 1) (const_int 18)))))]
  ""
  "tsc %0,%1")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
		     (const_int 27)))]
  ""
  "move %0,%1\;ash %0,-33"
  [(set_attr "length" "2")])

(define_insn ""
  [(set (match_operand:QI 0 "register_operand" "=r")
        (subreg:QI (zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
				    (const_int 9)
				    (const_int 0))
		   3))]
  ""
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = operands[1];
    ops[2] = GEN_INT (9);
    ops[3] = GEN_INT (0);
    if (get_attr_length (insn) == 1)
      output_asm_insn (pdp10_output_extzv (insn, ops), ops);
    else
      output_asm_insn (pdp10_output_extzv_sequence (ops), ops);
    return "";
  }
  [(set (attr "length")
	(if_then_else (ne (symbol_ref "TARGET_LARGE") (const_int 0))
		      (const_int 1)
		      (const_int 2)))])

(define_insn ""
  [(set (match_operand:QI 0 "register_operand" "=r")
	(subreg:QI (zero_extract:SI (match_operand:SI 1 "memory_operand" "m")
				    (const_int 9)
				    (const_int 9))
		   3))]
  ""
  {
    rtx ops[4];
    ops[0] = operands[0];
    ops[1] = operands[1];
    ops[2] = GEN_INT (9);
    ops[3] = GEN_INT (9);
    output_asm_insn (pdp10_output_extzv (insn, ops), ops);
    return "";
  })
