From 17168d5fdc587650225815db1669673abf4e6cc3 Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Thu, 30 Jun 2016 12:48:08 +0200 Subject: [PATCH] Add "GCC Machine Description" language. --- lib/linguist/heuristics.rb | 8 + lib/linguist/languages.yml | 7 + samples/GCC Machine Description/pdp10.md | 6665 ++++++++++++++++++++++ 3 files changed, 6680 insertions(+) create mode 100644 samples/GCC Machine Description/pdp10.md diff --git a/lib/linguist/heuristics.rb b/lib/linguist/heuristics.rb index 55703405..6f4ff997 100644 --- a/lib/linguist/heuristics.rb +++ b/lib/linguist/heuristics.rb @@ -239,6 +239,14 @@ module Linguist end end + disambiguate ".md" do |data| + if /^[-a-z0-9=#!\*\[|]/i.match(data) + Language["Markdown"] + elsif /^(;;|\(define_)/.match(data) + Language["GCC machine description"] + end + end + disambiguate ".ml" do |data| if /(^\s*module)|let rec |match\s+(\S+\s)+with/.match(data) Language["OCaml"] diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index fcf6becf..ea23d6e7 100755 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -1182,6 +1182,13 @@ GAS: tm_scope: source.assembly ace_mode: assembly_x86 +GCC Machine Description: + type: programming + extensions: + - .md + tm_scope: source.lisp + ace_mode: lisp + GDScript: type: programming extensions: diff --git a/samples/GCC Machine Description/pdp10.md b/samples/GCC Machine Description/pdp10.md new file mode 100644 index 00000000..7c0e2523 --- /dev/null +++ b/samples/GCC Machine Description/pdp10.md @@ -0,0 +1,6665 @@ +;;- Machine description for the PDP-10. +;; Copyright (C) 2001, 2002 Lars Brinkhoff. +;; Contributed by Lars Brinkhoff , 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") + +(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: xy +;; 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\;%_%; 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 ""; + })