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

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

;; Use peep2_reg_dead_p in peepholes.

;; Unsigned multiplication.
;;
;;	mul 1,3		; multiply AC1 by AC3
;;	lsh 2,1
;;	lshc 1,-1	; result in AC2

;; 71-bit arithmetic.
;;
;; Addition, subtraction, multiplication, division, arithmetic shift:
;; supported in hardware.
;;
;; Logical shift (left or right).
;;
;;	lsh 2,-1
;;	lshc 1,3
;;	lsh 2,1

;; 72-bit arithmetic.
;;
;; Addition 72 x 72 -> 72.
;;
;;	jfcl 17,.+1	; add AC1 and AC2 to AC3 and AC4
;;	add 2,4
;;	jcry0 [aoja 1,.+1]
;;	add 1,3		; result in AC1 and AC2
;;
;; Subtraction 72 x 72 -> 72.
;;
;;	jfcl 17,.+1	; add AC1 and AC2 to AC3 and AC4
;;	sub 2,4
;;	jcry0 .+2
;;	 subi 1,1
;;	sub 1,3		; result in AC1 and AC2
;;
;; Negation 72 -> 72.
;;
;;	setcm 1,3
;;	movn 2,4
;;	jumpe 2,[aoja 1,.+1]
;;
;;	; to self
;;	setca 1,
;;	jumpe 2,[aoja 1,.+2]
;;	 movn 2,2
;;
;; Magnitude 72 -> 72.
;;
;;	; conditional negation
;;	jumpge 1,.+4
;;	setca 1,
;;	jumpe 2,[aoja 1,.+2]
;;	 movn 2,2
;;
;;	; mask = x >> 71 (arithmetic shift)
;;	; y = (x ^ mask) - mask
;;	move 3,1
;;	ash 1,-43	; shortcut
;;	xor 1,3
;;	xor 2,3
;;	jfcl 17,.+1
;;	sub 2,3
;;	jcry0 [aoja 1,.+1]
;;
;; Signed right shift 72 -> 72.
;;
;;	Variable amount:
;;
;;	; only works if n <= 35
;;	movn 4,3	; operand in AC1:AC2, shift amount in AC3
;;	lshc 1,4
;;	lsh 1,3
;;	ash 1,4		; result in AC1:AC2
;;
;;	; loop
;;	jumple 3,.+5
;;	 lshc 1,-1
;;	 tlne 1,200000
;;	  tlo 1,400000
;;	 sojg 3,.-3
;;
;;	; only works if n <= 70
;;	tlnn 1,400000
;;	 tdza 4,4
;;	  movsi 4,400000
;;	movei 5,0
;;	ashc 4,3
;;	lsh 5,1
;;	lshc 1,3
;;	ior 1,4
;;	ior 2,5
;;
;;	Fixed amount:
;;
;;	lshc 1,-n
;;	tlne 1,mask1
;;	 tlo 1,mask2
;;
;;	skipge 1	; or cail 1,0 or jumpge 1,.+2 or tlne 1,400000
;;	 iori 2,<2^n-1>
;;	rotc 1,-n
;;
;; Signed multiplication 36 x 36 -> 72.
;;
;;	jfcl .+1	; multiply AC1 by AC3
;;	mul 1,3
;;	lsh 2,1
;;	jov [movsi 1,200000
;;	     jrst .+4]
;;	lshc 1,-1
;;	tlne 1,200000
;;	 tlo 1,400000	; result in AC1 and AC2
;;
;;	mul 1,3
;;	lsh 2,1
;;	jumpe 2,[cam 1,[400000000000]
;;	          jrst .+1
;;	         movsi 1,200000
;;	         jrst .+4]
;;	lshc 1,-1
;;	tlne 1,200000
;;	 tlo 1,400000	; result in AC1 and AC2
;;
;;	...
;;	lshc 1,-1
;;	lsh 1,1
;;	ash 1,-1	; result in AC1 and AC2
;;
;;	...
;;	skipge 1
;;	 iori 2,1
;;	rotc 1,-1	; result in AC1 and AC2
;;
;;	jfcl .+1	; multiply AC1 by AC3
;;	mul 1,3
;;	jov [movsi 1,200000
;;	     movei 2,0
;;	     jrst .+5]
;;	trne 1,1
;;	 tloa 2,400000
;;	  tlz 2,400000
;;	ash 1,-1	; result in AC1 and AC2
;;
;;	 377777,,777777 ^ 2		 =  177777,,777777 000000,,000001
;;	-400000,,000000 * 377777,,777777 = -177777,,777777 400000,,000000
;;					(=  600000,,000000 400000,,000000)
;;	-400000,,000000 ^ 2		 =  200000,,000000 000000,,000000
;;	-400000,,000000 * -1		 =  000000,,000000 400000,,000000
;;	-000000,,000001 ^ 2              =  000000,,000000 000000,,000001
;;	-000000,,000001 * 000000,,000001 = -000000,,000000 000000,,000001
;;					(=  777777,,777777 777777,,777777)
;;	-000000,,000001 * 000001,,000001 = -000000,,000000 000001,,000001
;;					(=  777777,,777777 777776,,777777)
;;
;; Signed high part multiplication 36 x 36 -> 36.
;;
;;	jfcl .+1	; multiply AC1 by AC2
;;	mulm 2,1
;;	jov [movsi 1,200000
;;	     jrst .+2]
;;	ash 1,-1	; result in AC1
;;
;; Unsigned multiplication 36 x 36 -> 72.
;;
;;	377777,,777777 ^ 2		= 177777,,777777 000000,,000001
;;	400000,,000000 * 377777,,777777 = 177777,,777777 400000,,000000
;;	400000,,000000 ^ 2		= 200000,,000000 000000,,000000
;;	400000,,000000 * 777777,,777777 = 377777,,777777 400000,,000000
;;	777777,,777777 ^ 2              = 777777,,777776 000000,,000001
;;	777777,,777777 * 000000,,000001 = 000000,,000000 777777,,777777
;;	777777,,777777 * 000001,,000001 = 000001,,000000 777776,,777777
;;
;; Multiplication 72 x 72 -> 72.
;;
;;	dmul 1,3	; multiply AC1 and AC2 by AC3 and AC4
;;	lsh 3,1
;;	lshc 2,-1
;;	lsh 4,1
;;	lshc 3,1
;;	trne 2,1
;;	 tlo 3,400000	; result in AC3 and AC4
;;
;;	dmul 1,3
;;	lsh 4,1
;;	lshc 3,-1
;;	lsh 3,2
;;	lshc 2,-2
;;
;; Comparisons 72 x 72.
;;
;;	; x == y
;;	CAMN x+1,y+1		
;;	 CAME x,y
;;	  ;here if false

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

;; Ok to negate double-word integer with DMOVN?
;; Answer: perhaps not.
;;
;; If comparison code cares about bit 0 in the second word of a
;; double-word integer, negation has to set the bit to the right
;; value.

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

;; ANDCMI really faster than TRZ?

;; Add `cmpdi' pattern.

;; Revisit `casesi'.

;; *move_and_skipsi and *move_and_skipsf clobbers 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.
   (UNSPEC_TRNE_TLO	16)	; TLNE-TLO sequence (SImode):
				;   Operand 0 is the TRNE operand.
				;   Operand 1 is the TLO operand.
   (UNSPEC_ASHC		17)	; ASHC operation (DImode):
				;   Operand 0 is the value to shift.
				;   Operand 1 is the amount to shift by.
   (UNSPEC_LSHC		18)])	; ASHC operation (DImode):
				;   Operand 0 is the value to shift.
				;   Operand 1 is the amount to shift by.

(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")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(subreg:SI (match_operand:QI 1 "memory_operand" "m") 0)
		    (match_operand 2 "const_int_operand" "")]
		   UNSPEC_SIGN_EXTEND))]
  "MEM_SCALAR_P (operands[1]) && INTVAL (operands[2]) >= 18"
  "hrre %0,%W1")

;; 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
	 ;; This could well be a scalar int variable.
; 	 (match_operand:SI 1 "pdp10_maybe_volatile_memory_operand" "m")
; 	 (const_int 511)))]
;   "MEM_SCALAR_P (operands[1])"
;   "move %0,%W1")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(subreg:SI (match_operand:QI 1 "memory_operand" "m") 0)
		    (match_operand 2 "const_int_operand" "")]
		   UNSPEC_ZERO_EXTEND))]
  "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")

(define_insn ""
  [(set (match_operand:QI 0 "memory_operand" "=m")
	(subreg:QI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
			       (match_operand 2 "const_int_operand" "")]
			      UNSPEC_SIGN_EXTEND)
		   3))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%W0")

(define_insn ""
  [(set (match_operand:QI 0 "memory_operand" "=m")
	(subreg:QI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
			       (match_operand 2 "const_int_operand" "")]
			      UNSPEC_ZERO_EXTEND)
		   3))]
  "MEM_SCALAR_P (operands[0])"
  "movem %1,%W0")

;; 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")
		 ;; This could well be a scalar int variable.
; 	 (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 "*sgeu"
  [(set (match_operand:SI 0 "register_operand" "=x")
	(ge:SI (xor:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")
		       (const_int SIGNBIT))
	       (match_operand:SI 2 "const_int_operand" "")))]
  ""
  {
    HOST_WIDE_INT sign = (HOST_WIDE_INT)1 << 35;
    operands[2] = gen_int_mode (INTVAL (operands[2]) ^ sign, SImode);
    if (INTVAL (operands[2]) & ~(HOST_WIDE_INT)0777777)
      return "skipl %0,%1\;%_caml %0,[%2]\;%_%_trna\;%_%_%_tdza %0,%0\;%_%_%_%_movei %0,1";
    else
      return "skipl %0,%1\;%_cail %0,%2\;%_%_trna\;%_%_%_tdza %0,%0\;%_%_%_%_movei %0,1";
  }
  [(set_attr "length" "5")])

(define_insn "*sgeu_plus"
  [(set (match_operand:SI 0 "register_operand" "=&r")
	(ge:SI (xor:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
				(match_operand:SI 2 "const_int_operand" ""))
		       (const_int SIGNBIT))
	       (match_operand:SI 3 "const_int_operand" "")))]
  ""
  {
    HOST_WIDE_INT sign = (HOST_WIDE_INT)1 << 35;

    output_asm_insn ("movei %0,0", operands);

    operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
    if (INTVAL (operands[2]) & ~(HOST_WIDE_INT)0777777)
      output_asm_insn ("caml %1,[%2]", operands);
    else
      output_asm_insn ("cail %1,%2", operands);
          
    operands[3] = gen_int_mode ((INTVAL (operands[3]) ^ sign)
				- INTVAL (operands[2]), SImode);
    if (INTVAL (operands[3]) & ~(HOST_WIDE_INT)0777777)
      output_asm_insn ("%_caml %1,[%3]", operands);
    else
      output_asm_insn ("%_cail %1,%3", operands);

    return "%_%_movei %0,1";
  }
  [(set_attr "length" "4")])

(define_insn "*cbranchgeu"
  [(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" ""))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))]
  ""
  {
    rtx ops[5];
    ops[0] = operands[0];
    ops[1] = operands[0];
    ops[2] = GEN_INT (0);
    ops[3] = operands[1];
    ops[4] = operands[2];
    return pdp10_output_range_compare (insn, ops, 0);
  }
  [(set_attr "length" "3")])

(define_insn "*cbranchgeu_mem"
  [(set (pc)
	(if_then_else
	 (ge (xor:SI (match_operand:SI 0 "memory_operand" "m")
		     (const_int SIGNBIT))
	     (match_operand:SI 1 "const_int_operand" ""))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 3 "=x"))]
  ""
  {
    rtx ops[5];
    ops[0] = operands[3];
    ops[1] = operands[0];
    ops[2] = GEN_INT (0);
    ops[3] = operands[1];
    ops[4] = operands[2];
    return pdp10_output_range_compare (insn, ops, 0);
  }
  [(set_attr "length" "4")])

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

(define_insn "*sltu"
  [(set (match_operand:SI 0 "register_operand" "=x")
	(lt:SI (xor:SI (match_operand:SI 1 "reg_or_mem_operand" "rm")
		       (const_int SIGNBIT))
	       (match_operand:SI 2 "const_int_operand" "")))]
  ""
  {
    HOST_WIDE_INT sign = (HOST_WIDE_INT)1 << 35;
    operands[2] = gen_int_mode (INTVAL (operands[2]) ^ sign, SImode);
    if (INTVAL (operands[2]) & ~(HOST_WIDE_INT)0777777)
      return "skipl %0,%1\;%_caml %0,[%2]\;%_%_tdza %0,%0\;%_%_%_movei %0,1";
    else
      return "skipl %0,%1\;%_cail %0,%2\;%_%_tdza %0,%0\;%_%_%_movei %0,1";
  }
  [(set_attr "length" "4")])

(define_insn "*sltu_plus"
  [(set (match_operand:SI 0 "register_operand" "=x")
	(lt:SI (xor:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
				(match_operand:SI 2 "const_int_operand" ""))
		       (const_int SIGNBIT))
	       (match_operand:SI 3 "const_int_operand" "")))]
  ""
  {
    HOST_WIDE_INT sign = (HOST_WIDE_INT)1 << 35;

    operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
    if (INTVAL (operands[2]) & ~(HOST_WIDE_INT)0777777)
      output_asm_insn ("caml %1,[%2]", operands);
    else
      output_asm_insn ("cail %1,%2", operands);

    operands[3] = gen_int_mode ((INTVAL (operands[3]) ^ sign)
				- INTVAL (operands[2]), SImode);
    if (INTVAL (operands[3]) & ~(HOST_WIDE_INT)0777777)
      output_asm_insn ("%_caml %1,[%3]", operands);
    else
      output_asm_insn ("%_cail %1,%3", operands);

    return "%_%_tdza %0,%0\;%_%_%_movei %0,1";
  }
  [(set_attr "length" "4")])

(define_insn "*cbranchltu"
  [(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" ""))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))]
  ""
  {
    rtx ops[5];
    ops[0] = operands[0];
    ops[1] = operands[0];
    ops[2] = GEN_INT (0);
    ops[3] = operands[1];
    ops[4] = operands[2];
    return pdp10_output_range_compare (insn, ops, 1);
  }
  [(set_attr "length" "4")])

(define_insn "*cbranchltu_mem"
  [(set (pc)
	(if_then_else
	 (lt (xor:SI (match_operand:SI 0 "memory_operand" "m")
		     (const_int SIGNBIT))
	     (match_operand:SI 1 "const_int_operand" ""))
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   (clobber (match_scratch:SI 3 "=x"))]
  ""
  {
    rtx ops[5];
    ops[0] = operands[3];
    ops[1] = operands[0];
    ops[2] = GEN_INT (0);
    ops[3] = operands[1];
    ops[4] = operands[2];
    return pdp10_output_range_compare (insn, ops, 1);
  }
  [(set_attr "length" "4")])

(define_insn "*cbranchltu_plus"
  [(set (pc)
	(if_then_else
	 (lt (xor:SI (plus:SI (match_operand:SI 0 "reg_or_mem_operand" "r")
			      (match_operand:SI 1 "const_int_operand" ""))
		     (const_int SIGNBIT))
	     (match_operand:SI 2 "const_int_operand" ""))
	 (label_ref (match_operand 3 "" ""))
	 (pc)))]
  ""
  {
    rtx ops[5];
    ops[0] = operands[0];
    ops[1] = operands[0];
    ops[2] = operands[1];
    ops[3] = operands[2];
    ops[4] = operands[3];
    return pdp10_output_range_compare (insn, ops, 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 "memory_operand" "=m")
	(and:SI (match_operand:SI 1 "memory_operand" "0")
		(const_int LEFT_HALF)))]
  ""
  "hllzs %W0")

(define_insn ""
  [(set (match_operand:HI 0 "memory_operand" "=m")
	(const_int 0))]
  "MEM_ALIGN (operands[0]) == 36"
  "hrrzs %W0")

(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 (REG_P (operands[0]) && GET_CODE (operands[1]) == CONST_INT)
         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
     }
   else
     {
       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]);
     }")

(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 (REG_P (operands[0]) && GET_CODE (operands[1]) == CONST_INT)
         operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
     }
   else
     {
       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" };
	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 "hrre %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
	   || INTVAL (operands[2]) + INTVAL (operands[3]) == 36)
       && !CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
;       && (GET_CODE (XEXP (operands[1], 0)) == REG
;	   || GET_CODE (XEXP (operands[1], 0)) == PLUS))"
;	   || (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_insn "*move_dpb"
  [(set (match_operand:QI 0 "memory_operand" "=m")
	(subreg:QI (zero_extract:SI (match_operand:SI 2 "memory_operand" "m")
				    (const_int 9)
				    (const_int 27)) 3))
   (clobber (match_scratch:SI 1 "=r"))]
  ""
  {
    output_asm_insn ("move %1,%2", operands);
    return pdp10_output_store_byte (insn, operands);
  }
  [(set_attr "length" "2")])

(define_insn "*move_dpb2"
  [(set (zero_extract:SI (match_operand:SI 0 "memory_operand" "+m")
			 (const_int 8)
			 (const_int 0))
	(and:SI (match_operand:SI 2 "memory_operand" "m")
		(const_int 255)))
   (clobber (match_scratch:SI 1 "=r"))]
  ""
  {
    output_asm_insn ("move %1,%2", operands);
    return pdp10_output_store_byte (insn, operands);
  }
  [(set_attr "length" "2")])

(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 may
;; be 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 "*MOVEI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (plus:SI (match_operand:SI 1 "register_operand" "x")
			 (match_operand:SI 2 "const_int_operand" "I"))
		(const_int RIGHT_HALF)))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "movei %0,%2(%1)")

(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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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:SI (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 "*sgesi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ge:SI (match_operand:SI 1 "register_operand" "0")
	       (const_int 0)))]
  ""
  "lsh %0,-43\;xori %0,1"
  [(set_attr "length" "2")])

;; This seemingly useless instruction combination is needed to enable
;; the combination below.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
			 (match_operand:SI 2 "reg_or_mem_operand" "rm"))
		(const_int SIGNBIT)))]
  "0"
  "add %0,%2\;tlc %0,400000")

;; Calculate the truth value of this particular unsigned comparison
;; with ADD and JCRY0.
(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
	(gt:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
		       (const_int SIGNBIT))
	       (xor:SI (plus:SI (match_operand:SI 2 "register_operand" "0")
				(match_operand:SI 3 "reg_or_mem_operand" "1"))
		       (const_int SIGNBIT))))]
  "0"
  "jfcl 17,.+1\;add %0,%3\;jcry0 .+2\;%_tdza %0,%0\;movei %0,1")

(define_insn "*sccsi"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(match_operator:SI 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:SI (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 "*sltsf"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lt:SI (match_operand:SF 1 "register_operand" "0")
	       (match_operand:SF 2 "immediate_operand" "R")))]
  ""
  "lsh %0,-43")

(define_insn "*sgesf"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ge:SI (match_operand:SF 1 "register_operand" "0")
	       (match_operand:SF 2 "immediate_operand" "R")))]
  ""
  "lsh %0,-43\;xori %0,1"
  [(set_attr "length" "2")])

(define_insn "*sccsf"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(match_operator:SI 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_insn "*snedf"
  [(set (match_operand:SI 0 "register_operand" "=x")
	(ne:SI (match_operand:DF 1 "reg_or_mem_operand" "ro")
	       (match_operand:DF 2 "pdp10_const_double_0_operand" "")))]
  ""
  "skipn %@%1\;%_skipe %0,%Z1\;%_%_movei %0,1"
  [(set_attr "length" "3")])

(define_insn "*sltdf"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(lt:SI (match_operand:DF 1 "register_operand" "0")
	       (match_operand:DF 2 "immediate_operand" "R")))]
  ""
  "lsh %0,-43")

(define_insn "*sgedf"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ge:SI (match_operand:DF 1 "register_operand" "0")
	       (match_operand:DF 2 "immediate_operand" "R")))]
  ""
  "lsh %0,-43\;xori %0,1"
  [(set_attr "length" "2")])

;; (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,r,m")
		        (const_int 0)])
	 (label_ref (match_operand 2 "" ""))
	 (pc)))
   ;; The predicate is "preferably_register_operand" so that memory
   ;; operands are invalid until after register allocation.  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 "preferably_register_operand" "=1,x,rm,!rm")
	(match_dup 1))]
  ""
  {
    if (which_alternative == 0)
      return "jump%0 %1,%F2";
    pdp10_remove_unnecessary_label (insn, operands[2]);
    switch (get_attr_length (insn))
      {
      case 1:
	return "skip%0 %3,%1";
      case 2:
	if (which_alternative == 2)
	  return "movem %1,%3\;jump%0 %1,%F2";
	else if (REGNO (operands[3]) == 0)
	  return "move %3,%1\;jump%0 %3,%F2";
	else
	  {
	    output_asm_insn ("skip%R0 %3,%1", operands);
	    return pdp10_output_jrst (operands[2]);
	  }
      /* FIXME: is the use of a fixed scratch register avoidable?  */
      case 3:
	return "move 0,%1\;movem 0,%3\;jump%0 0,%F2";
      default:
	abort ();
      }
  }
  [(set (attr "length")
	(cond [(eq_attr "alternative" "0") (const_int 1)
	       (eq_attr "alternative" "2") (const_int 2)
	       (eq_attr "alternative" "3") (const_int 3)
	       (eq (minus (match_dup 2) (pc)) (const_int 1)) (const_int 1)]
	       (const_int 2)))
   (set_attr "skip" "yes")])
; (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 "preferably_register_operand" so that memory
;    ;; operands are invalid until after register allocation.  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 "preferably_register_operand" "=1,x,!rm")
; 	(match_dup 1))]
;   ""
;   {
;     if (which_alternative == 0)
;       return "jump%0 %1,%F2";
;     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,%F2";
; 	else
; 	  {
; 	    output_asm_insn ("skip%R0 %3,%1", operands);
; 	    return pdp10_output_jrst (operands[2]);
; 	  }
;       /* FIXME: is the use of a fixed scratch register avoidable?  */
;       case 3:
; 	return "move 0,%1\;movem 0,%3\;jump%0 0,%F2";
;       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 "preferably_register_operand" so that memory
   ;; operands are invalid until after register allocation pass.  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:SF 4 "preferably_register_operand" "=1,x,!rm")
	(match_dup 1))]
  ""
  {
    if (which_alternative == 0)
      return "jump%0 %1,%F3";
    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,%F3";
	else
	  {
	    output_asm_insn ("skip%R0 %4,%1", operands);
	    return pdp10_output_jrst (operands[3]);
	  }
      /* FIXME: is the use of a fixed scratch register avoidable?  */
      case 3:
	return "move 0,%1\;movem 0,%4\;jump%0 0,%F3";
      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_expand "addsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "")
	(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "")
		 (match_operand:SI 2 "general_operand" "")))]
  ""
  ;; Make sure that for a MEM + x, x can only be a register or +/-1.
  "if (memory_operand (operands[1], SImode)
       && !(register_operand (operands[2], SImode)
	    || (const_int_operand (operands[2], SImode)
		&& (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))))
     operands[2] = force_reg (SImode, operands[2]);")

(define_insn "*addsi3"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,r,r,r,r,m,m,m")
	(plus:SI (match_operand:SI 1 "reg_or_mem_operand" "%0,0,0,r,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,S,i,r,Q,M")))]
  ""
;  ;; Make sure that for a MEM + x, x can only be a register or +/-1.
;  "!(memory_operand (operands[1], SImode)
;     && !(register_operand (operands[2], SImode)
;	  || (const_int_operand (operands[2], SImode)
;	      && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))))"
  "@
   add %0,%2
   addi %0,%2
   subi %0,%N2
   xmovei %0,%2(%1)
   add %0,[%X2]
   addm %2,%0
   aos %@%0
   sos %@%0")

(define_insn "*ADDI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (and:SI (match_operand:SI 1 "register_operand" "x")
			 (const_int RIGHT_HALF))
		 (match_operand:SI 2 "register_operand" "0")))]
  ""
  "addi %0,(%1)")
(define_insn "*ADDI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(plus:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "x")
				  (match_operand:SI 2 "const_int_operand" "I"))
			 (const_int RIGHT_HALF))
		 (match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "addi %0,%2(%1)")

(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_expand "adddi3"
  [(set (match_operand:DI 0 "register_operand" "")
	(plus:DI (match_operand:DI 1 "register_operand" "")
		 (match_operand:DI 2 "general_operand" "")))]
  "TARGET_KL10up && TARGET_71BIT"
  "")

(define_insn "*adddi3"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "=r,r,r,r,o,o,o")
	(plus:DI (match_operand:DI 1 "reg_or_mem_operand" "%0,0,0,0,0,0,0")
		 (match_operand:DI 2 "general_operand" "ro,I,J,i,r,Q,M")))]
  "0 && !TARGET_71BIT"
  "@
   jfcl 17,.+1\;add %Z0,%Z2\;jcry0 [aoja %0,.+1]\;add %0,%2
   jfcl 17,.+1\;addi %Z0,%2\;jcry0 [aoja %0,.+1]
   jfcl 17,.+1\;subi %Z0,%N2\;jcry0 .+2\;%_subi %0,1
   jfcl 17,.+1\;add %Z0,[%B2]\;jcry0 [aoja %0,.+1]\;add %0,[%A2]
   jfcl 17,.+1\;addm %Z2,%Z0\;jcry0 [aos %0\;jrst .+1]\;add %2,%0
   jfcl 17,.+1\;aos %Z0\;jcry0 [aos %0\;jrst .+1]\;aos %0
   jfcl 17,.+1\;sos %Z0\;jcry0 .+2\;sos %0\;sos %0"
  [(set_attr "length" "4,3,4,4,4,4,5")])

(define_insn "*DADD"
  [(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")))]
  "TARGET_71BIT && 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 "*SUBI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (match_operand:SI 1 "register_operand" "0")
		  (and:SI (match_operand:SI 2 "register_operand" "x")
			  (const_int RIGHT_HALF))))]
  ""
  "subi %0,(%2)")
(define_insn "*SUBI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(minus:SI (match_operand:SI 1 "register_operand" "0")
		  (and:SI (plus:SI
			   (match_operand:SI 2 "register_operand" "x")
			   (match_operand:SI 3 "const_int_operand" "I"))
		 (const_int RIGHT_HALF))))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[3]), 'I')"
  "subi %0,%3(%2)")

(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_expand "subdi3"
  [(set (match_operand:DI 0 "register_operand" "")
	(minus:DI (match_operand:DI 1 "register_operand" "")
		  (match_operand:DI 2 "general_operand" "")))]
  "TARGET_KL10up && TARGET_71BIT"
  "")

(define_insn "*subdi3"
  [(set (match_operand:DI 0 "register_operand" "=r,o")
	(minus:DI (match_operand:DI 1 "register_operand" "%0,0")
		  (match_operand:DI 2 "reg_or_mem_operand" "ro,r")))]
  "0 && !TARGET_71BIT"
  "@
   jfcl 17,.+1\;sub %Z0,%Z2\;jcry0 .+2\;%_subi %0,1\;sub %0,%2
   jfcl 17,.+1\;subm %Z2,%Z0\;jcry0 .+2\;%_sos %0\;subm %2,%0"
  [(set_attr "length" "5,5")])

(define_insn "*DSUB"
  [(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")))]
  "TARGET_71BIT && 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 "*IMULI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mult:SI (and:SI (match_operand:SI 1 "register_operand" "x")
			 (const_int RIGHT_HALF))
		 (match_operand:SI 2 "register_operand" "0")))]
  ""
  "imuli %0,(%1)")
(define_insn "*IMULI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(mult:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "x")
				  (match_operand:SI 2 "const_int_operand" "I"))
			 (const_int RIGHT_HALF))
		 (match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "imuli %0,%2(%1)")

(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_expand "mulsidi3"
  [(set (match_operand:DI 0 "register_operand" "")
	(mult:DI
	 (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
	 (sign_extend:DI (match_operand:SI 2 "general_operand" ""))))]
  "TARGET_71BIT"
  "")

(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"))))]
  "TARGET_71BIT"
  "@
   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))))]
  "0"
  "operands[3] = gen_reg_rtx (SImode);")

(define_insn "*smulsi3_highpart"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(truncate:SI
	 (lshiftrt:DI
	  (mult:DI
	   (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
	   (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
	  (const_int 36))))]
  "0"
  "jfcl .+1\;mulm %2,%0\;jov [movsi %0,200000\;%_%_%_%_%_jrst .+2]\;ash %0,-1"
  [(set_attr "length" "4")])

(define_insn "*smulsi3_highpart_71"
  [(set (match_operand:SI 0 "reg_or_mem_operand" "=rm")
	(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))))]
  "0"
  "mulm %1,%0")

(define_expand "muldi3"
  [(set (match_operand:DI 0 "register_operand" "")
	(mult:DI (match_operand:DI 1 "register_operand" "")
		 (match_operand:DI 2 "reg_or_mem_operand" "")))]
  "0"
  "{
     rtx temp = gen_reg_rtx (TImode);

     emit_move_insn (gen_rtx_SUBREG (DImode, temp, 0), operands[1]);
     emit_insn (gen_DMUL (temp, gen_rtx_SUBREG (DImode, temp, 8),
			  operands[2]));
     emit_insn (gen_ashlsi3 (gen_rtx_SUBREG (SImode, temp, 8),
			     gen_rtx_SUBREG (SImode, temp, 8),
			     GEN_INT (1)));
     emit_insn (gen_lshrdi3 (gen_rtx_SUBREG (DImode, temp, 4),
			     gen_rtx_SUBREG (DImode, temp, 4),
			     GEN_INT (1)));
     emit_insn (gen_ashlsi3 (gen_rtx_SUBREG (SImode, temp, 12),
			     gen_rtx_SUBREG (SImode, temp, 12),
			     GEN_INT (1)));
     emit_insn (gen_lshrdi3 (gen_rtx_SUBREG (DImode, temp, 8),
			     gen_rtx_SUBREG (DImode, temp, 8),
			     GEN_INT (1)));
     emit_insn (gen_TRNE_TLO (gen_rtx_SUBREG (SImode, temp, 8),
			      gen_rtx_SUBREG (SImode, temp, 8),
			      gen_rtx_SUBREG (SImode, temp, 12)));
				
     DONE;
   }")

(define_insn "TRNE_TLO"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "register_operand" "r")]
		   UNSPEC_TRNE_TLO))]
  ""
  "trne %2,1\;%_tlo %0,400000"
  [(set_attr "length" "2")])

(define_expand "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"))))]
  "TARGET_71BIT && TARGET_KL10up"
  "")

(define_insn "DMUL"
  [(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"))))]
  "TARGET_71BIT && 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")

;; IDIVI with indexing missing.
;; 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)))))]
  "TARGET_71BIT"
  "@
   div %0,%2
   divi %0,%2
   div %0,[%D2]")

(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")))))]
  "TARGET_71BIT"
  "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)))))]
  "TARGET_71BIT"
  "@
   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)))])]
  "TARGET_71BIT"
  "{
     rtx temp = gen_reg_rtx (TImode);
     emit_move_insn (gen_rtx_SUBREG (SImode, temp, 0),
		     gen_rtx_SUBREG (SImode, operands[1], 0));
     emit_insn (gen_ashrsi3 (gen_rtx_SUBREG (SImode, temp, 0),
			     gen_rtx_SUBREG (SImode, temp, 0),
			     GEN_INT (35)));
     emit_move_insn (gen_rtx_SUBREG (SImode, temp, 4),
		     gen_rtx_SUBREG (SImode, temp, 0));
     emit_move_insn (gen_rtx_SUBREG (DImode, temp, 8), 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]")

;; UIDIVI with indexing missing.
;; 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]")

;; UIMODI with indexing missing.
;; 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 "*MOVNI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(neg:SI (and:SI (match_operand:SI 1 "register_operand" "r")
			(const_int RIGHT_HALF))))]
  ""
  "movni %0,(%1)")
(define_insn "*MOVNI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(neg:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
				 (match_operand:SI 2 "const_int_operand" "I"))
			(const_int RIGHT_HALF))))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "movni %0,%2(%1)")

(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_expand "negdi2"
  [(set (match_operand:DI 0 "reg_or_mem_operand" "")
	(neg:DI (match_operand:DI 1 "reg_or_mem_operand" "")))]
  "TARGET_KI10up && TARGET_71BIT"
  "")

(define_insn "*negdi2"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(neg:DI (match_operand:DI 1 "reg_or_mem_operand" "0,ro")))]
  "!TARGET_71BIT"
  "@
   setca %0,\;jumpe %Z0,[aoja %0,.+2]\;%_movn %Z0,%Z0
   setcm %0,%1\;movn %Z0,%Z1\;jumpe %Z0,[aoja %0,.+1]"
  [(set_attr "length" "3,3")])

(define_insn "*DMOVN"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(neg:DI (match_operand:DI 1 "reg_or_mem_operand" "rm")))]
  "TARGET_71BIT && TARGET_KI10up"
  "dmovn %0,%1\;tlne %0,400000\;%_tlo %Z0,400000"
  [(set_attr "length" "3")])

(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")

; (define_expand "popcountsi"
;   Sequence taken from HAKMEM.
;   LDB B,[014300,,A]      ;or MOVE B,A then LSH B,-1
;   AND B,[333333,,333333]
;   SUB A,B
;   LSH B,-1
;   AND B,[333333,,333333]
;   SUBB A,B               ;each octal digit is replaced by number of 1's in it
;   LSH B,-3
;   ADD A,B
;   AND A,[070707,,070707]
;   IDIVI A,77             ;casting out 63.'s


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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 (REGNO (operands[0]) == REGNO (operands[1])
	&& zero_extended_p (operands[0], 18, insn))
      return "";
    else
      return "hrrz %0,%1%; zero_extendhisi2";
  })

(define_insn "zero_extendsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "const_int_operand" "")]
		   UNSPEC_ZERO_EXTEND))]
  ""
  {
    int extend_bits = INTVAL (operands[2]);
    int bitsize = BITS_PER_WORD - extend_bits;
    if (zero_extended_p (operands[0], extend_bits, insn))
      return "";
    else if (extend_bits > 18)
      {
        operands[2] = GEN_INT ((1 << bitsize) - 1);
        return "andi %0,%2";
      }
    else if (extend_bits == 18)
      return "hrrz %0,%0";
    else
      {
        operands[2] = GEN_INT (((1 << extend_bits) - 1) << (18 - extend_bits));
        return "tlz %0,%2";
      }
  })

(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 "hrre %0,%1%; extendhisi2";
  })

(define_insn "sign_extendsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand:SI 2 "const_int_operand" "")]
		   UNSPEC_SIGN_EXTEND))]
  ""
  {
    int extend_bits = INTVAL (operands[2]);
    if (sign_extended_p (operands[0], extend_bits, insn))
      return "";
    else if (zero_extended_p (operands[0], extend_bits, insn))
      {
        int bitsize = BITS_PER_WORD - extend_bits;
        operands[1] = GEN_INT ((HOST_WIDE_INT)1 << (bitsize - 1));
        operands[2] = GEN_INT (((HOST_WIDE_INT)1 << bitsize) - 1);
        return "trne %0,%1\;%_orcmi %0,%2";
      }
    else
      return "lsh %0,%2\;ash %0,-%2";
  })

(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")

(define_insn "truncsi"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
		    (match_operand 2 "const_int_operand" "")]
		   UNSPEC_TRUNCATE))]
  ""
  {
    int bits = BITS_PER_WORD - INTVAL (operands[2]);
    if (bits < 18)
      {
	operands[2] = GEN_INT (((HOST_WIDE_INT)1 << bits) - 1);
	return "andi %0,%2%; truncsi";
      }
    else
      {
	operands[2] = GEN_INT ((0777777 << (bits - 18)) & 0777777);
	return "tlz %0,%2%; truncsi";
      }
  })


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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))]
 "TARGET_71BIT"
 "@
  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))]
 "TARGET_71BIT"
 "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))))]
  ""
  "if (GET_CODE (operands[2]) == CONST_INT)
     {
       if (TARGET_71BIT)
	 emit_insn (gen_LSHC_right_71 (operands[0], operands[1],
				       GEN_INT (-INTVAL (operands[2]))));
       else
	 emit_insn (gen_LSHC_right (operands[0], operands[1],
				    GEN_INT (-INTVAL (operands[2]))));
       DONE;
     }
   else
     operands[3] = gen_reg_rtx (SImode);")

(define_insn "LSHC_right_71"
  [(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"))))]
  "TARGET_71BIT"
  {
    const char *asms[] =
    {
      "lsh %Z0,1\;lshc %0,(%2)\;lsh %Z0,-1",
      "lsh %Z0,1\;lshc %0,%2\;lsh %Z0,-1",
      "lsh %Z0,1\;lshc %0,@%2\;lsh %Z0,-1"
    };
    int n;

    if (get_attr_length (insn) == 1)
      {
        operands[2] = GEN_INT (INTVAL (operands[2]) - 1);
	return "lshc %0,%2";
      }
    /*else if (GET_CODE (operands[2]) == CONST_INT
	     && INTVAL (operands[2]) == -1)
      return "ashc %0,-1\;tlze %0,400000\;tlz %Z0,400000";*/
    else if (GET_CODE (operands[2]) == CONST_INT
	     && (n = INTVAL (operands[2])) >= -18)
      {
        int mask = (0777777 << (18 + n)) & 0777777;
	static char insn[100];

	snprintf (insn, sizeof insn,
		  "ashc %%0,%%2\;tlze %%0,%o\;tlz %%Z0,400000",
		  mask);
	return insn;
      }
    else
      return asms[which_alternative];
  }
  [(set (attr "length")
	(if_then_else (and (match_operand 2 "const_int_operand" "")
			   (ge (symbol_ref "-INTVAL (operands[2])")
			       (const_int 35)))
		      (const_int 1)
		      (const_int 3)))])

(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"))))]
  "!TARGET_71BIT"
  "@
   lshc %0,(%2)
   lshc %0,%2
   lshc %0,@%2")

(define_insn "*LSHC_right_plus_71"
  [(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")))))]
  "TARGET_71BIT"
  "lsh %Z0,1\;lshc %0,%3(%2)\;lsh %Z0,-1"
  [(set_attr "length" "3")])

(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")))))]
  "!TARGET_71BIT"
  "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_expand "ashldi3"
  [(set (match_operand:DI 0 "register_operand" "")
	(ashift:DI (match_operand:DI 1 "register_operand" "")
		   (match_operand:SI 2 "general_operand" "")))]
  ""
  "")

(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")))]
  "!TARGET_71BIT"
  "@
   lshc %0,(%2)
   lshc %0,%2
   lshc %0,@%2")

(define_insn "LSHC_left"
  [(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_LSHC))]
  "TARGET_71BIT"
  "@
   lshc %0,(%2)
   lshc %0,%2
   lshc %0,@%2")

(define_insn "*ashldi3_71bit"
  [(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")))]
  "TARGET_71BIT"
  {
    const char *asms[] =
    {
      "lsh %Z0,1\;lshc %0,(%2)\;lsh %Z0,-1",
      "lsh %Z0,1\;lshc %0,%2\;lsh %Z0,-1",
      "lsh %Z0,1\;lshc %0,@%2\;lsh %Z0,-1"
    };

    switch (get_attr_length (insn))
      {
      case 3:
        operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
	output_asm_insn ("lshc %0,%2", operands);
	break;
      case 4:
        {
	  static char insn[100];
	  int n = INTVAL (operands[2]);
	  snprintf (insn, sizeof insn,
		    n < 18 ? "tlne %%0,%o" : "trne %%0,%o",
		    0400000 >> (n < 18 ? n: n - 18));
	  output_asm_insn (insn, operands);
          return "%_tloa %0,400000\;%_%_tlz %0,400000\;ashc %0,%2";
	}
      case 5:
        output_asm_insn (asms[which_alternative], operands);
	break;
      default:
        abort ();
      }

    return "tlne %0,400000\;%_tlo %Z0,400000";
  }
  [(set (attr "length")
	(if_then_else (match_operand 2 "const_int_operand" "")
		      (if_then_else
		       (ge (symbol_ref "INTVAL (operands[2])") (const_int 36))
		       (const_int 3)
		       (const_int 4))
		      (const_int 5)))])

(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"))))]
  "!TARGET_71BIT"
  "lshc %0,%3(%2)")

(define_insn "*LSHC_left_plus_71bit"
  [(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"))))]
  "TARGET_71BIT"
  "lsh %Z0,1\;lshc %0,%3(%2)\;lsh %Z0,-1\;tlne %0,400000\;%_tlo %Z0,400000"
  [(set_attr "length" "5")])

(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))))]
  ""
  "if (!TARGET_71BIT)
     {
       HOST_WIDE_INT mask;
       /*rtx op0hi = gen_rtx_SUBREG (SImode, operands[0], 0);
       rtx op0lo = gen_rtx_SUBREG (SImode, operands[0], 4);*/
       rtx temp = gen_reg_rtx (SImode);
       rtx label;
	

       if (GET_CODE (operands[2]) == CONST_INT)
	 {
	   int n = INTVAL (operands[2]);
	   if (n <= 35)
	     {
	       label = gen_label_rtx ();
	       mask = (HOST_WIDE_INT)1 << (35 - n);
	       emit_insn (gen_lshrdi3 (operands[0], operands[1], operands[2]));
	       emit_jump_insn (gen_test_and_skip (gen_rtx_EQ (VOIDmode,
							      NULL_RTX,
							      NULL_RTX),
						  gen_rtx_SUBREG (SImode,
								  operands[0],
								  0),
						  gen_int_mode (mask, SImode),
						  label));
	       mask = ~(mask - 1);
	       if (n != 17 && n != 35)
		 mask <<= 1;
	       emit_insn (gen_iorsi3 (gen_rtx_SUBREG (SImode, operands[0], 0),
				      gen_rtx_SUBREG (SImode, operands[0], 0),
				      gen_int_mode (mask, SImode)));
	       emit_label (label);
	     }
	   else if (n == 36)
	     /*{
	       emit_insn (gen_ashrsi3 (gen_rtx_SUBREG (SImode, operands[0], 0),
				       gen_rtx_SUBREG (SImode, operands[1], 0),
				       GEN_INT (35)));
	       emit_move_insn (gen_rtx_SUBREG (SImode, operands[0], 4),
			       gen_rtx_SUBREG (SImode, operands[1], 0));
	     }*/
	     /*{
	       emit_move_insn (gen_rtx_SUBREG (SImode, operands[0], 4),
			       gen_rtx_SUBREG (SImode, operands[1], 0));
	       emit_insn (gen_ashrsi3 (gen_rtx_SUBREG (SImode, operands[0], 0),
				       gen_rtx_SUBREG (SImode, operands[1], 0),
				       GEN_INT (35)));
	     }*/
	     emit_insn (gen_ashrdi3_36 (operands[0], operands[1]));
	   else if (n >= 71 && !optimize_size)
	     emit_insn (gen_sign_extension_di (operands[0], operands[1]));
	   else
	     emit_insn (gen_ASHC (operands[0], operands[1], GEN_INT (1 - n)));
	   DONE;
	 }
	 
       /* Sequence adapted from Hacker's Delight, section 2-6.  */
       emit_insn (gen_ashrsi3 (temp, gen_rtx_SUBREG (SImode, operands[1], 0),
			       GEN_INT (35)));
       /*emit_move_insn (operands[0], operands[1]);
       emit_insn (gen_xorsi3 (op0hi, op0hi, temp));
       emit_insn (gen_xorsi3 (op0lo, op0lo, temp));*/
       emit_insn (gen_xordisi3 (operands[0], operands[1], temp));
       emit_insn (gen_lshrdi3 (operands[0], operands[0], operands[2]));
       /*emit_insn (gen_xorsi3 (op0hi, op0hi, temp));
       emit_insn (gen_xorsi3 (op0lo, op0lo, temp));*/
       emit_insn (gen_xordisi3 (operands[0], operands[0], temp));

       DONE;
     }
   else if (GET_CODE (operands[2]) == CONST_INT)
     {
       emit_insn (gen_ASHC_right (operands[0], operands[1],
				  GEN_INT (-INTVAL (operands[2]))));
       DONE;
     }
   else
     operands[3] = gen_reg_rtx (SImode);")

(define_insn "ashrdi3_36"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
		     (const_int 36)))]
  "!TARGET_71BIT"
  "@
   move %Z0,%0\;ash %0,-43"
  [(set_attr "length" "2")])

(define_insn "sign_extension_di"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0,r")
		     (const_int 71)))]
  "!TARGET_71BIT"
  {
    if (which_alternative == 0)
      return "ash %0,-43\;move %Z0,%0";
    else if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
      return "ash %Z0,-43\;move %0,%Z0";
    else
      return "move %0,%1\;ash %0,-43\;move %Z0,%0";
  }
  [(set_attr "length" "2,3")])

(define_insn "ASHC_right"
  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0,0")
		     (neg:SI (match_operand:SI 2 "general_operand" "x,K,m"))))]
  "TARGET_71BIT"
  "@
   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")
		    (match_operand:SI 2 "const_int_operand" "K")]
		   UNSPEC_ASHC))]
  "!TARGET_71BIT"
  "ashc %0,%2")

(define_insn "*ASHC_right_plus"
  [(set (match_operand:DI 0 "register_operand" "=r")
	(ashiftrt: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")))))]
  "TARGET_71BIT"
  "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")))]
  "!TARGET_71BIT"
  "@
   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"))))]
  "!TARGET_71BIT"
  "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))))]
  "!TARGET_71BIT"
  "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"))))]
  "!TARGET_71BIT"
  "@
   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")))))]
  "!TARGET_71BIT"
  "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 "*ANDI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (and:SI (match_operand:SI 1 "register_operand" "x")
			(const_int RIGHT_HALF))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "andi %0,(%1)")
(define_insn "*ANDI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I"))
			(const_int RIGHT_HALF))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "andi %0,%2(%1)")
(define_insn "*TLZ_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (not:SI (ashift:SI (match_operand:SI 1 "register_operand" "x")
				   (const_int 18)))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "tlz %0,(%1)")
(define_insn "*TLZ_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (not:SI (plus:SI (mult:SI
				  (match_operand:SI 1 "register_operand" "x")
				  (const_int 262144))
				 (match_operand:SI 2 "const_int_operand" "L")))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'L')"
  "tlz %0,%S2(%1)")

(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 "*ANDCMI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (ior:SI (not:SI (match_operand:SI 1 "register_operand" "x"))
			(const_int LEFT_HALF))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "andcmi %0,(%1)")
(define_insn "*ANDCMI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (ior:SI (not:SI
			 (plus:SI
			  (match_operand:SI 1 "register_operand" "x")
			  (match_operand:SI 2 "const_int_operand" "I")))
			(const_int LEFT_HALF))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "andcmi %0,%2(%1)")

(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 "*XORI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (xor:SI (and:SI (match_operand:SI 1 "register_operand" "r")
			(const_int RIGHT_HALF))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "xori %0,(%1)")
(define_insn "*XORI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (xor:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
				 (match_operand:SI 2 "const_int_operand" "I"))
			(const_int RIGHT_HALF))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "xori %0,%2(%1)")
(define_insn "*TLC_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
			   (const_int 18))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "tlc %0,(%1)")
(define_insn "*TLC_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(xor:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "x")
				  (const_int 262144))
			 (match_operand:SI 2 "const_int_operand" "L"))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'L')"
  "tlc %0,%S2(%1)")

(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")

(define_insn "xordisi3"
  [(set (match_operand:DI 0 "register_operand" "=r")
        (xor:DI (match_operand:DI 1 "register_operand" "%0")
                (plus:DI
		 (ashift:DI
		  (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))
		  (const_int 36))
		 (zero_extend:DI (match_dup 2)))))]
  ""
  "xor %0,%2\;xor %Z0,%2")

;; 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 "*IORI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (and:SI (match_operand:SI 1 "register_operand" "x")
			(const_int RIGHT_HALF))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "iori %0,(%1)")
(define_insn "*IORI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I"))
			(const_int RIGHT_HALF))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "iori %0,%2(%1)")
(define_insn "*TLO_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "x")
			   (const_int 18))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "tlo %0,(%1)")
(define_insn "*TLO_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(ior:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "x")
				  (const_int 262144))
			 (match_operand:SI 2 "const_int_operand" "L"))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'L')"
  "tlo %0,%S2(%1)")

(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 "*ANDCBI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (not:SI (and:SI (match_operand:SI 1 "register_operand" "x")
				(const_int RIGHT_HALF)))
		(not:SI (match_operand:SI 2 "register_operand" "0"))))]
  ""
  "andcbi %0,(%1)")
(define_insn "*ANDCBI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(and:SI (not:SI (and:SI
			 (plus:SI
			  (match_operand:SI 2 "register_operand" "x")
			  (match_operand:SI 3 "const_int_operand" "I"))
			 (const_int RIGHT_HALF)))
		(not:SI (match_operand:SI 1 "register_operand" "0"))))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[3]), 'I')"
  "andcbi %0,%3(%2)")

(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 "*EQVI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(not:SI (xor:SI (and:SI (match_operand:SI 1 "register_operand" "x")
				(const_int RIGHT_HALF))
			(match_operand:SI 2 "register_operand" "0"))))]
  ""
  "eqvi %0,(%1)")
(define_insn "*EQVI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
	(not:SI (xor:SI (and:SI (plus:SI
				 (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I"))
				(const_int RIGHT_HALF))
			(match_operand:SI 3 "register_operand" "0"))))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "eqvi %0,%2(%1)")

(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")

;; SETCMI is done with ORCBI.

;; 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 "*ORCMI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (ior:SI (not:SI (match_operand:SI 1 "register_operand" "x"))
			(const_int LEFT_HALF))
		(match_operand:SI 2 "register_operand" "0")))]
  ""
  "orcmi %0,(%1)")
(define_insn "*ORCMI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (ior:SI (not:SI (plus:SI
				 (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I")))
			(const_int LEFT_HALF))
		(match_operand:SI 3 "register_operand" "0")))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  "orcmi %0,%2(%1)")

(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 "*ORCBI_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (not:SI (and:SI (match_operand:SI 1 "register_operand" "x")
				(const_int RIGHT_HALF)))
		(not:SI (match_operand:SI 2 "register_operand" "0"))))]
  ""
  "orcbi %0,(%1)")
(define_insn "*ORCBI_const_plus_reg"
  [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (not:SI (and:SI (plus:SI
				 (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I"))
				(const_int RIGHT_HALF)))
		(not:SI (match_operand:SI 3 "register_operand" "0"))))]
  ""
  "orcbi %0,%2(%1)")

(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]));
       if (!flag_unsafe_math_optimizations)
	 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 (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_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_insn "*call_mem1"
  [(call (match_operand:SI 0 "memory_operand" "m")
	 (match_operand:SI 1 "general_operand" "g"))]
  ""
  {
    if (pdp10_output_call_as_jrst_p (insn))
      return "jrst @%0";
    else
      return "pushj 17,@%0";
  })

(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_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_insn "*call_value_mem3"
  [(set (match_operand 0 "register_operand" "=r")
;	(call (mem:SI (match_operand:SI 1 "address_operand" "a"))
	(call (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_expand "sibcall" ...)

; (define_expand "sibcall_value" ...)

(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 doesn't 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 the table is in .rodata located in another section.
;  (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 "cmpdi"
;;  [(set (cc0) (compare (match_operand:DI 0 "register_operand" "")
;;                       (match_operand:DI 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;")

;; KCC generates this for double x, y:
;; x == y:
;;	CAMN x+1,y+1		
;;	 CAME x,y
;;	  ;here if false
;; x < y:			x<y	x==y	x>y
;;	CAML x,y		?	false	false
;;	 CAMGE x+1,y+1		false	true	?
;;	  CAMLE x,y		true		false
;;	   ;here if false	no	yes	yes
;; x <= y:
;;	CAML x,y		?	false	false
;;	 CAMG x+1,y+1		false	false	?
;;	  CAMLE x,y		true	true	false
;;	   ;here if false	no	no	yes
;; These may also work for long long after adaptions.

;; To compare a double against zero:
;; x < 0:
;;	JUMPL x,label
;;	;here if false
;; x >= 0:
;;	JUMPGE x,label
;;	;here if false
;; x <= 0:			x<0	x==0	x>0
;;	JUMPL x,label		true	false	false
;;	 SKIPN x			false
;;	  JUMPE x+1,label		true
;;	   ;here if false
;; x > 0:
;;	JUMPG x,label		false	false	maybe
;;	 SKIPL x		true	false	false
;;	  JUMPG x+1,label		false	true
;;	   ;here if false

(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 - len);
    /* 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\;jrst %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)))]
  ""
  "if (pdp10_generate_cbranchdi (NE, pdp10_compare_op0, pdp10_compare_op1))
     DONE;
   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,%F0",
      "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 (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 "*CAI_reg"
  [(set (pc)
	(if_then_else (match_operator 0 "comparison_operator"
		       [(and:SI (match_operand:SI 1 "register_operand" "x")
				(const_int RIGHT_HALF))
		        (match_operand:SI 2 "register_operand" "r")])
		      (label_ref (match_operand 3 "" ""))
		      (pc)))]
  ""
  {
    pdp10_remove_unnecessary_label (insn, operands[3]);
    if (get_attr_length (insn) == 1)
      return "cai%0 %2,(%1)";
    else
      {
	/* Reverse the skip condition and output a JRST.  */
	output_asm_insn ("cai%R0 %2,(%1)", operands);
	return pdp10_output_jrst (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 "*CAI_const_plus_reg"
  [(set (pc)
	(if_then_else (match_operator 0 "comparison_operator"
		       [(and:SI (plus:SI
				 (match_operand:SI 1 "register_operand" "x")
				 (match_operand:SI 2 "const_int_operand" "I"))
				(const_int RIGHT_HALF))
		        (match_operand:SI 3 "register_operand" "r")])
		      (label_ref (match_operand 4 "" ""))
		      (pc)))]
  "pdp10_const_ok_for_letter_p (INTVAL (operands[2]), 'I')"
  {
    pdp10_remove_unnecessary_label (insn, operands[4]);
    if (get_attr_length (insn) == 1)
      return "cai%0 %3,%2(%1)";
    else
      {
	/* Reverse the skip condition and output a JRST.  */
	output_asm_insn ("cai%R0 %3,%2(%1)", operands);
	return pdp10_output_jrst (operands[4]);
      }
  }
  [(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 "*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" "R,R,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,%F0",	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,%F0";
    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 (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 (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 (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[2]);
	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 (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 (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 ();
  })

;; Allocate stack space, and return the word address of the allocated
;; memory.
(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, 1);
     rtx y, z = gen_reg_rtx (Pmode);
     if (GET_CODE (operands[1]) == CONST_INT)
       y = GEN_INT ((INTVAL (operands[1]) + 3) / 4);
     else
       {
	 y = gen_reg_rtx (Pmode);
	 emit_insn (gen_addsi3 (y, operands[1], GEN_INT (3)));
	 emit_insn (gen_ASH_right (y, y, GEN_INT (-2)));
       }
     emit_move_insn (z,
		     gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_ADDRESS));
     emit_move_insn (operands[0], z);
     emit_insn (pdp10_gen_stack_adjust (y));
     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))"
  ;"peep2_reg_dead_p (2, operands[0]) && ..."
  [(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])"
  ;"peep2_reg_dead_p (0, 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])"
  ;"peep2_reg_dead_p (0, 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:SI (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]))"
  ;"peep2_reg_dead_p (1, 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 "";
  })
