aboutsummaryrefslogtreecommitdiff
path: root/gcc-1.40/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-1.40/config')
-rw-r--r--gcc-1.40/config/alliant.md2784
-rw-r--r--gcc-1.40/config/convex.md1266
-rw-r--r--gcc-1.40/config/i386.md2021
-rw-r--r--gcc-1.40/config/i860.md2046
-rw-r--r--gcc-1.40/config/m68k.md4156
-rw-r--r--gcc-1.40/config/m88k.md2273
-rw-r--r--gcc-1.40/config/mips.md1957
-rw-r--r--gcc-1.40/config/ns32k.md2636
-rw-r--r--gcc-1.40/config/out-alliant.c291
-rw-r--r--gcc-1.40/config/out-convex.c219
-rw-r--r--gcc-1.40/config/out-i386.c1418
-rw-r--r--gcc-1.40/config/out-i860.c1507
-rw-r--r--gcc-1.40/config/out-m68k.c560
-rw-r--r--gcc-1.40/config/out-m88k.c605
-rw-r--r--gcc-1.40/config/out-mips.c1086
-rw-r--r--gcc-1.40/config/out-ns32k.c575
-rw-r--r--gcc-1.40/config/out-pyr.c849
-rw-r--r--gcc-1.40/config/out-sparc.c2092
-rw-r--r--gcc-1.40/config/out-spur.c316
-rw-r--r--gcc-1.40/config/out-tahoe.c550
-rw-r--r--gcc-1.40/config/out-vax.c152
-rw-r--r--gcc-1.40/config/pyr.md1377
-rw-r--r--gcc-1.40/config/sparc.md2370
-rw-r--r--gcc-1.40/config/spur.md1119
-rw-r--r--gcc-1.40/config/tahoe.md1497
-rw-r--r--gcc-1.40/config/tm-3b1.h482
-rw-r--r--gcc-1.40/config/tm-3b1g.h63
-rw-r--r--gcc-1.40/config/tm-aix386.h129
-rw-r--r--gcc-1.40/config/tm-alliant.h1440
-rw-r--r--gcc-1.40/config/tm-altos3068.h107
-rw-r--r--gcc-1.40/config/tm-apollo68.h177
-rw-r--r--gcc-1.40/config/tm-att386.h244
-rw-r--r--gcc-1.40/config/tm-bsd386.h202
-rw-r--r--gcc-1.40/config/tm-compaq.h39
-rw-r--r--gcc-1.40/config/tm-conv1os7.h6
-rw-r--r--gcc-1.40/config/tm-conv2os7.h6
-rw-r--r--gcc-1.40/config/tm-convex.h1034
-rw-r--r--gcc-1.40/config/tm-convex1.h24
-rw-r--r--gcc-1.40/config/tm-convex2.h24
-rw-r--r--gcc-1.40/config/tm-decstatn.h27
-rw-r--r--gcc-1.40/config/tm-delta68k.h486
-rw-r--r--gcc-1.40/config/tm-encore.h202
-rw-r--r--gcc-1.40/config/tm-genix.h163
-rw-r--r--gcc-1.40/config/tm-harris.h96
-rw-r--r--gcc-1.40/config/tm-hp9k2bsd.h53
-rw-r--r--gcc-1.40/config/tm-hp9k310.h32
-rw-r--r--gcc-1.40/config/tm-hp9k310g.h12
-rw-r--r--gcc-1.40/config/tm-hp9k320.h598
-rw-r--r--gcc-1.40/config/tm-hp9k320g.h12
-rw-r--r--gcc-1.40/config/tm-hp9k3bsd.h36
-rw-r--r--gcc-1.40/config/tm-i386.h1088
-rw-r--r--gcc-1.40/config/tm-i386esix.h36
-rw-r--r--gcc-1.40/config/tm-i386gas.h106
-rw-r--r--gcc-1.40/config/tm-i386isc.h24
-rw-r--r--gcc-1.40/config/tm-i386sco.h39
-rw-r--r--gcc-1.40/config/tm-i386v.h86
-rw-r--r--gcc-1.40/config/tm-i386v4.h62
-rw-r--r--gcc-1.40/config/tm-i386vgas.h121
-rw-r--r--gcc-1.40/config/tm-i860.h1228
-rw-r--r--gcc-1.40/config/tm-i860bsdg.h4
-rw-r--r--gcc-1.40/config/tm-i860g.h4
-rw-r--r--gcc-1.40/config/tm-iris.h48
-rw-r--r--gcc-1.40/config/tm-isi68-nfp.h5
-rw-r--r--gcc-1.40/config/tm-isi68.h79
-rw-r--r--gcc-1.40/config/tm-m68k.h1643
-rw-r--r--gcc-1.40/config/tm-m88k.h1128
-rw-r--r--gcc-1.40/config/tm-mips-bsd.h3
-rw-r--r--gcc-1.40/config/tm-mips-news.h19
-rw-r--r--gcc-1.40/config/tm-mips-sysv.h5
-rw-r--r--gcc-1.40/config/tm-mips.h2309
-rw-r--r--gcc-1.40/config/tm-news.h408
-rw-r--r--gcc-1.40/config/tm-newsgas.h7
-rw-r--r--gcc-1.40/config/tm-next.h98
-rw-r--r--gcc-1.40/config/tm-ns32k.h1457
-rw-r--r--gcc-1.40/config/tm-pyr.h1406
-rw-r--r--gcc-1.40/config/tm-seq386.h79
-rw-r--r--gcc-1.40/config/tm-sequent.h110
-rw-r--r--gcc-1.40/config/tm-sparc.h1435
-rw-r--r--gcc-1.40/config/tm-spur.h1033
-rw-r--r--gcc-1.40/config/tm-sun2.h67
-rw-r--r--gcc-1.40/config/tm-sun2os4.h57
-rw-r--r--gcc-1.40/config/tm-sun3-nfp.h5
-rw-r--r--gcc-1.40/config/tm-sun3.h186
-rw-r--r--gcc-1.40/config/tm-sun386.h218
-rw-r--r--gcc-1.40/config/tm-sun386i.h105
-rw-r--r--gcc-1.40/config/tm-sun3mach.h8
-rw-r--r--gcc-1.40/config/tm-sun3os3.h5
-rw-r--r--gcc-1.40/config/tm-sun3os3nf.h5
-rw-r--r--gcc-1.40/config/tm-sun4os3.h15
-rw-r--r--gcc-1.40/config/tm-tahoe.h850
-rw-r--r--gcc-1.40/config/tm-tower-as.h616
-rw-r--r--gcc-1.40/config/tm-tower.h100
-rw-r--r--gcc-1.40/config/tm-ultrix.h7
-rw-r--r--gcc-1.40/config/tm-vax.h1080
-rw-r--r--gcc-1.40/config/tm-vaxv.h62
-rw-r--r--gcc-1.40/config/tm-vms.h117
-rw-r--r--gcc-1.40/config/vax.md2166
-rw-r--r--gcc-1.40/config/xm-3b1.h7
-rw-r--r--gcc-1.40/config/xm-aix386.h53
-rw-r--r--gcc-1.40/config/xm-alliant.h48
-rw-r--r--gcc-1.40/config/xm-altos3068.h7
-rw-r--r--gcc-1.40/config/xm-convex.h61
-rw-r--r--gcc-1.40/config/xm-delta68k.h8
-rw-r--r--gcc-1.40/config/xm-genix.h9
-rw-r--r--gcc-1.40/config/xm-hp9k320.h13
-rw-r--r--gcc-1.40/config/xm-i386.h42
-rw-r--r--gcc-1.40/config/xm-i386v.h47
-rw-r--r--gcc-1.40/config/xm-i860.h38
-rw-r--r--gcc-1.40/config/xm-iris.h7
-rw-r--r--gcc-1.40/config/xm-m68k.h43
-rw-r--r--gcc-1.40/config/xm-m88k.h37
-rw-r--r--gcc-1.40/config/xm-mips.h44
-rw-r--r--gcc-1.40/config/xm-ns32k.h41
-rw-r--r--gcc-1.40/config/xm-pyr.h43
-rw-r--r--gcc-1.40/config/xm-sparc.h44
-rw-r--r--gcc-1.40/config/xm-spur.h37
-rw-r--r--gcc-1.40/config/xm-sun386i.h48
-rw-r--r--gcc-1.40/config/xm-tahoe.h57
-rw-r--r--gcc-1.40/config/xm-tower.h8
-rw-r--r--gcc-1.40/config/xm-umips.h44
-rw-r--r--gcc-1.40/config/xm-vax.h42
-rw-r--r--gcc-1.40/config/xm-vaxv.h9
-rw-r--r--gcc-1.40/config/xm-vms.h61
123 files changed, 62053 insertions, 0 deletions
diff --git a/gcc-1.40/config/alliant.md b/gcc-1.40/config/alliant.md
new file mode 100644
index 0000000..0dffea3
--- /dev/null
+++ b/gcc-1.40/config/alliant.md
@@ -0,0 +1,2784 @@
+;;- Machine description for GNU C compiler for Alliant FX systems
+;; Copyright (C) 1989 Free Software Foundation, Inc.
+;; Adapted from m68k.md by Paul Petersen (petersen@uicsrd.csrd.uiuc.edu)
+;; and Joe Weening (weening@gang-of-four.stanford.edu).
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- instruction definitions
+
+;;- @@The original PO technology requires these to be ordered by speed,
+;;- @@ so that assigner will pick the fastest.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- When naming insn's (operand 0 of define_insn) be careful about using
+;;- names from other targets machine descriptions.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+;;- 'a' one of the address registers can be used.
+;;- 'd' one of the data registers can be used.
+;;- 'f' one of the CE floating point registers can be used
+;;- 'r' either a data or an address register can be used.
+
+;;- Immediate integer operand constraints:
+;;- 'I' 1 .. 8
+;;- 'J' -32768 .. 32767
+;;- 'K' -128 .. 127
+;;- 'L' -8 .. -1
+
+;;- Some remnants of constraint codes for the m68k ('x','y','G','H')
+;;- may remain in the insn definitions.
+
+;;- Some of these insn's are composites of several Alliant op codes.
+;;- The assembler (or final @@??) insures that the appropriate one is
+;;- selected.
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+ if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+ return \"tst%.l %0\";
+ /* If you think that the 68020 does not support tstl a0,
+ reread page B-167 of the 68020 manual more carefully. */
+ /* On an address reg, cmpw may replace cmpl. */
+ return \"cmp%.w %#0,%0\";
+}")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+ if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+ return \"tst%.w %0\";
+ return \"cmp%.w %#0,%0\";
+}")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "dm"))]
+ ""
+ "tst%.b %0")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "nonimmediate_operand" "fm"))]
+ "TARGET_CE"
+ "*
+{
+ cc_status.flags = CC_IN_FP;
+ return \"ftest%.s %0\";
+}")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "nonimmediate_operand" "fm"))]
+ "TARGET_CE"
+ "*
+{
+ cc_status.flags = CC_IN_FP;
+ return \"ftest%.d %0\";
+}")
+
+;; compare instructions.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+;; A composite of the cmp, cmpa, & cmpi m68000 op codes.
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "rKs,mr,>")
+ (match_operand:SI 1 "general_operand" "mr,Ksr,>")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.l %1,%0\";
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cmp%.l %d0,%d1\";
+ }
+ return \"cmp%.l %d1,%d0\";
+}")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "rnm,d,n,m")
+ (match_operand:HI 1 "general_operand" "d,rnm,m,n")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.w %1,%0\";
+ if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+ return \"cmp%.w %d0,%d1\";
+ }
+ return \"cmp%.w %d1,%d0\";
+}")
+
+(define_insn "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "dn,md,>")
+ (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.b %1,%0\";
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cmp%.b %d0,%d1\";
+ }
+ return \"cmp%.b %d1,%d0\";
+}")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "nonimmediate_operand" "f,m")
+ (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ cc_status.flags = CC_IN_FP;
+ if (FP_REG_P (operands[0]))
+ return \"fcmp%.d %1,%0\";
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.d %0,%1\";
+}")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "nonimmediate_operand" "f,m")
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ cc_status.flags = CC_IN_FP;
+ if (FP_REG_P (operands[0]))
+ return \"fcmp%.s %1,%0\";
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.s %0,%1\";
+}")
+
+;; Recognizers for btst instructions.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; The following two patterns are like the previous two
+;; except that they use the fact that bit-number operands
+;; are automatically masked to 3 or 5 bits.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (and:SI
+ (match_operand:SI 1 "general_operand" "d")
+ (const_int 7)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (and:SI
+ (match_operand:SI 1 "general_operand" "d")
+ (const_int 31)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) < 8"
+ "*
+{
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+}")
+
+(define_insn ""
+ ;; The constraint "o,d" here means that a nonoffsettable memref
+ ;; will match the first alternative, and its address will be reloaded.
+ ;; Copying the memory contents into a reg would be incorrect if the
+ ;; bit position is over 7.
+ [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "o,d")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i,i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 15 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 15);
+}")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 31 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 31);
+}")
+
+(define_insn ""
+ [(set (cc0) (subreg:SI (lshiftrt:QI (match_operand:QI 0 "nonimmediate_operand" "dm")
+ (const_int 7))
+ 0))]
+ ""
+ "*
+{
+ cc_status.flags = CC_Z_IN_NOT_N | CC_NOT_NEGATIVE;
+ return \"tst%.b %0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "dm")))
+ (match_operand:SI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) < 0x100
+ && exact_log2 (INTVAL (operands[1])) >= 0)"
+ "*
+{ register int log = exact_log2 (INTVAL (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, log);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+}")
+
+;; move instructions
+
+;; A special case in which it is not desirable
+;; to reload the constant into a data register.
+(define_insn ""
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "general_operand" "J"))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -0x8000
+ && INTVAL (operands[1]) < 0x8000"
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clr%.l %0\";
+ return \"pea %a1\";
+}")
+
+;This is never used.
+;(define_insn "swapsi"
+; [(set (match_operand:SI 0 "general_operand" "r")
+; (match_operand:SI 1 "general_operand" "r"))
+; (set (match_dup 1) (match_dup 0))]
+; ""
+; "exg %1,%0")
+
+;; Special case of fullword move when source is zero.
+;; The reason this is special is to avoid loading a zero
+;; into a data reg with moveq in order to store it elsewhere.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (const_int 0))]
+ ""
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ return \"sub%.l %0,%0\";
+ return \"clr%.l %0\";
+}")
+
+;; General case of fullword move. The register constraints
+;; force integer constants in range for a moveq to be reloaded
+;; if they are headed for memory.
+(define_insn "movsi"
+ ;; Notes: make sure no alternative allows g vs g.
+ ;; We don't allow f-regs since fixed point cannot go in them.
+ ;; We do allow y and x regs since fixed point is allowed in them.
+ [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
+ (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM))
+ return \"clr%.l %0\";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ return \"moveq %1,%0\";
+ else if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"mov%.w %1,%0\";
+ else if (push_operand (operands[0], SImode)
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"pea %a1\";
+ }
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && push_operand (operands[0], SImode))
+ return \"pea %a1\";
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && ADDRESS_REG_P (operands[0]))
+ return \"lea %a1,%0\";
+ return \"mov%.l %1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM))
+ return \"clr%.w %0\";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+ return \"moveq %1,%0\";
+ }
+ else if (INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"mov%.w %1,%0\";
+ }
+ else if (CONSTANT_P (operands[1]))
+ return \"mov%.l %1,%0\";
+ /* Recognize the insn before a tablejump, one that refers
+ to a table of offsets. Such an insn will need to refer
+ to a label on the insn. So output one. Use the label-number
+ of the table of offsets to generate this label. */
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+ || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF)
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS)
+ {
+ rtx labelref;
+ if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF)
+ labelref = XEXP (XEXP (operands[1], 0), 0);
+ else
+ labelref = XEXP (XEXP (operands[1], 0), 1);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+ }
+ return \"mov%.w %1,%0\";
+}")
+
+(define_insn "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (match_operand:HI 1 "general_operand" "rmn"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM))
+ return \"clr%.w %0\";
+ }
+ return \"mov%.w %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a")
+ (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))]
+ ""
+ "*
+{
+ rtx xoperands[4];
+ if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
+ {
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx (MEM, QImode,
+ gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
+ xoperands[3] = stack_pointer_rtx;
+ /* Just pushing a byte puts it in the high byte of the halfword. */
+ /* We must put it in the low half, the second byte. */
+ output_asm_insn (\"subq%.w %#2,%3\;mov%.b %1,%2\", xoperands);
+ return \"mov%.w %+,%0\";
+ }
+ if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx (MEM, QImode,
+ gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
+ xoperands[3] = stack_pointer_rtx;
+ output_asm_insn (\"mov%.w %1,%-\;mov%.b %2,%0\;addq%.w %#2,%3\", xoperands);
+ return \"\";
+ }
+ if (operands[1] == const0_rtx)
+ return \"clr%.b %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ return \"st %0\";
+ if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
+ return \"mov%.l %1,%0\";
+ if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
+ return \"mov%.w %1,%0\";
+ return \"mov%.b %1,%0\";
+}")
+
+(define_insn "movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (match_operand:QI 1 "general_operand" "dmn"))]
+ ""
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clr%.b %0\";
+ return \"mov%.b %1,%0\";
+}")
+
+;; Floating-point moves on a CE are faster using an FP register than
+;; with movl instructions. (Especially for double floats, but also
+;; for single floats, even though it takes an extra instruction.) But
+;; on an IP, the FP registers are simulated and so should be avoided.
+;; We do this by using define_expand for movsf and movdf, and using
+;; different constraints for each target type. The constraints for
+;; TARGET_CE allow general registers because they sometimes need to
+;; hold floats, but they are not preferable.
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "nonimmediate_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f,m,!*r,!f*m")
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f,f*r*m,*r"))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.s %1,%0\";
+ if (REG_P (operands[1]))
+ return \"mov%.l %1,%-\;fmove%.s %+,%0\";
+ return \"fmove%.s %1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ return \"fmove%.s %1,%-\;mov%.l %+,%0\";
+ return \"fmove%.s %1,%0\";
+ }
+ return \"mov%.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=frm")
+ (match_operand:SF 1 "nonimmediate_operand" "frm"))]
+ "!TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.s %1,%0\";
+ if (REG_P (operands[1]))
+ return \"mov%.l %1,%-\;fmove%.s %+,%0\";
+ return \"fmove%.s %1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ return \"fmove%.s %1,%-\;mov%.l %+,%0\";
+ return \"fmove%.s %1,%0\";
+ }
+ return \"mov%.l %1,%0\";
+}")
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "nonimmediate_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f,m,!*r,!f*m")
+ (match_operand:DF 1 "nonimmediate_operand" "fm,f,f*r*m,*r"))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"mov%.l %1,%-\", xoperands);
+ output_asm_insn (\"mov%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+ }
+ return \"fmove%.d %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %1,%-\;mov%.l %+,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"mov%.l %+,%0\";
+ }
+ return \"fmove%.d %1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=frm")
+ (match_operand:DF 1 "nonimmediate_operand" "frm"))]
+ "!TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"mov%.l %1,%-\", xoperands);
+ output_asm_insn (\"mov%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+ }
+ return \"fmove%.d %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %1,%-\;mov%.l %+,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"mov%.l %+,%0\";
+ }
+ return \"fmove%.d %1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>")
+ (match_operand:DI 1 "general_operand" "r,m,roi<>"))]
+ ""
+ "*
+{
+ return output_move_double (operands);
+}
+")
+
+;; This goes after the move instructions
+;; because the move instructions are better (require no spilling)
+;; when they can apply. It goes before the add/sub insns
+;; so we will prefer it to them.
+
+(define_insn "pushasi"
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "pea %a1")
+
+;; truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:SI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ return \"mov%.l %1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 3);
+ return \"mov%.b %1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:HI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG
+ && (GET_CODE (operands[1]) == MEM
+ || GET_CODE (operands[1]) == CONST_INT))
+ return \"mov%.w %1,%0\";
+ if (GET_CODE (operands[0]) == REG)
+ return \"mov%.l %1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 1);
+ return \"mov%.b %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm,d")
+ (truncate:HI
+ (match_operand:SI 1 "general_operand" "roJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ return \"mov%.l %1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 2);
+ return \"mov%.w %1,%0\";
+}")
+
+;; zero extension instructions
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:HI (match_dup 0) 0))
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "operands[1] = make_safe_from (operands[1], operands[0]);")
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:QI (match_dup 0) 0))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "operands[1] = make_safe_from (operands[1], operands[0]);")
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:QI (match_dup 0) 0))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ " operands[1] = make_safe_from (operands[1], operands[0]); ")
+
+;; Patterns to recognize zero-extend insns produced by the combiner.
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFFFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"mov%.w %1,%0\;and%.l %#0xFFFF,%0\";
+ return \"clr%.l %0\;mov%.w %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"mov%.w %1,%0\;clr%.w %0\";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.w %0\;mov%.w %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.w %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ return \"mov%.w %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=do<>")
+ (zero_extend:HI
+ (match_operand:QI 1 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.w %#0xFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"mov%.b %1,%0\;and%.w %#0xFF,%0\";
+ return \"clr%.w %0\;mov%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ if (REGNO (XEXP (XEXP (operands[0], 0), 0))
+ == STACK_POINTER_REGNUM)
+ return \"clr%.w %-\;mov%.b %1,%0\";
+ else
+ return \"mov%.b %1,%0\;clr%.b %0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.b %0\;mov%.b %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.b %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 1);
+ return \"mov%.b %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"mov%.b %1,%0\;and%.l %#0xFF,%0\";
+ return \"clr%.l %0\;mov%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ return \"clr%.l %0@-\;mov%.b %1,%0@(3)\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ return \"clr%.l %0@+\;mov%.b %1,%0@(-1)\";
+ }
+ else
+ {
+ output_asm_insn (\"clr%.l %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 3);
+ return \"mov%.b %1,%0\";
+ }
+}")
+
+;; sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=*d,a")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "0,rmn")))]
+ ""
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ return \"mov%.w %1,%0\";
+ return \"ext%.l %0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "ext%.w %0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "0")))]
+ "TARGET_68020"
+ "extb%.l %0")
+
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f,m")
+ (float_extend:DF
+ (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "fmovesd %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f,m")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "fmoveds %1,%0")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmovels %1,%0")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmoveld %1,%0")
+
+(define_insn "floathisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:HI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmovews %1,%0")
+
+(define_insn "floathidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:HI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmovewd %1,%0")
+
+(define_insn "floatqisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:QI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmovebs %1,%0")
+
+(define_insn "floatqidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:QI 1 "nonimmediate_operand" "dm")))]
+ "TARGET_CE"
+ "fmovebd %1,%0")
+
+;; Float-to-fix conversion insns.
+
+(define_insn "fix_truncsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovesb %1,%0")
+
+(define_insn "fix_truncsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovesw %1,%0")
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovesl %1,%0")
+
+(define_insn "fix_truncdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovedb %1,%0")
+
+(define_insn "fix_truncdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovedw %1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ "TARGET_CE"
+ "fmovedl %1,%0")
+
+;; add instructions
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,r,!a,!a")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,0,a,rJK")
+ (match_operand:SI 2 "general_operand" "dIKLs,mrIKLs,rJK,a")))]
+ ""
+ "*
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (!ADDRESS_REG_P (operands[1]))
+ {
+ rtx tmp = operands[1];
+
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+
+ /* These insns can result from reloads to access
+ stack slots over 64k from the frame pointer. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
+ return \"mov%.l %2,%0\;add%.l %1,%0\";
+ if (GET_CODE (operands[2]) == REG)
+ return \"lea %1@[%2:L:B],%0\";
+ else
+ return \"lea %1@(%c2),%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return (ADDRESS_REG_P (operands[0])
+ ? \"addq%.w %2,%0\"
+ : \"addq%.l %2,%0\");
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]));
+ return (ADDRESS_REG_P (operands[0])
+ ? \"subq%.w %2,%0\"
+ : \"subq%.l %2,%0\");
+ }
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ return \"add%.w %2,%0\";
+ }
+ return \"add%.l %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (plus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))]
+ ""
+ "add%.w %2,%0")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.w %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]));
+ return \"subq%.w %2,%0\";
+ }
+ }
+ return \"add%.w %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ ""
+ "add%.w %1,%0")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.b %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
+ return \"subq%.b %2,%0\";
+ }
+ }
+ return \"add%.b %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (plus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ ""
+ "add%.b %1,%0")
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%f")
+ (match_operand:DF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fadd%.d %2,%1,%0")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%f")
+ (match_operand:SF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fadd%.s %2,%1,%0")
+
+;; subtract instructions
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs")
+ (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))]
+ ""
+ "*
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"subq%.l %1,%0\;neg%.l %0\";
+ }
+ return \"sub%.l %1,%0\;neg%.l %0\";
+ }
+ /* This case is matched by J, but negating -0x8000
+ in an lea would give an invalid displacement.
+ So do this specially. */
+ if (INTVAL (operands[2]) == -0x8000)
+ return \"mov%.l %1,%0\;sub%.l %2,%0\";
+ return \"lea %1@(%n2),%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"subq%.l %2,%0\";
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ return \"sub%.w %2,%0\";
+ }
+ return \"sub%.l %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))]
+ ""
+ "sub%.w %2,%0")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ ""
+ "sub%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (minus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ ""
+ "sub%.w %1,%0")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "sub%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (minus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ ""
+ "sub%.b %1,%0")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (minus:DF (match_operand:DF 1 "nonimmediate_operand" "f,fm")
+ (match_operand:DF 2 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fsub%.d %2,%1,%0\";
+ return \"frsub%.d %1,%2,%0\";
+}")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (minus:SF (match_operand:SF 1 "nonimmediate_operand" "f,fm")
+ (match_operand:SF 2 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fsub%.s %2,%1,%0\";
+ return \"frsub%.s %1,%2,%0\";
+}")
+
+;; multiply instructions
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "muls %2,%0")
+
+(define_insn "mulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "muls %2,%0")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "muls%.l %2,%0")
+
+(define_insn "umulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "mulu %2,%0")
+
+(define_insn "umulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (umult:SI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "mulu %2,%0")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (umult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "mulu%.l %2,%0")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%f")
+ (match_operand:DF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fmul%.d %2,%1,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%f")
+ (match_operand:SF 2 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fmul%.s %2,%1,%0")
+
+;; divide instructions
+
+(define_insn "divhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (div:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "extl %0\;divs %2,%0")
+
+(define_insn "divhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (div:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "divs %2,%0")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "divs%.l %2,%0,%0")
+
+(define_insn "udivhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (udiv:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "and%.l %#0xFFFF,%0\;divu %2,%0")
+
+(define_insn "udivhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (udiv:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "divu %2,%0")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "divu%.l %2,%0,%0")
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "nonimmediate_operand" "f,fm")
+ (match_operand:DF 2 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fdiv%.d %2,%1,%0\";
+ return \"frdiv%.d %1,%2,%0\";
+}")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "nonimmediate_operand" "f,fm")
+ (match_operand:SF 2 "nonimmediate_operand" "fm,f")))]
+ "TARGET_CE"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fdiv%.s %2,%1,%0\";
+ return \"frdiv%.s %1,%2,%0\";
+}")
+
+;; Remainder instructions.
+
+(define_insn "modhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mod:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+ return \"extl %0\;divs %2,%0\;swap %0\";
+}")
+
+(define_insn "modhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mod:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+ return \"divs %2,%0\;swap %0\";
+}")
+
+(define_insn "umodhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umod:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+ return \"and%.l %#0xFFFF,%0\;divu %2,%0\;swap %0\";
+}")
+
+(define_insn "umodhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umod:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+ return \"divu %2,%0\;swap %0\";
+}")
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020"
+ "divs%.l %2,%0,%3")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020"
+ "divu%.l %2,%0,%3")
+
+;; logical-and instructions
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (operands[2] == const0_rtx)
+ return \"clr%.w %0\";
+ return \"and%.w %2,%0\";
+ }
+ return \"and%.l %2,%0\";
+}")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (and:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ ""
+ "and%.w %2,%0")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "and%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
+ "and%.w %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "dm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
+ "and%.b %1,%0")
+
+;; inclusive-or instructions
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
+ ""
+ "*
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ return \"or%.w %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
+ }
+ return \"bset %1,%0\";
+ }
+ return \"or%.l %2,%0\";
+}")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ ""
+ "or%.w %2,%0")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "or%.b %2,%0")
+
+;; xor instructions
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=do,m")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "di,dKs")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
+ {
+ if (! DATA_REG_P (operands[0]))
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ return \"eor%.w %2,%0\";
+ }
+ return \"eor%.l %2,%0\";
+}")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dn")))]
+ ""
+ "eor%.w %2,%0")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (xor:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "dn")))]
+ ""
+ "eor%.b %2,%0")
+
+;; negation instructions
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "neg%.l %0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "neg%.w %0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "neg%.b %0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fneg%.s %1,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fneg%.d %1,%0")
+
+;; Absolute value instructions
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fabs%.s %1,%0")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fabs%.d %1,%0")
+
+;; Square root instructions
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fsqrt%.s %1,%0")
+
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "fm")))]
+ "TARGET_CE"
+ "fsqrt%.d %1,%0")
+
+;; one complement instructions
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "not%.l %0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (not:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "not%.w %0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (not:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "not%.b %0")
+
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+ && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+ "*
+{
+ if (TARGET_68020)
+ return \"mov%.b %1,%0\;extb%.l %0\";
+ return \"mov%.b %1,%0\;ext%.w %0\;ext%.l %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+ && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+ "*
+{
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"mov%.b %1,%0\;and%.l %#0xFF,%0\";
+ return \"clr%.l %0\;mov%.b %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24))))]
+ "(GET_CODE (operands[0]) == CONST_INT
+ && (INTVAL (operands[0]) & ~0xff) == 0)"
+ "* cc_status.flags |= CC_REVERSED;
+ return \"cmp%.b %0,%1\";
+")
+
+(define_insn ""
+ [(set (cc0) (compare (lshiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+ (const_int 24))
+ (match_operand:QI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & ~0xff) == 0)"
+ "*
+ return \"cmp%.b %1,%0\";
+")
+
+(define_insn ""
+ [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24))))]
+ "(GET_CODE (operands[0]) == CONST_INT
+ && ((INTVAL (operands[0]) + 0x80) & ~0xff) == 0)"
+ "* cc_status.flags |= CC_REVERSED;
+ return \"cmp%.b %0,%1\";
+")
+
+(define_insn ""
+ [(set (cc0) (compare (ashiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+ (const_int 24))
+ (match_operand:QI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) + 0x80) & ~0xff) == 0)"
+ "*
+ return \"cmp%.b %1,%0\";
+")
+
+;; arithmetic shift instructions
+;; We don't need the shift memory by 1 bit instruction
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "asl%.l %2,%0")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (ashift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "asl%.w %2,%0")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ashift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "asl%.b %2,%0")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "asr%.l %2,%0")
+
+(define_insn "ashrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "asr%.w %2,%0")
+
+(define_insn "ashrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "asr%.b %2,%0")
+
+;; logical shift instructions
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.l %2,%0")
+
+(define_insn "lshlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (lshift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.w %2,%0")
+
+(define_insn "lshlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lshift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.b %2,%0")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.l %2,%0")
+
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.w %2,%0")
+
+(define_insn "lshrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.b %2,%0")
+
+;; rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (rotate:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "rol%.l %2,%0")
+
+(define_insn "rotlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (rotate:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "rol%.w %2,%0")
+
+(define_insn "rotlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (rotate:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "rol%.b %2,%0")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (rotatert:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "ror%.l %2,%0")
+
+(define_insn "rotrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (rotatert:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "ror%.w %2,%0")
+
+(define_insn "rotrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (rotatert:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "ror%.b %2,%0")
+
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do")
+ (match_operand:SI 1 "immediate_operand" "i")
+ (match_operand:SI 2 "immediate_operand" "i"))
+ (match_operand:SI 3 "general_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+ && (GET_CODE (operands[0]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
+ return \"bfins %3,[%c2,%c1]%0\";
+ }
+ else
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ if (GET_CODE (operands[3]) == MEM)
+ operands[3] = adj_offsettable_operand (operands[3],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[1]) == 8)
+ return \"mov%.b %3,%0\";
+ return \"mov%.w %3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=&d")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfextu [%c3,%c2]%1,%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ output_asm_insn (\"clrl %0\", operands);
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[2]) == 8)
+ return \"mov%.b %1,%0\";
+ return \"mov%.w %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfexts [%c3,%c2]%1,%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"mov%.b %1,%0\;extb%.l %0\";
+ return \"mov%.w %1,%0\;ext%.l %0\";
+}")
+
+;; Bit field instructions, general cases.
+;; "o,d" constraint causes a nonoffsettable memref to match the "o"
+;; so that its address is reloaded.
+
+(define_insn "extv"
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
+ (match_operand:SI 2 "general_operand" "di,di")
+ (match_operand:SI 3 "general_operand" "di,di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts [%c3,%c2]%1,%0")
+
+(define_insn "extzv"
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
+ (match_operand:SI 2 "general_operand" "di,di")
+ (match_operand:SI 3 "general_operand" "di,di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfextu [%c3,%c2]%1,%0")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
+ (match_operand 3 "immediate_operand" "i,i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[3]) == CONST_INT
+ && (INTVAL (operands[3]) == -1
+ || (GET_CODE (operands[1]) == CONST_INT
+ && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfchg [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset [%c2,%c1]%0\";
+}")
+
+(define_insn "insv"
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (match_operand:SI 3 "general_operand" "d,d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfins %3,[%c2,%c1]%0")
+
+;; Now recognize bit field insns that operate on registers
+;; (or at least were intended to do so).
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts [%c3,%c2]%1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfextu [%c3,%c2]%1,%0")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (match_operand:SI 3 "general_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ return \"bfins %3,[%c2,%c1]%0\";
+}")
+
+;; Special patterns for optimizing bit-field instructions.
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:QI
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:HI
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+;;; now handle the register cases
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:QI
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:HI
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst [%c2,%c1]%0\";
+}")
+
+(define_insn "seq"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
+")
+
+(define_insn "sne"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sne %0\", \"fsneq %0\", \"sne %0\");
+")
+
+(define_insn "sgt"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", \"and%.b %#0xc,%!\;sgt %0\");
+")
+
+(define_insn "sgtu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"shi %0\"; ")
+
+(define_insn "slt"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+
+(define_insn "sltu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"scs %0\"; ")
+
+(define_insn "sge"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+
+(define_insn "sgeu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"scc %0\"; ")
+
+(define_insn "sle"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sle %0\", \"fsle %0\", \"and%.b %#0xc,%!\;sle %0\");
+")
+
+(define_insn "sleu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"sls %0\"; ")
+
+;; Basic conditional jump instructions.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"jeq %l0\", \"fbeq %l0\", \"jeq %l0\");
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"jne %l0\", \"fbneq %l0\", \"jne %l0\");
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jgt %l0\", \"fbgt %l0\", \"and%.b %#0xc,%!\;jgt %l0\");
+")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ return \"jhi %l0\";
+")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jlt %l0\", \"fblt %l0\", \"jmi %l0\");
+")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ return \"jcs %l0\";
+")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jge %l0\", \"fbge %l0\", \"jpl %l0\");
+")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ return \"jcc %l0\";
+")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jle %l0\", \"fble %l0\", \"and%.b %#0xc,%!\;jle %l0\");
+")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+ return \"jls %l0\";
+")
+
+;; Negated conditional jump instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"jne %l0\", \"fbneq %l0\", \"jne %l0\");
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"jeq %l0\", \"fbeq %l0\", \"jeq %l0\");
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jle %l0\", \"fbngt %l0\", \"and%.b %#0xc,%!\;jle %l0\");
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ return \"jls %l0\";
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jge %l0\", \"fbnlt %l0\", \"jpl %l0\");
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ return \"jcc %l0\";
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jlt %l0\", \"fbnge %l0\", \"jmi %l0\");
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ return \"jcs %l0\";
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ OUTPUT_JUMP (\"jgt %l0\", \"fbnle %l0\", \"and%.b %#0xc,%!\;jgt %l0\");
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+ return \"jhi %l0\";
+")
+
+;; Subroutines of "casesi".
+
+(define_expand "casesi_1"
+ [(set (match_operand:SI 3 "general_operand" "")
+ (plus:SI (match_operand:SI 0 "general_operand" "")
+ ;; Note operand 1 has been negated!
+ (match_operand:SI 1 "immediate_operand" "")))
+ (set (cc0) (compare (match_operand:SI 2 "general_operand" "")
+ (match_dup 3)))
+ (set (pc) (if_then_else (ltu (cc0) (const_int 0))
+ (label_ref (match_operand 4 "" "")) (pc)))]
+ ""
+ "")
+
+(define_expand "casesi_2"
+ [(set (match_operand:SI 0 "" "") (mem:HI (match_operand:SI 1 "" "")))
+ ;; The USE here is so that at least one jump-insn will refer to the label,
+ ;; to keep it alive in jump_optimize.
+ (parallel [(set (pc)
+ (plus:SI (pc) (match_dup 0)))
+ (use (label_ref (match_operand 2 "" "")))])]
+ ""
+ "")
+
+;; Operand 0 is index (in bytes); operand 1 is minimum, operand 2 the maximum;
+;; operand 3 is CODE_LABEL for the table;
+;; operand 4 is the CODE_LABEL to go to if index out of range.
+(define_expand "casesi"
+ ;; We don't use these for generating the RTL, but we must describe
+ ;; the operands here.
+ [(match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "immediate_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand 3 "" "")
+ (match_operand 4 "" "")]
+ ""
+ "
+{
+ rtx table_elt_addr;
+ rtx index_diff;
+
+ operands[1] = negate_rtx (SImode, operands[1]);
+ index_diff = gen_reg_rtx (SImode);
+ /* Emit the first few insns. */
+ emit_insn (gen_casesi_1 (operands[0], operands[1], operands[2],
+ index_diff, operands[4]));
+ /* Construct a memory address. This may emit some insns. */
+ table_elt_addr
+ = memory_address_noforce
+ (HImode,
+ gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, index_diff,
+ gen_rtx (CONST_INT, VOIDmode, 2)),
+ gen_rtx (LABEL_REF, VOIDmode, operands[3])));
+ /* Emit the last few insns. */
+ emit_insn (gen_casesi_2 (gen_reg_rtx (HImode), table_elt_addr, operands[3]));
+ DONE;
+}")
+
+;; Recognize one of the insns resulting from casesi_2.
+(define_insn ""
+ [(set (pc)
+ (plus:SI (pc) (match_operand:HI 0 "general_operand" "r")))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+ return \"jmp pc@(2:B)[%0:W:B]\";
+")
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+ return \"jra %l0\";
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (plus:HI (match_operand:HI 0 "general_operand" "g")
+ (const_int -1))
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ return \"subq%.w %#1,%0\;jcc %l1\";
+ }
+ return \"subq%.w %#1,%0\;cmp%.w %#-1,%0\;jne %l1\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (plus:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int -1))
+ (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 (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq%.l %#1,%0\;jcc %l1\";
+ return \"subq%.l %#1,%0\;cmp%.l %#-1,%0\;jne %l1\";
+}")
+
+;; dbra patterns that use REG_NOTES info generated by strength_reduce.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "find_reg_note (insn, REG_NONNEG, 0)"
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq%.l %#1,%0\;jcc %l1\";
+ return \"subq%.l %#1,%0\;cmp%.l %#-1,%0\;jne %l1\";
+}")
+
+;; Call subroutine with no return value.
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "o")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ int size = XINT(operands[1],0);
+
+ if (size == 0)
+ output_asm_insn (\"sub%.l a0,a0\;jbsr %0\", operands);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode, size/4);
+ output_asm_insn (\"mov%.l sp,a0\;pea %a1\", xoperands);
+ output_asm_insn (\"jbsr %0\", operands);
+ size = size + 4;
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode, size);
+ if (size <= 8)
+ output_asm_insn (\"addq%.l %1,sp\", xoperands);
+ else if (size < 0x8000)
+ output_asm_insn (\"add%.w %1,sp\", xoperands);
+ else
+ output_asm_insn (\"add%.l %1,sp\", xoperands);
+ }
+ return \"mov%.l a6@(-4),a0\";
+}")
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:QI 1 "general_operand" "o")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ rtx xoperands[3];
+ int size = XINT(operands[2],0);
+
+ if (size == 0)
+ output_asm_insn(\"sub%.l a0,a0\;jbsr %1\", operands);
+ else
+ {
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, size/4);
+ output_asm_insn (\"mov%.l sp,a0\;pea %a2\", xoperands);
+ output_asm_insn (\"jbsr %1\", operands);
+ size = size + 4;
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, size);
+ if (size <= 8)
+ output_asm_insn (\"addq%.l %2,sp\", xoperands);
+ else if (size < 0x8000)
+ output_asm_insn (\"add%.w %2,sp\", xoperands);
+ else
+ output_asm_insn (\"add%.l %2,sp\", xoperands);
+ }
+ return \"mov%.l a6@(-4),a0\";
+}")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;; This should not be used unless the add/sub insns can't be.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "lea %a1,%0")
+
+;; This is the first machine-dependent peephole optimization.
+;; It is useful when a floating value is returned from a function call
+;; and then is moved into an FP register.
+;; But it is mainly intended to test the support for these optimizations.
+
+;Not applicable to Alliant -- floating results are returned in fp0
+;(define_peephole
+; [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
+; (set (match_operand:DF 0 "register_operand" "f")
+; (match_operand:DF 1 "register_operand" "ad"))]
+; "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
+; "*
+;{
+; rtx xoperands[2];
+; xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+; output_asm_insn (\"mov%.l %1,%@\", xoperands);
+; output_asm_insn (\"mov%.l %1,%-\", operands);
+; return \"fmove%.d %+,%0\";
+;}
+;")
+
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- comment-start-skip: ";+- *"
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
+
diff --git a/gcc-1.40/config/convex.md b/gcc-1.40/config/convex.md
new file mode 100644
index 0000000..97d874d
--- /dev/null
+++ b/gcc-1.40/config/convex.md
@@ -0,0 +1,1266 @@
+;;- Machine description for GNU compiler
+;;- Convex Version
+;; Copyright (C) 1989 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- Instruction patterns. When multiple patterns apply,
+;;- the first one in the file is chosen.
+;;-
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+;;-
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "* return set_cmp (operands[0], const0_rtx, 'w');")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "register_operand" "r"))]
+ ""
+ "* return set_cmp (operands[0], const0_rtx, 'h');")
+
+(define_expand "tstqi"
+ [(set (match_dup 1)
+ (sign_extend:SI (match_operand:QI 0 "register_operand" "r")))
+ (set (cc0)
+ (match_dup 1))]
+ ""
+ "operands[1] = gen_reg_rtx (SImode);")
+
+(define_insn "tstdi"
+ [(set (cc0)
+ (match_operand:DI 0 "register_operand" "d"))
+ (clobber (reg:DI 1))]
+ ""
+ "*
+{
+ output_asm_insn (\"ld.l #0,s1\");
+ return set_cmp (operands[0], gen_rtx (REG, DImode, 1), 'l');
+}")
+
+(define_expand "tstdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "d")
+ (match_dup 1)))]
+ ""
+ "operands[1] = force_reg (DFmode, dconst0_rtx);")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "d"))]
+ ""
+ "* return set_cmp (operands[0], fconst0_rtx, 's');")
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonmemory_operand" "d,a,i,r")
+ (match_operand:SI 1 "nonmemory_operand" "d,a,r,i")))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 'w');")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "nonmemory_operand" "d,a,r,i")
+ (match_operand:HI 1 "nonmemory_operand" "d,a,i,r")))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 'h');")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (sign_extend:SI (match_operand:QI 0 "register_operand" "d"))
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "d"))))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 'b');")
+
+(define_insn "cmpdi"
+ [(set (cc0)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 'l');")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "d")
+ (match_operand:DF 1 "register_operand" "d")))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 'd');")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "nonmemory_operand" "dF,d")
+ (match_operand:SF 1 "nonmemory_operand" "d,F")))]
+ ""
+ "* return set_cmp (operands[0], operands[1], 's');")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=g,d")
+ (match_operand:DF 1 "general_operand" "d,gG"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], DFmode))
+ return \"psh.l %1\";
+ else if (GET_CODE (operands[0]) == MEM)
+ return \"st.l %1,%0\";
+ else if (GET_CODE (operands[1]) == REG)
+ return \"mov %1,%0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ const_double_high_int (operands[1]));
+ return \"ld.d %1,%0\";
+ }
+ else
+ return \"ld.l %1,%0\";
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=g,d")
+ (match_operand:SF 1 "general_operand" "d,gF"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SFmode))
+ return \"psh.w %1\";
+ else if (GET_CODE (operands[0]) == MEM)
+ return \"st.s %1,%0\";
+ else if (GET_CODE (operands[1]) == REG)
+ return \"mov.s %1,%0\";
+ else
+ return \"ld.s %1,%0\";
+}")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=g,d")
+ (match_operand:DI 1 "general_operand" "d,gG"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], DImode))
+ return \"psh.l %1\";
+ else if (GET_CODE (operands[0]) == MEM)
+ return \"st.l %1,%0\";
+ else if (GET_CODE (operands[1]) == REG)
+ return \"mov %1,%0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ const_double_high_int (operands[1]));
+ return \"ld.d %1,%0\";
+ }
+ else
+ return \"ld.l %1,%0\";
+}")
+
+;; Special case of movsi, needed to express A-reg preference.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "push_operand" "=<")
+ (plus:SI (match_operand:SI 1 "register_operand" "a")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] != stack_pointer_rtx"
+ "pshea %a2(%1)")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g,r,<")
+ (match_operand:SI 1 "general_operand" "r,g,io"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ {
+ if (GET_CODE (operands[1]) == REG)
+ return \"psh.w %1\";
+ else
+ return \"pshea %a1\";
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st.w %1,%0\";
+ if (GET_CODE (operands[1]) != REG)
+ return \"ld.w %1,%0\";
+ if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
+ return \"mov.w %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g,r")
+ (match_operand:HI 1 "general_operand" "r,g"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], HImode))
+ abort ();
+ else if (GET_CODE (operands[0]) == MEM)
+ return \"st.h %1,%0\";
+ else if (GET_CODE (operands[1]) == REG)
+ {
+ if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
+ return \"mov.w %1,%0\";
+ else
+ return \"mov %1,%0\";
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ return \"ld.w %1,%0\";
+ else
+ return \"ld.h %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=g,r")
+ (match_operand:QI 1 "general_operand" "r,g"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], QImode))
+ abort ();
+ else if (GET_CODE (operands[0]) == MEM)
+ return \"st.b %1,%0\";
+ else if (GET_CODE (operands[1]) == REG)
+ {
+ if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
+ return \"mov.w %1,%0\";
+ else
+ return \"mov %1,%0\";
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ return \"ld.w %1,%0\";
+ else
+ return \"ld.b %1,%0\";
+}")
+
+;; Extension and truncation insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d,a")
+ (truncate:QI (match_operand:SI 1 "register_operand" "d,a")))]
+ ""
+ "cvtw.b %1,%0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (truncate:HI (match_operand:SI 1 "register_operand" "d,a")))]
+ ""
+ "cvtw.h %1,%0")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI (match_operand:HI 1 "register_operand" "0")))]
+ ""
+ "")
+
+(define_insn "truncdisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "cvtl.w %1,%0")
+
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "d")))]
+ ""
+ "cvtw.l %1,%0")
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "d,a")))]
+ ""
+ "cvth.w %1,%0")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (sign_extend:HI (match_operand:QI 1 "register_operand" "d,a")))]
+ ""
+ "cvtb.w %1,%0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "d,a")))]
+ ""
+ "cvtb.w %1,%0")
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "d")))]
+ ""
+ "cvts.d %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "d")))]
+ ""
+ "cvtd.s %1,%0")
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))]
+ ""
+ "and #0xffff,%0")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "0")))]
+ ""
+ "and #0xff,%0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
+ ""
+ "and #0xff,%0")
+
+(define_insn "zero_extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "0")))]
+ ""
+ "ld.u #0,%0")
+
+;; Fix-to-float conversion insns.
+;; Note that the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (float:SF (match_operand:SI 1 "register_operand" "d")))]
+ ""
+ "cvtw.s %1,%0")
+
+(define_insn "floatdisf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (float:SF (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "cvtl.s %1,%0")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (float:DF (match_operand:SI 1 "register_operand" "d")))]
+ "TARGET_C2"
+ "cvtw.d %1,%0")
+
+(define_insn "floatdidf2"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (float:DF (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "cvtl.d %1,%0")
+
+;; Float-to-fix conversion insns.
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
+ ""
+ "cvts.w %1,%0")
+
+(define_insn "fix_truncsfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
+ ""
+ "cvts.l %1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
+ ""
+ "*
+{
+ if (TARGET_C2)
+ return \"cvtd.w %1,%0\";
+ return \"cvtd.l %1,%0\";
+}")
+
+(define_insn "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
+ ""
+ "cvtd.l %1,%0")
+
+;;- All kinds of add instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "register_operand" "d")))]
+ ""
+ "add.d %2,%0")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "nonmemory_operand" "dF")))]
+ ""
+ "add.s %2,%0")
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (plus:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "add.l %2,%0")
+
+;; special case of addsi3, needed to specify an A reg for the destination
+;; when the source is a sum involving FP or AP.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (plus:SI (match_operand:SI 1 "register_operand" "%a")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"
+ "ldea %a2(%1),%0")
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a,a")
+ (plus:SI (match_operand:SI 1 "nonmemory_operand" "%0,0,a")
+ (match_operand:SI 2 "nonmemory_operand" "di,ri,i")))]
+ ""
+ "* switch (which_alternative)
+{
+ case 0:
+ case 1:
+ return \"add.w %2,%0\";
+ case 2:
+ if ((TARGET_C2 || A_REG_P (operands[0]))
+ && operands[1] != stack_pointer_rtx)
+ return \"ldea %a2(%1),%0\";
+ else
+ return \"mov %1,%0\;add.w %2,%0\";
+}")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "add.h %2,%0")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (plus:QI (match_operand:QI 1 "register_operand" "%0")
+ (match_operand:QI 2 "register_operand" "d")))]
+ ""
+ "add.b %2,%0")
+
+;;- All kinds of subtract instructions.
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (minus:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "d")))]
+ ""
+ "sub.d %2,%0")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (minus:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "nonmemory_operand" "dF")))]
+ ""
+ "sub.s %2,%0")
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "sub.l %2,%0")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "sub.w %2,%0")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (minus:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "sub.h %2,%0")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (minus:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "d")))]
+ ""
+ "sub.b %2,%0")
+
+;;- Multiply instructions.
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "register_operand" "d")))]
+ ""
+ "mul.d %2,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "nonmemory_operand" "dF")))]
+ ""
+ "mul.s %2,%0")
+
+(define_insn "muldi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "mul.l %2,%0")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "mul.w %2,%0")
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "mul.h %2,%0")
+
+(define_insn "mulqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (mult:QI (match_operand:QI 1 "register_operand" "%0")
+ (match_operand:QI 2 "register_operand" "d")))]
+ ""
+ "mul.b %2,%0")
+
+;;- Divide instructions.
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (div:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "d")))]
+ ""
+ "div.d %2,%0")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (div:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "nonmemory_operand" "dF")))]
+ ""
+ "div.s %2,%0")
+
+(define_insn "divdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (div:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "div.l %2,%0")
+
+(define_insn "udivdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (udiv:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "psh.l %2\;psh.l %1\;callq udiv64\;pop.l %0\;add.w #8,sp")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (div:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "div.w %2,%0")
+
+(define_insn "divhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (div:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "div.h %2,%0")
+
+(define_insn "divqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (div:QI (match_operand:QI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "d")))]
+ ""
+ "div.b %2,%0")
+
+;; - and, or, xor
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (and:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "and %2,%0")
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "and %2,%0")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "and %2,%0")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d,a")
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "and %2,%0")
+
+;;- Bit set instructions.
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ior:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "or %2,%0")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "or %2,%0")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "or %2,%0")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d,a")
+ (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "or %2,%0")
+
+;;- xor instructions.
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (xor:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "register_operand" "d")))]
+ ""
+ "xor %2,%0")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "xor %2,%0")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (xor:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "xor %2,%0")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d,a")
+ (xor:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "xor %2,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (neg:DF (match_operand:DF 1 "register_operand" "d")))]
+ ""
+ "neg.d %1,%0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (neg:SF (match_operand:SF 1 "register_operand" "d")))]
+ ""
+ "neg.s %1,%0")
+
+(define_insn "negdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "neg.l %1,%0")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (neg:SI (match_operand:SI 1 "register_operand" "d,a")))]
+ ""
+ "neg.w %1,%0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (neg:HI (match_operand:HI 1 "register_operand" "d,a")))]
+ ""
+ "neg.h %1,%0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (neg:QI (match_operand:QI 1 "register_operand" "d")))]
+ ""
+ "neg.b %1,%0")
+
+(define_insn "one_cmpldi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (not:DI (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "not %1,%0")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (not:SI (match_operand:SI 1 "register_operand" "d,a")))]
+ ""
+ "not %1,%0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,a")
+ (not:HI (match_operand:HI 1 "register_operand" "d,a")))]
+ ""
+ "not %1,%0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "register_operand" "=d,a")
+ (not:QI (match_operand:QI 1 "register_operand" "d,a")))]
+ ""
+ "not %1,%0")
+
+;;- shifts
+;;
+;; Convex shift instructions are unsigned.
+;; To make signed right shifts:
+;; for SImode, sign extend to DImode and shift, works for 0..32
+;; for DImode, shift and then extend the sign, works for 0..63
+;;
+;; It is very sad that DImode right shift 64 fails, but I don't see
+;; any reasonable way to handle it. ANSI only requires up to 63.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "INTVAL (operands[2]) >= 0"
+ "*
+{
+ if (operands[2] == const1_rtx)
+ return \"add.w %0,%0\";
+ else if (TARGET_C2 && S_REG_P (operands[0]))
+ return \"shf.w %2,%0\";
+ else
+ return \"shf %2,%0\";
+}")
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx)
+ return \"add.w %0,%0\";
+ else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0)
+ return TARGET_C2 ? \"shf.w %2,%0\" : \"shf %2,%0\";
+ else
+ return \"cvtw.l %0,%0\;shf %2,%0\";
+}")
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")))]
+ ""
+ "operands[2] = negate_rtx (SImode, operands[2]);")
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,a")
+ (lshift:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "di,ai")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx)
+ return \"add.w %0,%0\";
+ if (S_REG_P (operands[0]))
+ {
+ if (TARGET_C2)
+ return \"shf.w %2,%0\";
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 0)
+ return \"shf %2,%0\";
+ else
+ return \"ld.u #0,%0\;shf %2,%0\";
+ }
+ return \"shf %2,%0\";
+}")
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")))]
+ ""
+ "operands[2] = negate_rtx (SImode, operands[2]);")
+
+;; signed a >> b is
+;; ((a >> b) ^ signbit) - signbit
+;; where signbit is (1 << 63) >> b
+
+(define_expand "ashldi3"
+ [(match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")
+ (match_dup 3)]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0)
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (LSHIFT, DImode, operands[1], operands[2])));
+ else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ {
+ int rshift = - INTVAL (operands[2]);
+ operands[3] = force_reg
+ (DImode,
+ immed_double_const (1 << (63 - rshift), 1 << (31 - rshift), DImode));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (LSHIFT, DImode, operands[1], operands[2])));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (XOR, DImode, operands[0], operands[3])));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (MINUS, DImode, operands[0], operands[3])));
+ }
+ else
+ {
+ operands[3] =
+ force_reg (DImode, immed_double_const (0, 1 << 31, DImode));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (LSHIFT, DImode, operands[1], operands[2])));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[3],
+ gen_rtx (LSHIFT, DImode, operands[3], operands[2])));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (XOR, DImode, operands[0], operands[3])));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (MINUS, DImode, operands[0], operands[3])));
+ }
+ DONE;
+}")
+
+(define_expand "ashrdi3"
+ [(match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")]
+ ""
+ "
+{
+ emit_insn (gen_ashldi3 (operands[0], operands[1],
+ negate_rtx (SImode, operands[2])));
+ DONE;
+}")
+
+(define_insn "lshldi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (lshift:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")))]
+ ""
+ "shf %2,%0")
+
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (lshift:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "nonmemory_operand" "di")))]
+ ""
+ "operands[2] = negate_rtx (SImode, operands[2]);")
+
+;; __builtin instructions
+
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "register_operand" "=d")
+ (sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
+ "TARGET_C2"
+ "sqrt.d %0")
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_C2"
+ "sqrt.s %0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
+ (const_int 1)))]
+ ""
+ "tzc %1,%0\;le.w #32,%0\;jbrs.f .+6\;ld.w #-1,%0")
+
+(define_expand "ffssi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
+ (const_int 1)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ ""
+ "")
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=d")
+ (abs:SF (match_operand:SF 1 "register_operand" "0")))]
+ ""
+ "and #0x7fffffff,%0")
+
+(define_expand "absdf2"
+ [(set (subreg:DI (match_operand:DF 0 "register_operand" "=d") 0)
+ (and:DI (subreg:DI (match_operand:DF 1 "register_operand" "d") 0)
+ (match_dup 2)))]
+ ""
+ "operands[2] = force_reg (DImode,
+ immed_double_const (-1, 0x7fffffff, DImode));")
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "jbr %l0")
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"eq\", 't'); ")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"eq\", 'f'); ")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"le\", 'f'); ")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"leu\", 'f'); ")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"lt\", 't'); ")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"ltu\", 't'); ")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"lt\", 'f'); ")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"ltu\", 'f'); ")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"le\", 't'); ")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return gen_cmp (operands[0], \"leu\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"eq\", 'f'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"eq\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"le\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"leu\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"lt\", 'f'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"ltu\", 'f'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"lt\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"ltu\", 't'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"le\", 'f'); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return gen_cmp (operands[0], \"leu\", 'f'); ")
+
+;; - Calls
+;;
+;; arg count word may be omitted to save a push and let gcc try to
+;; combine the arg list pop. RETURN_POPS_ARGS from tm.h decides this.
+
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (! RETURN_POPS_ARGS (ignoreme))
+ {
+ if (operands[1] == const0_rtx)
+ return \"calls %0\";
+ if (! reg_mentioned_p (arg_pointer_rtx, operands[0]))
+ return \"mov sp,ap\;calls %0\;ld.w 12(fp),ap\";
+ operands[0] = XEXP (operands[0], 0);
+ return \"ld.w %0,a1\;mov sp,ap\;calls (a1)\;ld.w 12(fp),ap\";
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 3)/ 4);
+ if (! reg_mentioned_p (arg_pointer_rtx, operands[0]))
+ return \"mov sp,ap\;pshea %a1\;calls %0\;ld.w 12(fp),ap\;add.w #4*%a1+4,sp\";
+ operands[0] = XEXP (operands[0], 0);
+ return \"ld.w %0,a1\;mov sp,ap\;pshea %a1\;calls (a1)\;ld.w 12(fp),ap\;add.w #4*%a1+4,sp\";
+}")
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=g")
+ (call (match_operand:QI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (! RETURN_POPS_ARGS (ignoreme))
+ {
+ if (operands[2] == const0_rtx)
+ return \"calls %1\";
+ if (! reg_mentioned_p (arg_pointer_rtx, operands[1]))
+ return \"mov sp,ap\;calls %1\;ld.w 12(fp),ap\";
+ operands[1] = XEXP (operands[1], 0);
+ return \"ld.w %1,a1\;mov sp,ap\;calls (a1)\;ld.w 12(fp),ap\";
+ }
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 3) / 4);
+ if (! reg_mentioned_p (arg_pointer_rtx, operands[1]))
+ return \"mov sp,ap\;pshea %a2\;calls %1\;ld.w 12(fp),ap\;add.w #4*%a2+4,sp\";
+ operands[1] = XEXP (operands[1], 0);
+ return \"ld.w %1,a1\;mov sp,ap\;pshea %a2\;calls (a1)\;ld.w 12(fp),ap\;add.w #4*%a2+4,sp\";
+}")
+
+(define_insn "return"
+ [(return)]
+ ""
+ "rtn")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "address_operand" "p"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp %a0")
+
+;; - fix up the code generated for bit field tests
+
+;; cc0 = (x >> k1) & k2 --> cc0 = x & (k2 << k1)
+;; cc0 = (x << k1) & k2 --> cc0 = x & (k2 >> k1)
+;; provided k2 and (k2 << k1) don't include the sign bit
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (lshift:SI (match_dup 0)
+ (match_operand 1 "immediate_operand" "i")))
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand 2 "immediate_operand" "i")))
+ (set (cc0) (match_dup 0))]
+ "dead_or_set_p (insn, operands[0])
+ && GET_CODE (operands[1]) == CONST_INT
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 0
+ && (INTVAL (operands[2]) << INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) >> INTVAL (operands[1]));
+ output_asm_insn (\"and %2,%0\", operands);
+ return set_cmp (operands[0], const0_rtx, 'w');
+}")
+
+;; same as above where x is (y & 0xff...) caused by a zero extend
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (zero_extend:SI (match_operand 1 "register_operand" "0")))
+ (set (match_dup 0)
+ (lshift:SI (match_dup 0)
+ (match_operand 2 "immediate_operand" "i")))
+ (set (match_dup 0)
+ (and:SI (match_dup 0)
+ (match_operand 3 "immediate_operand" "i")))
+ (set (cc0) (match_dup 0))]
+ "dead_or_set_p (insn, operands[0])
+ && REGNO (operands[0]) == REGNO (operands[1])
+ && GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[3]) == CONST_INT
+ && (INTVAL (operands[3]) << INTVAL (operands[2])) >= 0"
+ "*
+{
+ operands[3] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[3]) >> INTVAL (operands[2])) &
+ ~((-1) << GET_MODE_BITSIZE (GET_MODE (operands[1]))));
+ output_asm_insn (\"and %3,%0\", operands);
+ return set_cmp (operands[0], const0_rtx, 'w');
+}")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
+
diff --git a/gcc-1.40/config/i386.md b/gcc-1.40/config/i386.md
new file mode 100644
index 0000000..df467e3
--- /dev/null
+++ b/gcc-1.40/config/i386.md
@@ -0,0 +1,2021 @@
+;; GCC machine description for Intel 80386.
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+;; Mostly by William Schelter.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- instruction definitions
+
+;;- @@The original PO technology requires these to be ordered by speed,
+;;- @@ so that assigner will pick the fastest.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- When naming insn's (operand 0 of define_insn) be careful about using
+;;- names from other targets machine descriptions.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+;;- 'a' for eax
+;;- 'd' for edx
+;;- 'c' for ecx
+;;- 'b' for ebx
+;;- 'f' for anything in FLOAT_REGS
+;;- 'r' any (non-floating-point) register
+;;- 'q' regs that allow byte operations (A, B, C and D)
+;;- 'A' A and D registers
+
+;; the special asm out single letter directives following a '%' are:
+;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of operands[1]
+;; 's' output a '*'
+;; 'w' If the operand is a REG, it uses the mode size to determine the
+;; printing of the reg
+
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+ operands[1] = const0_rtx;
+ if (REG_P (operands[0]))
+ return AS2 (test%L0,%0,%0);
+ return AS2 (cmp%L0,%1,%0);
+}")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+ operands[1] = const0_rtx;
+ if (REG_P (operands[0]))
+ return AS2 (test%W0,%0,%0);
+ return AS2 (cmp%W0,%1,%0);
+}")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "qm"))]
+ ""
+ "*
+{
+ operands[1] = const0_rtx;
+ if (REG_P (operands[0]))
+ return AS2 (test%B0,%0,%0);
+ return AS2 (cmp%B0,%1,%0);
+}")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "rm,f"))
+ (clobber (reg:SI 0))]
+ "TARGET_80387"
+ "*
+{
+ rtx xops[1];
+ if (!FP_REG_P (operands[0]))
+ fp_push_sf (operands[0]);
+/* fp_pop_level--; */
+ xops[0] = FP_TOP;
+ cc_status.flags |= CC_IN_80387;
+ if (FP_REG_P (operands[0]) && ! top_dead_p (insn))
+ output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops);
+ else
+ output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops);
+ RETCOM (testsf);
+}")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "rm,f"))
+ (clobber (reg:SI 0))
+ ]
+ "TARGET_80387"
+ "*
+{
+ rtx xops[1];
+ if (!FP_REG_P (operands[0]))
+ fp_push_df (operands[0]);
+/* fp_pop_level--; */
+ xops[0] = FP_TOP;
+ cc_status.flags |= CC_IN_80387;
+ if (FP_REG_P (operands[0]) && ! top_dead_p (insn))
+ output_asm_insn (\"ftst\;fnstsw %R0ax\;sahf\", xops);
+ else
+ output_asm_insn (\"ftst\;fstp %0(0)\;fnstsw %R0ax\;sahf\", xops);
+ RETCOM (testdf);
+}")
+
+;;- compare instructions
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "mr,ri")
+ (match_operand:SI 1 "general_operand" "ri,mr")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return AS2 (cmp%L0,%0,%1);
+ }
+ return AS2 (cmp%L0,%1,%0);
+}")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "mr,ri")
+ (match_operand:HI 1 "general_operand" "ri,mr")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return AS2 (cmp%W0,%0,%1);
+ }
+ return AS2 (cmp%W0,%1,%0);
+}")
+
+(define_insn "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "qn,mq")
+ (match_operand:QI 1 "general_operand" "qm,nq")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return AS2 (cmp%B0,%0,%1);
+ }
+ return AS2 (cmp%B0,%1,%0);
+}")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "m,f*r,m,f,r,!*r")
+ (match_operand:DF 1 "general_operand" "m,m,f*r,r,f,*r")))
+ (clobber (reg:SI 0))]
+ "TARGET_80387"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ rtx tem = operands[1];
+ operands[1] = operands[0];
+ operands[0] = tem;
+ cc_status.flags |= CC_REVERSED;
+ }
+ if (! FP_REG_P (operands[1]))
+ output_movdf (FP_TOP, operands[1]);
+ output_movdf (FP_TOP, operands[0]);
+/* fp_pop_level--;
+ fp_pop_level--; */
+ cc_status.flags |= CC_IN_80387;
+ return \"fcompp\;fnstsw %R0ax\;sahf\";
+}")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "m,f*r,m,f,r,!*r")
+ (match_operand:SF 1 "general_operand" "m,m,f*r,r,f,*r")))
+ (clobber (reg:SI 0))]
+ "TARGET_80387"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ rtx tem = operands[1];
+ operands[1] = operands[0];
+ operands[0] = tem;
+ cc_status.flags |= CC_REVERSED;
+ }
+ if (! FP_REG_P (operands[1]))
+ output_movsf (FP_TOP, operands[1]);
+ output_movsf (FP_TOP, operands[0]);
+/* fp_pop_level--;
+ fp_pop_level--; */
+ cc_status.flags |= CC_IN_80387;
+ return \"fcompp\;fnstsw %R0ax\;sahf\";
+}")
+
+;; logical compare
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "general_operand" "rm,ri")
+ (match_operand:SI 1 "general_operand" "ri,rm")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
+ return AS2 (test%L0,%1,%0);
+ return AS2 (test%L0,%0,%1);
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "general_operand" "rm,ri")
+ (match_operand:HI 1 "general_operand" "ri,rm")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
+ return AS2 (test%W0,%1,%0);
+ return AS2 (test%W0,%0,%1);
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "general_operand" "qm,qi")
+ (match_operand:QI 1 "general_operand" "qi,qm")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
+ return AS2 (test%B0,%1,%0);
+ return AS2 (test%B0,%0,%1);
+}")
+
+;; move instructions.
+;; There is one for each machine mode,
+;; and each is preceded by a corresponding push-insn pattern
+;; (since pushes are not general_operands on the 386).
+
+(define_insn ""
+ [(set (match_operand:SI 0 "push_operand" "=<")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ""
+ "push%L0 %1")
+
+;; General case of fullword move.
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g,r")
+ (match_operand:SI 1 "general_operand" "ri,m"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const0_rtx && REG_P (operands[0]))
+ return \"xor%L0 %0,%0\";
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ /* Make sure the insn that stored the 0 is still present. */
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ /* Make sure cross jumping didn't happen here. */
+ && no_labels_between_p (XEXP (link, 0), insn))
+ /* Fastest way to change a 0 to a 1. */
+ return \"inc%L0 %0\";
+ return \"mov%L0 %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "push_operand" "=<")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "push%W0 %1")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g,r")
+ (match_operand:HI 1 "general_operand" "ri,m"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const0_rtx && REG_P (operands[0]))
+ return \"xor%W0 %0,%0\";
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ /* Make sure the insn that stored the 0 is still present. */
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ /* Make sure cross jumping didn't happen here. */
+ && no_labels_between_p (XEXP (link, 0), insn))
+ /* Fastest way to change a 0 to a 1. */
+ return \"inc%W0 %0\";
+ return \"mov%W0 %1,%0\";
+}")
+
+;; emit_push_insn when it calls move_by_pieces
+;; requires an insn to "push a byte".
+;; But actually we use pushw, which has the effect of rounding
+;; the amount pushed up to a halfword.
+(define_insn ""
+ [(set (match_operand:QI 0 "push_operand" "=<")
+ (match_operand:QI 1 "general_operand" "q"))]
+ ""
+ "*
+{
+ operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
+ return \"push%W0 %1\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=q,*r,m")
+ (match_operand:QI 1 "general_operand" "*g,q,qi"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const0_rtx && REG_P (operands[0]))
+ return \"xor%B0 %0,%0\";
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ /* Make sure the insn that stored the 0 is still present. */
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ /* Make sure cross jumping didn't happen here. */
+ && no_labels_between_p (XEXP (link, 0), insn))
+ /* Fastest way to change a 0 to a 1. */
+ return \"inc%B0 %0\";
+ /* If mov%B0 isn't allowed for one of these regs, use mov%W0. */
+ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
+ return (AS2 (mov%W0,%w1,%w0));
+ return (AS2 (mov%B0,%1,%0));
+}")
+
+; I suspect nothing can ever match this ???
+;(define_insn ""
+; [(set (match_operand:SF 0 "general_operand" "rm")
+; (match_operand:SF 1 "general_operand" "f"))
+; (clobber (reg:SF 8))]
+; ""
+; "*
+;{
+; output_asm_insn ("???", operands);
+; fpop_sf (operands[0]);
+; RETCOM (movsf_clobber);
+;}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "push_operand" "=<,<")
+ (match_operand:SF 1 "general_operand" "gF,f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ {
+ rtx xops[3];
+ xops[0] = AT_SP (SFmode);
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
+ xops[2] = stack_pointer_rtx;
+/* fp_pop_level--; */
+ output_asm_insn (AS2 (sub%L0,%1,%2), xops);
+ if (top_dead_p (insn))
+ output_asm_insn (\"fstp%S0 %0\", xops);
+ else
+ output_asm_insn (\"fst%S0 %0\", xops);
+ RET;
+ }
+ return \"push%L0 %1\";
+}")
+
+(define_insn "movsf"
+ ;; `rf' is duplicated in the second alternative
+ ;; to make sure an optional reload is generated
+ ;; for the memref in operand 0. Otherwise
+ ;; we could use too many hard regs.
+ [(set (match_operand:SF 0 "general_operand" "=rf,mrf,!rm")
+ (match_operand:SF 1 "general_operand" "mrf,rf,F"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1])
+ && !FP_REG_P (operands[0])
+ && !top_dead_p (insn))
+ fp_store_sf (operands[0]);
+ else
+ output_movsf (operands[0], operands[1]);
+ RETCOM (movsf);
+}")
+
+;;should change to handle the memory operands[1] without doing df push..
+(define_insn ""
+ [(set (match_operand:DF 0 "push_operand" "=<,<")
+ (match_operand:DF 1 "general_operand" "gF,f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ {
+ rtx xops[3];
+ xops[0] = AT_SP (DFmode);
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 8);
+ xops[2] = stack_pointer_rtx;
+/* fp_pop_level--; */
+ output_asm_insn (AS2 (sub%L0,%1,%2), xops);
+ if (top_dead_p(insn))
+ output_asm_insn (\"fstp%Q0 %0\", xops);
+ else
+ output_asm_insn (\"fst%Q0 %0\", xops);
+ RETCOM (pushdf);
+ }
+ else
+ return output_move_double (operands);
+}")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=rmf,&fr,!rm")
+ ;; `rf' is duplicated in the second alternative
+ ;; to make sure that optional reloads are generated
+ ;; for the memory reference in operand 1.
+ (match_operand:DF 1 "general_operand" "fr,mrf,F"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1])
+ && ! FP_REG_P (operands[0])
+ && ! top_dead_p (insn))
+ fp_store_df (operands[0]);
+ else
+ output_movdf (operands[0], operands[1]);
+ RETCOM (movdf);
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "push_operand" "=<")
+ (match_operand:DI 1 "general_operand" "roiF"))]
+ ""
+ "*
+{
+ return output_move_double (operands);
+}")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=&r,rm")
+ (match_operand:DI 1 "general_operand" "m,riF"))]
+ ""
+ "*
+{
+ return output_move_double (operands);
+}")
+
+;; These go after the move instructions
+;; because the move instructions are better (require no spilling)
+;; when they can apply. But these go before the add and subtract insns
+;; because it is often shorter to use these when both apply.
+
+;Lennart Augustsson <augustss@cs.chalmers.se>
+;says this pattern just makes slower code:
+; pushl %ebp
+; addl $-80,(%esp)
+;instead of
+; leal -80(%ebp),%eax
+; pushl %eax
+;
+;(define_insn ""
+; [(set (match_operand:SI 0 "push_operand" "=<")
+; (plus:SI (match_operand:SI 1 "general_operand" "%r")
+; (match_operand:SI 2 "general_operand" "ri")))]
+; ""
+; "*
+;{
+; rtx xops[4];
+; xops[0] = operands[0];
+; xops[1] = operands[1];
+; xops[2] = operands[2];
+; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
+; output_asm_insn (\"push%z1 %1\", xops);
+; output_asm_insn (AS2 (add%z3,%2,%3), xops);
+; RET;
+;}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (plus:SI (match_operand:SI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "inc%L0 %0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (plus:SI (match_operand:SI 1 "general_operand" "0")
+ (const_int -1)))]
+ ""
+ "dec%L0 %0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "dec%L0 %0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ /* Adding a constant to a register is faster with an add. */
+ if (GET_CODE (operands[1]) == PLUS
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
+ && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
+ {
+ operands[1] = XEXP (operands[1], 1);
+ return AS2 (add%L0,%1,%0);
+ }
+ return \"lea%L0 %a1,%0\";
+}")
+
+;;- conversion instructions
+;;- NONE
+
+;;- truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=q,m")
+ (truncate:QI
+ (match_operand:SI 1 "general_operand" "qim,qn")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
+ return \"mov%L0 %1,%k0\";
+ return \"mov%B0 %b1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=q,m")
+ (truncate:QI
+ (match_operand:HI 1 "general_operand" "qim,qn")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
+ return \"mov%W0 %1,%w0\";
+ return \"mov%B0 %b1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=r,m")
+ (truncate:HI
+ (match_operand:SI 1 "general_operand" "rim,rn")))]
+ ""
+ "*
+{
+ if (CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != CONST_INT)
+ return \"mov%L0 %1,%k0\";
+ return \"mov%W0 %w1,%0\";
+}")
+
+;;- zero extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "rm")))]
+ ""
+ "movz%W0%L0 %1,%0")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=r")
+ (zero_extend:HI
+ (match_operand:QI 1 "general_operand" "qm")))]
+ ""
+ "movz%B0%W0 %1,%0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "qm")))]
+ ""
+ "movz%B0%L0 %1,%0")
+
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+/*
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "general_operand" "=a")
+ (sign_extend:DI
+ (match_operand:SI 1 "general_operand" "a")))]
+ ""
+ "clq")
+*/
+
+;; Note that the i386 programmers' manual says that the opcodes
+;; are named movsx..., but the assembler on Unix does not accept that.
+;; We use what the Unix assembler expects.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "rm")))]
+ ""
+ "movs%W0%L0 %1,%0")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "qm")))]
+ ""
+ "movs%B0%W0 %1,%0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "qm")))]
+ ""
+ "movs%B0%L0 %1,%0"
+ )
+
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm,f,fm,fm")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "m,0,f,!*r")))]
+ "TARGET_80387"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ output_movsf (operands[0], operands[1]);
+ RET;
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (top_dead_p (insn))
+ fp_pop_df (operands[0]);
+ else
+ fp_store_df (operands[0]);
+ RET;
+ }
+ output_movsf (FP_TOP, operands[1]);
+ fp_pop_df (operands[0]);
+ RETCOM (extendsfdf2);
+}")
+
+;; This cannot output into an f-reg because there is no way to be
+;; sure of truncating in that case.
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=m,!*r")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "f,f")))]
+ "TARGET_80387"
+ "*
+{
+ if (top_dead_p (insn))
+ fp_pop_sf (operands[0]);
+ else
+ fp_store_sf (operands[0]);
+ RETCOM (truncdfsf2);
+}")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode. The 80387 would not know
+;; what to do with the smaller sizes anyway. (I think).
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm,fm")
+ (float:SF (match_operand:SI 1 "general_operand" "m,!*r")))]
+ "TARGET_80387"
+ "*
+{
+/* fp_pop_level++; */
+
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ rtx xops[2];
+ output_asm_insn (\"push%L0 %1\", operands);
+ operands[1] = AT_SP (SImode);
+ output_asm_insn (\"fild%L0 %1\", operands);
+ xops[0] = stack_pointer_rtx;
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
+ output_asm_insn (AS2 (add%L0,%1,%0), xops);
+ }
+ else
+ output_asm_insn (\"fild%L0 %1\", operands);
+
+ if (! FP_REG_P (operands[0]))
+ {
+/* fp_pop_level--; */
+ return \"fstp%S0 %0\";
+ }
+ RET;
+}")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm,fm")
+ (float:DF (match_operand:SI 1 "general_operand" "m,!*r")))]
+ "TARGET_80387"
+ "*
+{
+/* fp_pop_level++; */
+ if (GET_CODE (operands[1]) != MEM)
+ {
+ rtx xops[2];
+ output_asm_insn (\"push%L0 %1\", operands);
+ operands[1] = AT_SP (SImode);
+ output_asm_insn (\"fild%L0 %1\", operands);
+ xops[0] = stack_pointer_rtx;
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
+ output_asm_insn (AS2 (add%L0,%1,%0), xops);
+ }
+ else
+ output_asm_insn (\"fild%L0 %1\", operands);
+ if (! FP_REG_P (operands[0]))
+ {
+/* fp_pop_level--; */
+ return \"fstp%Q0 %0\";
+ }
+ RET;
+}")
+
+;; Convert a float to a float whose value is an integer.
+;; This is the first stage of converting it to an integer type.
+
+;; On the 387 truncating doub to an short integer shor can be performed:
+
+; fstcw -4(%esp) ;save cw
+; movw -4(%esp),%ax
+; orw $0x0c00,%ax ;set rounding to chop towards zero
+; movw %ax,-2(%esp) ;
+; fldcw -2(%esp) ;
+; fldl doubl
+; fistpl -12(%esp) ;store the round value
+; fldcw -4(%esp) ;restore cw
+; movl -12(%esp),%eax
+; movw %ax,shor ; move the result into shor.
+
+;; but it is probably better to have a call, rather than waste this
+;; space. The last instruction would have been a movl if were
+;; going to an int instead of a short.
+;; For the moment we will go with the soft float for these.
+
+/* These are incorrect since they don't set the rounding bits of CW flag.
+ The proper way to do that is to make the function prologue save the CW
+ and also construct the alternate CW value needed for these insns.
+ Then these insns can output two fldcw's, referring to fixed places in
+ the stack frame.
+
+;; Convert a float whose value is an integer
+;; to an actual integer. Second stage of converting float to integer type.
+
+(define_insn "fix_truncsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=m,?*q")
+ (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+
+(define_insn "fix_truncsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=m,?*r")
+ (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=m,?*r")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+
+(define_insn "fix_truncdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=m,?*q")
+ (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
+
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+
+
+(define_insn "fix_truncdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=m,?*r")
+ (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=m,?*r")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
+ "TARGET_80387"
+ "*
+{
+ fp_pop_int (operands[0]);
+ RET;
+}")
+*/
+
+
+;;- add instructions
+;;moved incl to above leal
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm,r")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")))]
+ ""
+ "add%L0 %2,%0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (plus:HI (match_operand:HI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "inc%W0 %0")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm,r")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ ""
+ "add%W0 %2,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (plus:QI (match_operand:QI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "inc%B0 %0")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,q")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ ""
+ "add%B0 %2,%0")
+
+;;had "fmF,m"
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "general_operand" "=f,m,f")
+ (plus:DF (match_operand:DF 1 "general_operand" "%0,0,0")
+ (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "general_operand" "=f,m,f")
+ (plus:SF (match_operand:SF 1 "general_operand" "%0,0,0")
+ (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")
+
+;;- subtract instructions
+
+;;moved decl above leal
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm,r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")))]
+ ""
+ "sub%L0 %2,%0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (minus:HI (match_operand:HI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "dec%W0 %0")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm,r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ ""
+ "sub%W0 %2,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (minus:QI (match_operand:QI 1 "general_operand" "0")
+ (const_int 1)))]
+ ""
+ "dec%B0 %0")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,q")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ ""
+ "sub%B0 %2,%0")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
+ (match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")
+
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
+ (match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")
+
+;;- multiply instructions
+
+;(define_insn "mulqi3"
+; [(set (match_operand:QI 0 "general_operand" "=a")
+; (mult:QI (match_operand:QI 1 "general_operand" "%0")
+; (match_operand:QI 2 "general_operand" "qm")))]
+; ""
+; "mul%B0 %2,%0")
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=r,r")
+ (mult:SI (match_operand:HI 1 "general_operand" "%0,rm")
+ (match_operand:HI 2 "general_operand" "g,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) == REGNO (operands[0])
+ && (GET_CODE (operands[2]) == MEM
+ || GET_CODE (operands[2]) == REG))
+ /* Assembler has weird restrictions. */
+ return AS2 (imul%W0,%2,%0);
+ return AS3 (imul%W0,%2,%1,%0);
+}")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=r,r")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
+ (match_operand:SI 2 "general_operand" "g,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) == REGNO (operands[0])
+ && (GET_CODE (operands[2]) == MEM
+ || GET_CODE (operands[2]) == REG))
+ /* Assembler has weird restrictions. */
+ return AS2 (imul%L0,%2,%0);
+ return AS3 (imul%L0,%2,%1,%0);
+}")
+
+;; Turned off due to possible assembler bug.
+;(define_insn "umulqi3"
+; [(set (match_operand:QI 0 "general_operand" "=a")
+; (umult:QI (match_operand:QI 1 "general_operand" "%0")
+; (match_operand:QI 2 "general_operand" "qm")))]
+; ""
+; "mul%B0 %2,%0")
+
+;(define_insn "umulqihi3"
+; [(set (match_operand:HI 0 "general_operand" "=a")
+; (umult:HI (match_operand:QI 1 "general_operand" "%0")
+; (match_operand:QI 2 "general_operand" "qm")))]
+; ""
+; "mul%B0 %2,%0")
+
+(define_insn "umulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=a")
+ (umult:SI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "rm")))
+ (clobber (reg:HI 1))]
+ ""
+ "mul%W0 %2,%0")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (umult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (clobber (reg:SI 1))]
+ ""
+ "mul%L0 %2,%0")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "general_operand" "=f,m,f")
+ (mult:DF (match_operand:DF 1 "general_operand" "%0,0,0")
+ (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
+")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "general_operand" "=f,m,f")
+ (mult:SF (match_operand:SF 1 "general_operand" "%0,0,0")
+ (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
+")
+
+;;- divide instructions
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
+ (div:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
+ (match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
+")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
+ (div:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
+ (match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
+ "TARGET_80387"
+ "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
+")
+
+;; Divide and Remainder instructions.
+
+;; Copy operands 1 and 2 to new registers, so that there's no
+;; danger that put_var_into_stack will mess up the sharing match_dup needs.
+;; CSE will get rid of the extra pseudo regs.
+;; No problem if not optimizing, since then only `register' vars
+;; will get pseudo regs, and they aren't allowed to have address taken.
+
+(define_expand "divmodsi4"
+ [(parallel [(set (match_operand:SI 0 "general_operand" "=a")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (set (match_operand:SI 3 "general_operand" "=&d")
+ (mod:SI (match_dup 1) (match_dup 2)))])]
+ ""
+ "
+{
+ extern int optimize;
+ if (optimize)
+ {
+ if (GET_CODE (operands[1]) == REG && REG_USERVAR_P (operands[1]))
+ operands[1] = copy_to_mode_reg (SImode, operands[1]);
+ if (GET_CODE (operands[2]) == REG && REG_USERVAR_P (operands[2]))
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ }
+}")
+
+(define_expand "udivmodsi4"
+ [(parallel [(set (match_operand:SI 0 "general_operand" "=a")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (set (match_operand:SI 3 "general_operand" "=&d")
+ (umod:SI (match_dup 1) (match_dup 2)))])]
+ ""
+ "
+{
+ extern int optimize;
+ if (optimize)
+ {
+ if (GET_CODE (operands[1]) == REG && REG_USERVAR_P (operands[1]))
+ operands[1] = copy_to_mode_reg (SImode, operands[1]);
+ if (GET_CODE (operands[2]) == REG && REG_USERVAR_P (operands[2]))
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (set (match_operand:SI 3 "general_operand" "=&d")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "cltd\;idiv%L0 %2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (set (match_operand:SI 3 "general_operand" "=&d")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "xor%L0 %3,%3\;div%L0 %2")
+
+/*
+;;this should be a valid double division which we may want to add
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (udiv:DI (match_operand:DI 1 "general_operand" "a")
+ (match_operand:SI 2 "general_operand" "rm")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "div%L0 %2,%0")
+*/
+
+;;- and instructions
+
+;; The `r' in `rm' for operand 3 looks redundant, but it causes
+;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm,r")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")))]
+ ""
+ "and%L0 %2,%0")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm,r")
+ (and:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ ""
+ "and%W0 %2,%0")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,q")
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ ""
+ "and%B0 %2,%0")
+
+/* I am nervous about these two.. add them later..
+;I presume this means that we have something in say op0= eax which is small
+;and we want to and it with memory so we can do this by just an
+;andb m,%al and have success.
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
+ "and%W0 %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=q")
+ (and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "qm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
+ "and%L0 %1,%0")
+
+*/
+
+
+
+;;- Bit set (inclusive or) instructions
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm,r")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")))]
+ ""
+ "or%L0 %2,%0")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm,r")
+ (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ ""
+ "or%W0 %2,%0")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,q")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ ""
+ "or%B0 %2,%0")
+
+;;- xor instructions
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm,r")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")))]
+ ""
+ "xor%L0 %2,%0")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm,r")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ ""
+ "xor%W0 %2,%0")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (xor:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "qn")))]
+ ""
+ "xor%B0 %2,%0")
+
+;;- negation instructions
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "neg%L0 %0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "neg%W0 %0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "neg%B0 %0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f,!m")
+ (neg:SF (match_operand:SF 1 "general_operand" "0,0")))]
+ "TARGET_80387"
+ "*FP_CALL1 (\"fchs\")")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f,!m")
+ (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
+ "TARGET_80387"
+ "*FP_CALL1 (\"fchs\")")
+
+;; Absolute value instructions
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "general_operand" "=f,!m")
+ (abs:SF (match_operand:SF 1 "general_operand" "0,0")))]
+ "TARGET_80387"
+ "*FP_CALL1 (\"fabs\")")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f,!m")
+ (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
+ "TARGET_80387"
+ "*FP_CALL1 (\"fabs\")")
+
+;;- one complement instructions
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "not%L0 %0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (not:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "not%W0 %0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (not:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "not%B0 %0")
+
+;;- arithmetic shift instructions
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (ashift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sal%L0,%R0cl,%0);
+ else if (REG_P (operands[1]) && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 1)
+ return AS2 (add%L0,%1,%1);
+ return AS2 (sal%L0,%2,%1);
+}")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (ashift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sal%W0,%R0cl,%0);
+ else
+ return AS2 (sal%W0,%2,%1);
+}")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (ashift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sal%B0,%R0cl,%0);
+ else
+ return AS2 (sal%B0,%2,%1);
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sar%L0,%R0cl,%0);
+ else
+ return AS2 (sar%L0,%2,%0);
+}")
+
+(define_insn "ashrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sar%W0,%R0cl,%0);
+ else
+ return AS2 (sar%W0,%2,%0);
+}")
+
+(define_insn "ashrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (sar%B0,%R0cl,%0);
+ return
+ AS2 (sar%B0,%2,%1);
+}")
+
+;;- logical shift instructions
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (lshift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shl%L0,%R0cl,%0);
+ else
+ return AS2 (shl%L0,%2,%1);
+}")
+
+(define_insn "lshlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (lshift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shl%W0,%R0cl,%0);
+ else
+ return AS2 (shl%W0,%2,%1);
+}")
+
+(define_insn "lshlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (lshift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shl%B0,%R0cl,%0);
+ else
+ return AS2 (shl%B0,%2,%1);
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shr%L0,%R0cl,%0);
+ else
+ return AS2 (shr%L0,%2,%1);
+}")
+
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shr%W0,%%cl,%0);
+ else
+ return AS2 (shr%W0,%2,%1);
+}")
+
+(define_insn "lshrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (shr%B0,%%cl,%0);
+ else
+ return AS2 (shr%B0,%2,%1);
+}")
+
+;;- rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (rotate:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (rol%L0,%%cl,%0);
+ else
+ return AS2 (rol%L0,%2,%1);
+}")
+
+(define_insn "rotlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (rotate:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (rol%W0,%%cl,%0);
+ else
+ return AS2 (rol%W0,%2,%1);
+}")
+
+(define_insn "rotlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (rotate:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (rol%B0,%%cl,%0);
+ else
+ return AS2 (rol%B0,%2,%1);
+}")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (rotatert:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (ror%L0,%%cl,%0);
+ else
+ return AS2 (ror%L0,%2,%1);
+}")
+
+(define_insn "rotrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=rm")
+ (rotatert:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (ror%W0,%%cl,%0);
+ else
+ return AS2 (ror%W0,%2,%1);
+}")
+
+(define_insn "rotrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=qm")
+ (rotatert:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "cI")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return AS2 (ror%B0,%%cl,%0);
+ else
+ return AS2 (ror%B0,%2,%1);
+}")
+
+;; Store-flag instructions.
+
+(define_insn "seq"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ return \"sete %0\";
+")
+
+(define_insn "sne"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ return \"setne %0\";
+")
+
+(define_insn "sgt"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"setg %0\", \"seta %0\", 0);
+")
+
+(define_insn "sgtu"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"seta %0\"; ")
+
+(define_insn "slt"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); ")
+
+(define_insn "sltu"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"setb %0\"; ")
+
+(define_insn "sge"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); ")
+
+(define_insn "sgeu"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"setae %0\"; ")
+
+(define_insn "sle"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"setle %0\", \"setbe %0\", 0);
+")
+
+(define_insn "sleu"
+ [(set (match_operand:QI 0 "general_operand" "=q")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"setbe %0\"; ")
+
+;; Basic conditional jump instructions.
+;; We ignore the overflow flag for signed branch instructions.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "je %l0")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jne %l0")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "ja %l0")
+
+;; There is no jump insn to check for `<' on IEEE floats.
+;; Page 17-80 in the 80387 manual says jb, but that's wrong;
+;; jb checks for `not >='. So swap the operands and do `>'.
+(define_expand "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ extern rtx sequence_stack;
+ rtx prev = XEXP (XEXP (sequence_stack, 1), 0);
+ rtx body = PATTERN (prev);
+ rtx comp;
+ if (GET_CODE (body) == SET)
+ comp = SET_SRC (body);
+ else
+ comp = SET_SRC (XVECEXP (body, 0, 0));
+
+ if (GET_CODE (comp) == COMPARE
+ ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
+ : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
+ {
+ if (GET_CODE (comp) == COMPARE)
+ {
+ rtx op0 = XEXP (comp, 0);
+ rtx op1 = XEXP (comp, 1);
+ XEXP (comp, 0) = op1;
+ XEXP (comp, 1) = op0;
+ }
+ else
+ {
+ rtx new = gen_rtx (COMPARE, VOIDmode,
+ CONST0_RTX (GET_MODE (comp)), comp);
+ if (GET_CODE (body) == SET)
+ SET_SRC (body) = new;
+ else
+ SET_SRC (XVECEXP (body, 0, 0)) = new;
+ }
+ emit_insn (gen_bgt (operands[0]));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jb %l0")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jae %l0")
+
+;; See comment on `blt', above.
+(define_expand "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ extern rtx sequence_stack;
+ rtx prev = XEXP (XEXP (sequence_stack, 1), 0);
+ rtx body = PATTERN (prev);
+ rtx comp;
+ if (GET_CODE (body) == SET)
+ comp = SET_SRC (body);
+ else
+ comp = SET_SRC (XVECEXP (body, 0, 0));
+
+ if (GET_CODE (comp) == COMPARE
+ ? GET_MODE_CLASS (GET_MODE (XEXP (comp, 0))) == MODE_FLOAT
+ : GET_MODE_CLASS (GET_MODE (comp)) == MODE_FLOAT)
+ {
+ if (GET_CODE (comp) == COMPARE)
+ {
+ rtx op0 = XEXP (comp, 0);
+ rtx op1 = XEXP (comp, 1);
+ XEXP (comp, 0) = op1;
+ XEXP (comp, 1) = op0;
+ }
+ else
+ {
+ rtx new = gen_rtx (COMPARE, VOIDmode,
+ CONST0_RTX (GET_MODE (comp)), comp);
+ if (GET_CODE (body) == SET)
+ SET_SRC (body) = new;
+ else
+ SET_SRC (XVECEXP (body, 0, 0)) = new;
+ }
+ emit_insn (gen_bge (operands[0]));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jbe %l0")
+
+;; Negated conditional jump instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jne %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "je %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", 0) ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jbe %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\")
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jae %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\")")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jb %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", 0)")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "ja %l0")
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "jmp %l0")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+
+ return \"jmp %*%0\";
+}")
+
+/*
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (minus:HI (match_operand:HI 0 "general_operand" "c")
+ (const_int 1))
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" "g"))
+ (pc)))
+ (set (match_dup 0)
+ (minus:HI (match_dup 0)
+ (const_int 1)))]
+ ""
+ "loop %l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (const_int -1)
+ (minus:SI (match_operand:SI 0 "general_operand" "c")
+ (const_int 1)))
+ (const_int 0))
+ (label_ref (match_operand 1 "" "g"))
+ (pc)))
+ (set (match_dup 0)
+ (minus:SI (match_dup 0)
+ (const_int 1)))]
+ ""
+ "loop %l1")
+*/
+
+;; Call subroutine returning no value.
+(define_insn "call"
+ [(call (match_operand:QI 0 "indirect_operand" "m")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;; Operand 1 not really used on the m68000.
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ operands[0] = XEXP (operands[0], 0);
+ return \"call %*%0\";
+ }
+ else
+ return \"call %0\";
+}")
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:QI 1 "indirect_operand" "m")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;; Operand 2 not really used on the m68000.
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == MEM
+ && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ operands[1] = XEXP (operands[1], 0);
+ output_asm_insn (\"call %*%1\", operands);
+ }
+ else
+ output_asm_insn (\"call %1\", operands);
+
+ if (GET_MODE (operands[0]) == DFmode
+ || GET_MODE (operands[0]) == SFmode)
+ {
+/* fp_pop_level++; */
+ /* pop if reg dead */
+ if (!FP_REG_P (operands[0]))
+ abort ();
+ if (top_dead_p (insn))
+ {
+ POP_ONE_FP;
+ }
+ }
+ RET;
+}")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/i860.md b/gcc-1.40/config/i860.md
new file mode 100644
index 0000000..5752a58
--- /dev/null
+++ b/gcc-1.40/config/i860.md
@@ -0,0 +1,2046 @@
+;;- Machine description for Intel 860 chip for GNU C compiler
+;; Copyright (C) 1989 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+
+/* Bit-test instructions. */
+
+(define_insn ""
+ [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "logic_operand" "rL"))
+ (const_int 0)))]
+ ""
+ "*
+{
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"and %1,%0,r0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "logic_operand" "rL"))
+ (const_int 0)))]
+ ""
+ "*
+{
+ cc_status.flags |= CC_NEGATED;
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"and %1,%0,r0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "immediate_operand" "i"))
+ (const_int 0)))]
+ "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
+ "*
+{
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"andh h%%%1,%0,r0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "immediate_operand" "i"))
+ (const_int 0)))]
+ "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
+ "*
+{
+ cc_status.flags |= CC_NEGATED;
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"andh h%%%1,%0,r0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (eq (ashiftrt:SI
+ (sign_extend:SI
+ (ashift:QI (match_operand:QI 0 "register_operand" "r")
+ (match_operand:QI 1 "logic_int" "n")))
+ (match_operand:SI 2 "logic_int" "n"))
+ (const_int 0)))]
+ ""
+ "*
+{
+ int width = 8 - INTVAL (operands[2]);
+ int pos = 8 - width - INTVAL (operands[1]);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ ~((-1) << width) << pos);
+ return \"and %2,%0,r0\";
+}")
+
+;; Compare instructions.
+;; This controls RTL generation and register allocation.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpeqsi"
+ [(set (cc0) (eq (match_operand:SI 0 "logic_operand" "r,rL")
+ (match_operand:SI 1 "logic_operand" "L,r")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_EQ;
+ if (REG_P (operands[0]))
+ return \"xor %1,%0,r0\";
+ return \"xor %0,%1,r0\";
+}")
+
+(define_insn "cmpltsi"
+ [(set (cc0) (lt (match_operand:SI 0 "arith_operand" "r,rI")
+ (match_operand:SI 1 "arith_operand" "I,r")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ if (REG_P (operands[1]))
+ return \"subs %0,%1,r0\";
+ cc_status.flags |= CC_REVERSED;
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
+ return \"adds %1,%0,r0\";
+}")
+
+(define_insn "cmpgtsi"
+ [(set (cc0) (gt (match_operand:SI 0 "arith_operand" "r,rI")
+ (match_operand:SI 1 "arith_operand" "I,r")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ if (REG_P (operands[0]))
+ return \"subs %1,%0,r0\";
+ cc_status.flags |= CC_REVERSED;
+ operands[0] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[0]));
+ return \"adds %0,%1,r0\";
+}")
+
+(define_insn "cmpgeusi"
+ [(set (cc0) (geu (match_operand:SI 0 "arith_operand" "r,rI")
+ (match_operand:SI 1 "arith_operand" "I,r")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LEU;
+ if (REG_P (operands[1]))
+ return \"subu %0,%1,r0\";
+ cc_status.flags |= CC_REVERSED;
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
+ return \"addu %1,%0,r0\";
+}")
+
+(define_insn "cmpleusi"
+ [(set (cc0) (leu (match_operand:SI 0 "arith_operand" "r,rI")
+ (match_operand:SI 1 "arith_operand" "I,r")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LEU;
+ if (REG_P (operands[0]))
+ return \"subu %1,%0,r0\";
+ cc_status.flags |= CC_REVERSED;
+ operands[0] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[0]));
+ return \"addu %0,%1,r0\";
+}")
+
+(define_insn "cmpeqsf"
+ [(set (cc0) (eq (match_operand:SF 0 "reg_or_0_operand" "fG")
+ (match_operand:SF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"pfeq.ss %r1,%r0,f0\";
+}")
+
+(define_insn "cmpltsf"
+ [(set (cc0) (lt (match_operand:SF 0 "reg_or_0_operand" "fG")
+ (match_operand:SF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ return \"pfgt.ss %r1,%r0,f0\";
+}")
+
+(define_insn "cmpgtsf"
+ [(set (cc0) (gt (match_operand:SF 0 "reg_or_0_operand" "fG")
+ (match_operand:SF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ return \"pfgt.ss %r0,%r1,f0\";
+}")
+
+(define_insn "cmplesf"
+ [(set (cc0) (le (match_operand:SF 0 "reg_or_0_operand" "fG")
+ (match_operand:SF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LE;
+ return \"pfle.ss %r1,%r0,f0\";
+}")
+
+(define_insn "cmpgesf"
+ [(set (cc0) (ge (match_operand:SF 0 "reg_or_0_operand" "fG")
+ (match_operand:SF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LE;
+ return \"pfle.ss %r0,%r1,f0\";
+}")
+
+(define_insn "cmpeqdf"
+ [(set (cc0) (eq (match_operand:DF 0 "reg_or_0_operand" "fG")
+ (match_operand:DF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_EQ;
+ return \"pfeq.dd %r1,%r0,f0\";
+}")
+
+(define_insn "cmpltdf"
+ [(set (cc0) (lt (match_operand:DF 0 "reg_or_0_operand" "fG")
+ (match_operand:DF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ return \"pfgt.dd %r1,%r0,f0\";
+}")
+
+(define_insn "cmpgtdf"
+ [(set (cc0) (gt (match_operand:DF 0 "reg_or_0_operand" "fG")
+ (match_operand:DF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LT;
+ return \"pfgt.dd %r0,%r1,f0\";
+}")
+
+(define_insn "cmpledf"
+ [(set (cc0) (le (match_operand:DF 0 "reg_or_0_operand" "fG")
+ (match_operand:DF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LE;
+ return \"pfle.dd %r1,%r0,f0\";
+}")
+
+(define_insn "cmpgedf"
+ [(set (cc0) (ge (match_operand:DF 0 "reg_or_0_operand" "fG")
+ (match_operand:DF 1 "reg_or_0_operand" "fG")))]
+ ""
+ "*
+{
+ cc_status.flags &= ~ CC_CONDITION_MASK;
+ cc_status.flags |= CC_ONLY_LE;
+ return \"pfle.dd %r0,%r1,f0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m"))
+ (match_operand:SI 1 "small_int" "I")))]
+ "INTVAL (operands[1]) >= 0"
+ "ld.s %0,r31\;xor %1,r31,r0")
+
+(define_insn ""
+ [(set (cc0) (eq (match_operand:SI 0 "small_int" "I")
+ (zero_extend:SI (match_operand:HI 1 "load_operand" "m"))))]
+ "INTVAL (operands[0]) >= 0"
+ "ld.s %1,r31\;xor %0,r31,r0")
+
+;; Define the real conditional branch instructions.
+
+(define_insn "cbranch"
+ [(set (pc) (if_then_else (cc0) (label_ref (match_operand 0 "" "")) (pc)))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_NEGATED)
+ return \"bnc %l0\";
+ else
+ return \"bc %l0\";
+}")
+
+(define_insn "inverse_cbranch"
+ [(set (pc) (if_then_else (cc0) (pc) (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_NEGATED)
+ return \"bc %l0\";
+ else
+ return \"bnc %l0\";
+}")
+
+;; Other conditional branches, made by combining.
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "bte_operand" "%rK")
+ (match_operand:SI 1 "bte_operand" "rJ"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG"
+ "bte %0,%r1,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "bte_operand" "%rK")
+ (match_operand:SI 1 "bte_operand" "rJ"))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG"
+ "btne %0,%r1,%2")
+
+;; Optimize fetching an unsigned half word and comparing against constant.
+;; No need to zero-extend.
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m"))
+ (match_operand:SI 1 "immediate_operand" "K"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0x10 && INTVAL (operands[1]) >= 0"
+ "ld.s %0,r31\;bte %1,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "immediate_operand" "K")
+ (zero_extend:SI (match_operand:HI 1 "load_operand" "m")))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) == CONST_INT
+ && INTVAL (operands[0]) < 0x10 && INTVAL (operands[0]) >= 0"
+ "ld.s %1,r31\;bte %0,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m"))
+ (match_operand:SI 1 "immediate_operand" "K"))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0x10 && INTVAL (operands[1]) >= 0"
+ "ld.s %0,r31\;btne %1,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "immediate_operand" "K")
+ (zero_extend:SI (match_operand:HI 1 "load_operand" "m")))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[0]) == CONST_INT
+ && INTVAL (operands[0]) < 0x10 && INTVAL (operands[0]) >= 0"
+ "ld.s %1,r31\;btne %0,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "load_operand" "m"))
+ (match_operand:SI 1 "immediate_operand" "K"))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0x10 && INTVAL (operands[1]) >= 0"
+ "ld.b %0,r31\;bte %1,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "immediate_operand" "K")
+ (zero_extend:SI (match_operand:QI 1 "load_operand" "m")))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) == CONST_INT
+ && INTVAL (operands[0]) < 0x10 && INTVAL (operands[0]) >= 0"
+ "ld.b %1,r31\;bte %0,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (zero_extend:SI (match_operand:QI 0 "load_operand" "m"))
+ (match_operand:SI 1 "immediate_operand" "K"))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0x10 && INTVAL (operands[1]) >= 0"
+ "ld.b %0,r31\;btne %1,r31,%2")
+
+(define_insn ""
+ [(set (pc) (if_then_else (eq (match_operand:SI 0 "immediate_operand" "K")
+ (zero_extend:SI (match_operand:QI 1 "load_operand" "m")))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[0]) == CONST_INT
+ && INTVAL (operands[0]) < 0x10 && INTVAL (operands[0]) >= 0"
+ "ld.b %1,r31\;btne %0,r31,%2")
+
+;; Generation of conditionals.
+
+;; The first step is the emission of a standard-looking compare insn.
+;; Then a standard-named conditional branch pattern is run.
+;; That branch pattern looks back at the compare insn and deletes it.
+;; It then emits a machine-specific compare insn and a branch-if-true
+;; or a branch-if-false.
+
+;; These patterns have `abort' because they are supposed to be deleted
+;; in that fashion.
+
+(define_insn "cmpsi"
+ [(set (cc0) (compare (match_operand:SI 0 "compare_operand" "")
+ (match_operand:SI 1 "compare_operand" "")))]
+ ""
+ "* abort ();")
+
+(define_insn "cmpsf"
+ [(set (cc0) (compare (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")))]
+ ""
+ "* abort ();")
+
+(define_insn "cmpdf"
+ [(set (cc0) (compare (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" "")))]
+ ""
+ "* abort ();")
+
+;; These are the standard-named conditional branch patterns.
+;; Detailed comments are found in the first one only.
+
+(define_expand "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ /* Get out of the sequence just started for us. */
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ /* Examine the preceding compare insn, and get rid of it. */
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+
+ /* Now once again start a sequence for our new instructions. */
+
+ start_sequence ();
+
+ /* Emit a single-condition compare insn according to
+ the type of operands and the condition to be tested. */
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpeqsi (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmpeqsf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpeqdf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+
+ /* Emit branch-if-true. */
+
+ emit_jump_insn (gen_cbranch (label));
+
+ DONE;
+}")
+
+(define_expand "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpeqsi (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmpeqsf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpeqdf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_inverse_cbranch (label));
+
+ DONE;
+}")
+
+(define_expand "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpgtsi (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmpgtsf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpgtdf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ DONE;
+}")
+
+(define_expand "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpltsi (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmpltsf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpltdf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ DONE;
+}")
+
+(define_expand "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ {
+ emit_insn (gen_cmpgtsi (recog_operand[0], recog_operand[1]));
+ emit_jump_insn (gen_inverse_cbranch (label));
+ }
+ else
+ {
+ if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmplesf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpledf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ }
+ DONE;
+}")
+
+(define_expand "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ {
+ emit_insn (gen_cmpltsi (recog_operand[0], recog_operand[1]));
+ emit_jump_insn (gen_inverse_cbranch (label));
+ }
+ else
+ {
+ if (code == CODE_FOR_cmpsf)
+ emit_insn (gen_cmpgesf (recog_operand[0], recog_operand[1]));
+ else if (code == CODE_FOR_cmpdf)
+ emit_insn (gen_cmpgedf (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ }
+ DONE;
+}")
+
+(define_expand "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpleusi (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_inverse_cbranch (label));
+ DONE;
+}")
+
+(define_expand "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpgeusi (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_inverse_cbranch (label));
+ DONE;
+}")
+
+(define_expand "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpgeusi (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ DONE;
+}")
+
+(define_expand "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "
+{
+ rtx label = operands[0];
+ enum insn_code code;
+ rtx prev;
+
+ end_sequence ();
+ prev = get_last_insn ();
+
+ code = recog_memoized (prev);
+ insn_extract (prev);
+ NEXT_INSN (PREV_INSN (prev)) = 0;
+ set_last_insn (PREV_INSN (prev));
+ start_sequence ();
+
+ if (code == CODE_FOR_cmpsi)
+ emit_insn (gen_cmpleusi (recog_operand[0], recog_operand[1]));
+ else
+ abort ();
+ emit_jump_insn (gen_cbranch (label));
+ DONE;
+}")
+
+;; Move instructions
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r,m,f")
+ (match_operand:SI 1 "general_operand" "rmif,rfJ,rmfJ"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (FP_REG_P (operands[1]))
+ return \"fst.l %1,%0\";
+ return \"st.l %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+ if (FP_REG_P (operands[0]))
+ return \"fld.l %1,%0\";
+ return \"ld.l %1,%0\";
+ }
+ if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
+ return \"fmov.ss %1,%0\";
+ if (FP_REG_P (operands[1]))
+ return \"fxfr %1,%0\";
+ if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
+ return \"fmov.ss f0,%0\";
+ if (FP_REG_P (operands[0]))
+ return \"ixfr %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=r,m,!*f,!r")
+ (match_operand:HI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ return \"st.s %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+ return \"ld.s %1,%0\";
+ }
+ if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
+ return \"fmov.ss %1,%0\";
+ if (FP_REG_P (operands[1]))
+ return \"fxfr %1,%0\";
+ if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
+ return \"fmov.ss f0,%0\";
+ if (FP_REG_P (operands[0]))
+ return \"ixfr %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=r,m,!*f,!r")
+ (match_operand:QI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ return \"st.b %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+ return \"ld.b %1,%0\";
+ }
+ if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
+ return \"fmov.ss %1,%0\";
+ if (FP_REG_P (operands[1]))
+ return \"fxfr %1,%0\";
+ if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
+ return \"fmov.ss f0,%0\";
+ if (FP_REG_P (operands[0]))
+ return \"ixfr %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+(define_expand "movstrsi"
+ [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
+ (mem:BLK (match_operand:BLK 1 "general_operand" "")))
+ (use (match_operand:SI 2 "nonmemory_operand" ""))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))
+ (clobber (match_dup 6))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))])]
+ ""
+ "
+{
+ operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
+ operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
+ operands[4] = gen_reg_rtx (SImode);
+ operands[5] = gen_reg_rtx (SImode);
+ operands[6] = gen_reg_rtx (SImode);
+}")
+
+(define_insn ""
+ [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
+ (mem:BLK (match_operand:SI 1 "register_operand" "r")))
+ (use (match_operand:SI 2 "nonmemory_operand" "rn"))
+ (use (match_operand:SI 3 "immediate_operand" "i"))
+ (clobber (match_operand:SI 4 "register_operand" "=r"))
+ (clobber (match_operand:SI 5 "register_operand" "=r"))
+ (clobber (match_operand:SI 6 "register_operand" "=r"))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))]
+ ""
+ "* return output_block_move (operands);")
+
+;; Floating point move insns
+
+;; This pattern forces (set (reg:DF ...) (const_double ...))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general movdf pattern.
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=r,f,o")
+ (match_operand:DF 1 "" "mG,m,G"))]
+ "GET_CODE (operands[1]) == CONST_DOUBLE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return output_fp_move_double (operands);
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
+ {
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"mov r0,%0\;mov r0,%1\";
+ }
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"orh ha%%%m0,r0,r31\", operands);
+ }
+ return \"st.l r0,l%%%m0(r31)\;st.l r0,l%%%m0+4(r31)\";
+ }
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"st.l r0,%0\;st.l r0,%1\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=*rm,&*r,?f,?*rm")
+ (match_operand:DF 1 "general_operand" "*r,m,*rfmG,f"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+
+ /* Note that the only CONST_DOUBLE that should be possible is 0. */
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=rm,&r,?f,?rm")
+ (match_operand:DI 1 "general_operand" "r,miF,rfmG,fG"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+
+ if (FP_REG_P (operands[0]) && operands[1] == dconst0_rtx)
+ return \"fmov.dd f0,%0\";
+
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}")
+
+;; The alternative m/r is separate from m/f
+;; so that an f-reg won't be used as a reload reg between m and F.
+;; The first alternative is separate from the second for the same reason.
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=*rf,*rf,*r,m,m")
+ (match_operand:SF 1 "general_operand" "*r,fmG,F,*r,fG"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load (operands);
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmov.ss %1,%0\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"ixfr %1,%0\";
+ if (operands[1] == fconst0_rtx)
+ return \"fmov.ss f0,%0\";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"orh ha%%%m1,r0,r31\;fld.l l%%%m1(r31),%0\";
+ }
+ return \"fld.l %1,%0\";
+ }
+ if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ if (GET_CODE (operands[0]) == REG && FP_REG_P (operands[1]))
+ return \"fxfr %1,%0\";
+ if (GET_CODE (operands[0]) == REG)
+ return \"mov %1,%0\";
+ /* Now operand 0 must be memory.
+ If operand 1 is CONST_DOUBLE, its value must be 0. */
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"orh ha%%%m0,r0,r31\", operands);
+ }
+ return \"fst.l %r1,l%%%m0(r31)\";
+ }
+ return \"fst.l %r1,%0\";
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st.l %r1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld.l %1,%0\";
+ if (operands[1] == fconst0_rtx)
+ return \"mov r0,%0\";
+ return \"mov %1,%0\";
+}")
+
+;; Special load insns for REG+REG addresses.
+;; Such addresses are not "legitimate" because st rejects them.
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=rf")
+ (match_operand:DF 1 "indexed_operand" "m"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=rf")
+ (match_operand:SF 1 "indexed_operand" "m"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return \"fld.l %1,%0\";
+ return \"ld.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=rf")
+ (match_operand:SI 1 "indexed_operand" "m"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return \"fld.l %1,%0\";
+ return \"ld.l %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (match_operand:HI 1 "indexed_operand" "m"))]
+ ""
+ "ld.s %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (match_operand:QI 1 "indexed_operand" "m"))]
+ ""
+ "ld.b %1,%0")
+
+;; Likewise for floating-point store insns.
+
+(define_insn ""
+ [(set (match_operand:DF 0 "indexed_operand" "=m")
+ (match_operand:DF 1 "register_operand" "f"))]
+ ""
+ "fst.d %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "indexed_operand" "=m")
+ (match_operand:SF 1 "register_operand" "f"))]
+ ""
+ "fst.l %1,%0")
+
+;;- truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"orh ha%%%m0,r0,r31\", operands);
+ }
+ return \"st.b %1,l%%%m0(r31)\";
+ }
+ else
+ return \"st.b %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"orh ha%%%m0,r0,r31\", operands);
+ }
+ return \"st.b %1,l%%%m0(r31)\";
+ }
+ else
+ return \"st.b %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (truncate:HI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"orh ha%%%m0,r0,r31\", operands);
+ }
+ return \"st.s %1,l%%%m0(r31)\";
+ }
+ else
+ return \"st.s %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+;;- zero extension instructions
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "and 0xffff,%1,%0")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI
+ (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "and 0xff,%1,%0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "and 0xff,%1,%0")
+
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "mr")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"shl 16,%1,%0\;shra 16,%0,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ abort ();
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"orh ha%%%m1,r0,r31\;ld.s l%%%m1(r31),%0\";
+ }
+ else
+ return \"ld.s %1,%0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "mr")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"shl 24,%1,%0\;shra 24,%0,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ abort ();
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"orh ha%%%m1,r0,r31\;ld.b l%%%m1(r31),%0\";
+ }
+ else
+ return \"ld.b %1,%0\";
+}")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "mr")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"shl 24,%1,%0\;shra 24,%0,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ abort ();
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"orh ha%%%m1,r0,r31\;ld.b l%%%m1(r31),%0\";
+ }
+ else
+ return \"ld.b %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:HI 1 "indexed_operand" "m")))]
+ ""
+ "ld.s %1,%0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "indexed_operand" "m")))]
+ ""
+ "ld.b %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:QI 1 "indexed_operand" "m")))]
+ ""
+ "ld.b %1,%0")
+
+;; Signed bitfield extractions come out looking like
+;; (shiftrt (sign_extend (shift <Y> <C1>)) <C2>)
+;; which we expand poorly as four shift insns.
+;; These patters yeild two shifts:
+;; (shiftrt (shift <Y> <C3>) <C4>)
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI
+ (sign_extend:SI
+ (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:SI 2 "logic_int" "n")))]
+ "INTVAL (operands[2]) < 8"
+ "*
+{
+ return \"shl 24,%1,%0\;shra 24+%2,%0,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI
+ (sign_extend:SI
+ (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "logic_int" "n")) 0))
+ (match_operand:SI 3 "logic_int" "n")))]
+ "INTVAL (operands[3]) < 8"
+ "*
+{
+ return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI
+ (sign_extend:SI
+ (ashift:QI (match_operand:QI 1 "register_operand" "r")
+ (match_operand:QI 2 "logic_int" "n")))
+ (match_operand:SI 3 "logic_int" "n")))]
+ "INTVAL (operands[3]) < 8"
+ "*
+{
+ return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
+}")
+
+;; Special patterns for optimizing bit-field instructions.
+
+;; First two patterns are for bitfields that came from memory
+;; testing only the high bit. They work with old combiner.
+
+(define_insn ""
+ [(set (cc0)
+ (eq (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 7)) 0))
+ (const_int 0)))]
+ ""
+ "and 128,%0,r0")
+
+(define_insn ""
+ [(set (cc0)
+ (eq (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 7)) 0))
+ (const_int 0)))]
+ ""
+ "and 128,%0,r0")
+
+;; next two patterns are good for bitfields coming from memory
+;; (via pseudo-register) or from a register, though this optimization
+;; is only good for values contained wholly within the bottom 13 bits
+(define_insn ""
+ [(set (cc0)
+ (eq
+ (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "logic_int" "n"))
+ (match_operand:SI 2 "logic_int" "n"))
+ (const_int 0)))]
+ "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) << INTVAL (operands[1])));
+ return \"and %2,%0,r0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (eq
+ (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "logic_int" "n"))
+ (match_operand:SI 2 "logic_int" "n"))
+ (const_int 0)))]
+ "LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) << INTVAL (operands[1])));
+ return \"and %2,%0,r0\";
+}")
+
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "fmov.sd %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "fmov.ds %1,%0")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_expand "floatsidf2"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (xor:SI (match_operand:SI 1 "register_operand" "")
+ (const_int -2147483648)))
+ (set (subreg:SI (match_dup 5) 0) (match_dup 4))
+ (set (subreg:SI (match_dup 5) 1) (subreg:SI (match_dup 2) 1))
+ (set (match_operand:DF 0 "register_operand" "")
+ (minus:DF (match_dup 5) (match_dup 2)))]
+ ""
+ "
+{
+ /* Generate desired value, in float format of host machine. */
+ double d = (double) (1 << 30) * ((double) (1 << 22) + (double) (1 << 1));
+ operands[2] = gen_reg_rtx (DFmode);
+ operands[3] = immed_double_const (d, DFmode);
+ operands[4] = gen_reg_rtx (SImode);
+ operands[5] = gen_reg_rtx (DFmode);
+}")
+
+;; Floating to fixed conversion.
+
+(define_expand "fix_truncdfsi2"
+ ;; This first insn produces a double-word value
+ ;; in which only the low word is valid.
+ [(set (match_dup 2)
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+ (set (match_operand:SI 0 "register_operand" "=f")
+ (subreg:SI (match_dup 2) 0))]
+ ""
+ "
+{
+ operands[2] = gen_reg_rtx (DImode);
+}")
+
+;; Recognize the first insn generated above.
+;; This RTL looks like a fix_truncdfdi2 insn,
+;; but we dont call it that, because only 32 bits
+;; of the result are valid.
+;; This pattern will work for the intended purposes
+;; as long as we do not have any fixdfdi2 or fix_truncdfdi2.
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ ""
+ "ftrunc.dd %1,%0")
+
+(define_expand "fix_truncsfsi2"
+ ;; This first insn produces a double-word value
+ ;; in which only the low word is valid.
+ [(set (match_dup 2)
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
+ (set (match_operand:SI 0 "register_operand" "=f")
+ (subreg:SI (match_dup 2) 0))]
+ ""
+ "
+{
+ operands[2] = gen_reg_rtx (DImode);
+}")
+
+;; Recognize the first insn generated above.
+;; This RTL looks like a fix_truncsfdi2 insn,
+;; but we dont call it that, because only 32 bits
+;; of the result are valid.
+;; This pattern will work for the intended purposes
+;; as long as we do not have any fixsfdi2 or fix_truncsfdi2.
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ ""
+ "ftrunc.sd %1,%0")
+
+;;- arithmetic instructions
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,*f")
+ (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r,*f")
+ (match_operand:SI 2 "nonmemory_operand" "rn,*f")))]
+ ""
+ "*
+{
+ if (which_alternative == 1)
+ return \"fiadd.ss %2,%1,%0\";
+ if (REG_P (operands[2]))
+ return \"addu %2,%1,%0\";
+ if (SMALL_INT (operands[2]))
+ return \"addu %2,%1,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_R31;
+ return \"orh h%%%2,r0,r31\;or l%%%2,r31,r31\;addu %1,r31,%0\";
+}")
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (plus:DI (match_operand:DI 1 "register_operand" "%f")
+ (match_operand:DI 2 "register_operand" "f")))]
+ ""
+ "fiadd.dd %1,%2,%0")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,*f")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,I,*f")
+ (match_operand:SI 2 "nonmemory_operand" "rn,r,*f")))]
+ ""
+ "*
+{
+ if (which_alternative == 2)
+ return \"fisub.ss %1,%2,%0\";
+ if (REG_P (operands[2]))
+ return \"subu %1,%2,%0\";
+ if (SMALL_INT (operands[2]) && INTVAL (operands[2]) != -0x10000)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
+ return \"addu %2,%1,%0\";
+ }
+ cc_status.flags &= ~CC_KNOW_HI_R31;
+ return \"orh h%%%2,r0,r31\;or l%%%2,r31,r31\;sub %1,r31,%0\";
+}")
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (minus:DI (match_operand:DI 1 "register_operand" "%f")
+ (match_operand:DI 2 "register_operand" "f")))]
+ ""
+ "fisub.dd %1,%2,%0")
+
+(define_expand "mulsi3"
+ [(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" ""))
+ (set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" ""))
+ (clobber (match_dup 3))
+ (set (subreg:SI (match_dup 3) 0)
+ (mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0)))
+ (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))]
+ ""
+ "
+{
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_reg_rtx (DImode);
+}")
+
+(define_insn ""
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 0)
+ (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0)
+ (subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))]
+ ""
+ "fmlow.dd %2,%1,%0")
+
+;;- and instructions (with compliment also)
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ rtx xop[3];
+
+ if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
+ return \"and %2,%1,%0\";
+ if ((INTVAL (operands[2]) & 0xffff) == 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"andh %2,%1,%0\";
+ }
+ xop[0] = operands[0];
+ xop[1] = operands[1];
+ xop[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]) & 0xffff);
+ output_asm_insn (\"andnot %2,%1,%0\", xop);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ ~(unsigned) INTVAL (operands[2]) >> 16);
+ return \"andnoth %2,%0,%0\";
+}")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "r")
+ (not:SI (match_operand:SI 2 "register_operand" "rn"))))]
+ ""
+ "*
+{
+ rtx xop[3];
+
+ if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
+ return \"andnot %2,%1,%0\";
+ if ((INTVAL (operands[2]) & 0xffff) == 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"andnoth %2,%1,%0\";
+ }
+ xop[0] = operands[0];
+ xop[1] = operands[1];
+ xop[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) & 0xffff));
+ output_asm_insn (\"andnot %2,%1,%0\", xop);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"andnoth %2,%0,%0\";
+}")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ rtx xop[3];
+
+ if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
+ return \"or %2,%1,%0\";
+ if ((INTVAL (operands[2]) & 0xffff) == 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"orh %2,%1,%0\";
+ }
+ xop[0] = operands[0];
+ xop[1] = operands[1];
+ xop[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) & 0xffff));
+ output_asm_insn (\"or %2,%1,%0\", xop);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"orh %2,%0,%0\";
+}")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ rtx xop[3];
+
+ if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
+ return \"xor %2,%1,%0\";
+ if ((INTVAL (operands[2]) & 0xffff) == 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"xorh %2,%1,%0\";
+ }
+ xop[0] = operands[0];
+ xop[1] = operands[1];
+ xop[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) & 0xffff));
+ output_asm_insn (\"xor %2,%1,%0\", xop);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (unsigned) INTVAL (operands[2]) >> 16);
+ return \"xorh %2,%0,%0\";
+}")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "subu r0,%1,%0")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (not:SI (match_operand:SI 1 "arith_operand" "r")))]
+ ""
+ "subu -1,%1,%0")
+
+;; Floating point arithmetic instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fadd.dd %1,%2,%0")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fadd.ss %1,%2,%0")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (minus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fsub.dd %1,%2,%0")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (minus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fsub.ss %1,%2,%0")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fmul.dd %1,%2,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fmul.ss %1,%2,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "fsub.dd f0,%1,%0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "fsub.ss f0,%1,%0")
+
+;; Shift instructions
+
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ ""
+ "*
+{
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"orh ha%%%m1,r0,r31\;ld.b l%%%m1(r31),%0\";
+ }
+ return \"ld.b %1,%0\";
+}")
+
+
+;;- arithmetic shift instructions
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ return \"mov r0,%0\";
+ return \"shl %2,%1,%0\";
+}")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ashift:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:HI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 16)
+ return \"mov r0,%0\";
+ return \"shl %2,%1,%0\";
+}")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (ashift:QI (match_operand:QI 1 "register_operand" "r")
+ (match_operand:QI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 8)
+ return \"mov r0,%0\";
+ return \"shl %2,%1,%0\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ return \"shra 31,%1,%0\";
+ return \"shra %2,%1,%0\";
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ return \"mov r0,%0\";
+ return \"shr %2,%1,%0\";
+}")
+
+;; Unconditional and other jump instructions
+
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ return \"br %l0\;nop\";
+}")
+
+;; Here are two simple peepholes which fill the delay slot of
+;; an unconditional branch.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=rf")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (set (pc) (label_ref (match_operand 2 "" "")))]
+ ""
+ "* return output_delayed_branch (\"br %l2\", operands, insn);")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
+ (set (pc) (label_ref (match_operand 2 "" "")))]
+ ""
+ "* return output_delayed_branch (\"br %l2\", operands, insn);")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "bri %0\;nop")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
+ (set (pc) (match_operand:SI 2 "register_operand" "r"))
+ (use (label_ref (match_operand 3 "" "")))]
+ ""
+ "* return output_delayed_branch (\"bri %2\", operands, insn);")
+
+;;- jump to subroutine
+(define_expand "call"
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))]
+ ;; operand[2] is next_arg_register
+ ""
+ "
+{
+ if (INTVAL (operands[1]) > 0)
+ {
+ emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
+ emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
+ }
+}")
+
+;;- jump to subroutine
+(define_insn ""
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))]
+ ;; operand[2] is next_arg_register
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[0] = XEXP (operands[0], 0);
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[0]) == REG)
+ return \"calli %0\;nop\";
+ return \"call %0\;nop\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=rf")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (call (match_operand:SI 2 "memory_operand" "m")
+ (match_operand 3 "" "i"))]
+ ;;- Don't use operand 1 for most machines.
+ "! reg_mentioned_p (operands[0], operands[2])"
+ "*
+{
+ /* strip the MEM. */
+ operands[2] = XEXP (operands[2], 0);
+ if (GET_CODE (operands[2]) == REG)
+ return output_delayed_branch (\"calli %2\", operands, insn);
+ return output_delayed_branch (\"call %2\", operands, insn);
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
+ (call (match_operand:SI 2 "memory_operand" "m")
+ (match_operand 3 "" "i"))]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[2] = XEXP (operands[2], 0);
+ if (GET_CODE (operands[2]) == REG)
+ return output_delayed_branch (\"calli %2\", operands, insn);
+ return output_delayed_branch (\"call %2\", operands, insn);
+}")
+
+(define_expand "call_value"
+ [(set (match_operand 0 "register_operand" "=rf")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))]
+ ;; operand 3 is next_arg_register
+ ""
+ "
+{
+ if (INTVAL (operands[2]) > 0)
+ {
+ emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
+ emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand 0 "register_operand" "=rf")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))]
+ ;; operand 3 is next_arg_register
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[1] = XEXP (operands[1], 0);
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[1]) == REG)
+ return \"calli %1\;nop\";
+ return \"call %1\;nop\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=rf")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (set (match_operand 2 "" "=rf")
+ (call (match_operand:SI 3 "memory_operand" "m")
+ (match_operand 4 "" "i")))]
+ ;;- Don't use operand 4 for most machines.
+ "! reg_mentioned_p (operands[0], operands[3])"
+ "*
+{
+ /* strip the MEM. */
+ operands[3] = XEXP (operands[3], 0);
+ if (GET_CODE (operands[3]) == REG)
+ return output_delayed_branch (\"calli %3\", operands, insn);
+ return output_delayed_branch (\"call %3\", operands, insn);
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rJf"))
+ (set (match_operand 2 "" "=rf")
+ (call (match_operand:SI 3 "memory_operand" "m")
+ (match_operand 4 "" "i")))]
+ ;;- Don't use operand 4 for most machines.
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[3] = XEXP (operands[3], 0);
+ if (GET_CODE (operands[3]) == REG)
+ return output_delayed_branch (\"calli %3\", operands, insn);
+ return output_delayed_branch (\"call %3\", operands, insn);
+}")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (label_ref (match_operand 2 "" "")))))]
+ ""
+ "*
+{
+ cc_status.flags = 0;
+ return \"mov %l2,r31\;ld.l r31(%1),%0\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=rf")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (set (pc) (match_operand:SI 2 "register_operand" "r"))
+ (use (label_ref (match_operand 3 "" "")))]
+ "REGNO (operands[0]) != REGNO (operands[2])"
+ "* return output_delayed_branch (\"bri %2\", operands, insn);")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
+
diff --git a/gcc-1.40/config/m68k.md b/gcc-1.40/config/m68k.md
new file mode 100644
index 0000000..c241ab4
--- /dev/null
+++ b/gcc-1.40/config/m68k.md
@@ -0,0 +1,4156 @@
+;;- Machine description for GNU compiler
+;;- Motorola 68000 Version
+;; Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- instruction definitions
+
+;;- @@The original PO technology requires these to be ordered by speed,
+;;- @@ so that assigner will pick the fastest.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- When naming insn's (operand 0 of define_insn) be careful about using
+;;- names from other targets machine descriptions.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+;;- 'a' one of the address registers can be used.
+;;- 'd' one of the data registers can be used.
+;;- 'f' one of the m68881 registers can be used
+;;- 'r' either a data or an address register can be used.
+;;- 'x' if one of the Sun FPA registers
+;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).
+
+;;- Immediate Floating point operator constraints
+;;- 'G' a floating point constant that is *NOT* one of the standard
+;; 68881 constant values (to force calling output_move_const_double
+;; to get it from rom if it is a 68881 constant).
+;;- 'H' one of the standard FPA constant values
+;;
+;; See the functions standard_XXX_constant_p in output-m68k.c for more
+;; info.
+
+;;- Immediate integer operand constraints:
+;;- 'I' 1 .. 8
+;;- 'J' -32768 .. 32767
+;;- 'K' -128 .. 127
+;;- 'L' -8 .. -1
+
+;;- FPA port explanation:
+
+;;- Usage of the Sun FPA and the 68881 together
+
+;;- The current port of gcc to the sun fpa disallows use of the m68881
+;;- instructions completely if code is targetted for the fpa. This is
+;;- for the following reasons:
+
+;;- 1) Expressing the preference hierarchy (ie. use the fpa if you
+;;- can, the 68881 otherwise, and data registers only if you are
+;;- forced to it) is a bitch with the current constraint scheme,
+;;- especially since it would have to work for any combination of
+;;- -mfpa, -m68881.
+
+;;- 2) There are no instructions to move between the two types of
+;;- registers; the stack must be used as an intermediary.
+
+;;- It could indeed be done; I think the best way would be to have
+;;- seperate patterns for TARGET_FPA (which implies a 68881),
+;;- TARGET_68881, and no floating point co-processor. Use
+;;- define_expands for all of the named instruction patterns, and
+;;- include code in the FPA instruction to deal with the 68881 with
+;;- preferences specifically set to favor the fpa. Some of this has
+;;- already been done:
+;;-
+;;- 1) Separation of most of the patterns out into a TARGET_FPA
+;;- case and a TARGET_68881 case (the exceptions are the patterns
+;;- which would need one define_expand and three define_insn's under
+;;- it (with alot of duplicate code between them) to replace the
+;;- current single define_insn. These are mov{[ds]f,[ds]i} and the
+;;- first two patterns in the md.
+;;-
+;;- Some would still have to be done:
+;;-
+;;- 1) Add code to the fpa patterns which correspond to 68881
+;;- patterns to deal with the 68881 case (including preferences!).
+;;- What you might actually do here is combine the fpa and 68881 code
+;;- back together into one pattern for those instructions where it's
+;;- absolutely necessary and save yourself some duplicate code. I'm
+;;- not completely sure as to whether you could get away with doing
+;;- this only for the mov* insns, or if you'd have to do it for all
+;;- named insns.
+;;- 2) Add code to the mov{[ds]f,[ds]i} instructions to handle
+;;- moving between fpa regs and 68881 regs.
+
+;;- Since the fpa is more powerful than the 68881 and also has more
+;;- registers, and since I think the reultant md would be medium ugly
+;;- (lot's of duplicate code, ugly constraint strings), I elected not
+;;- to do this change.
+
+;;- Another reason why someone *might* want to do the change is to
+;;- control which register classes are accessed in a slightly cleaner
+;;- way than I have. See the blurb on CONDITIONAL_REGISTER_USAGE in
+;;- the internals manual.
+
+;;- Yet another reason why someone might want to do this change is to
+;;- allow use of some of the 68881 insns which have no equivalent on
+;;- the fpa. The sqrt instruction comes fairly quickly to mind.
+
+;;- If this is ever done, don't forget to change tm-sun3.h so that
+;;- it *will* define __HAVE_68881__ when the FPA is in use.
+
+;;- Condition code hack
+
+;;- When a floating point compare is done in the fpa, the resulting
+;;- condition codes are left in the fpastatus register. The values in
+;;- this register must be moved into the 68000 cc register before any
+;;- jump is executed. Once this has been done, regular jump
+;;- instructions are fine (ie. floating point jumps are not necessary.
+;;- They are only done if the cc is in the 68881).
+
+;;- The instructions that move the fpastatus register to the 68000
+;;- register clobber a data register (the move cannot be done direct).
+;;- These instructions might be bundled either with the compare
+;;- instruction, or the branch instruction. If we were using both the
+;;- fpa and the 68881 together, we would wish to only mark the
+;;- register clobbered if we were doing the compare in the fpa, but I
+;;- think that that decision (whether to clobber the register or not)
+;;- must be done before register allocation (makes sense) and hence we
+;;- can't know if the floating point compare will be done in the fpa
+;;- or the fp. So whenever we are asked for code that uses the fpa,
+;;- we will mark a data register as clobbered. This is reasonable, as
+;;- almost all floating point compare operations done with fpa code
+;;- enabled will be done in the fpa. It's even more reasonable since
+;;- we decided to make the 68881 and the fpa mutually exclusive.
+
+;;- We place to code to move the fpastatus register inside of a
+;;- define_expand so that we can do it conditionally based on whether
+;;- we are tagetting an fpa or not.
+
+;;- This still leaves us with the question of where we wish to put the
+;;- code to move the fpastatus reg. If we put it in the compare
+;;- instruction, we can restrict the clobbering of the register to
+;;- floating point compares, but we can't take advantage of floating
+;;- point subtracts & etc. that alter the fpastatus register. If we
+;;- put it in the branch instruction, all branches compiled with fpa
+;;- code enabled will clobber a data register, but we will be able to
+;;- take advantage of fpa subtracts. This balance favors putting the
+;;- code in with the compare instruction.
+
+;;- Note that if some enterprising hacker should decide to switch
+;;- this, he'll need to modify the code in NOTICE_UPDATE_CC.
+
+;;- Usage of the top 16 fpa registers
+
+;;- The only locations which we may transfer fpa registers 16-31 from
+;;- or to are the fpa registers 0-15. (68000 registers and memory
+;;- locations are impossible). This causes problems in gcc, which
+;;- assumes that mov?? instructions require no additional registers
+;;- (see section 11.7) and since floating point moves *must* be
+;;- supported into general registers (see section 12.3 under
+;;- HARD_REGNO_OK_FOR_MODE_P) from anywhere.
+
+;;- My solution was to reserve fpa0 for moves into or out of these top
+;;- 16 registers and to disparage the choice to reload into or out of
+;;- these registers as much as I could. That alternative is always
+;;- last in the list, so it will not be used unless all else fails. I
+;;- will note that according to my current information, sun's compiler
+;;- doesn't use these top 16 registers at all.
+
+;;- There is another possible way to do it. I *believe* that if you
+;;- make absolutely sure that the code will not be exectued in the
+;;- reload pass, you can support the mov?? names with define_expands
+;;- which require new registers. This may be possible by the
+;;- appropriate juggling of constraints. I may come back to this later.
+
+;;- Usage of constant RAM
+
+;;- This has been handled correctly (I believe) but the way I've done
+;;- it could use a little explanation. The constant RAM can only be
+;;- accessed when the instruction is in "command register" mode.
+;;- "command register" mode means that no accessing of memory or the
+;;- 68000 registers is being done. This can be expressed easily in
+;;- constraints, so generally the mode of the instruction is
+;;- determined by a branch off of which_alternative. In outputing
+;;- instructions, a 'w' means to output an access to the constant ram
+;;- (if the arg is CONST_DOUBLE and is one of the available
+;;- constants), and 'x' means to output a register pair (if the arg is
+;;- a 68000 register) and a 'y' is the combination of the above two
+;;- processies. You use a 'y' in two operand DF instructions where you
+;;- *know* the other operand is an fpa register, you use an 'x' in DF
+;;- instructions where the arg might be a 68000 register and the
+;;- instruction is *not* in "command register" mode, and you use a 'w'
+;;- in two situations: 1) The instruction *is* in command register
+;;- mode (and hence won't be accessing 68000 registers), or 2) The
+;;- instruction is a two operand SF instruction where you know the
+;;- other operand is an fpa register.
+
+;;- Optimization issues
+
+;;- I actually think that I've included all of the fpa instructions
+;;- that should be included. Note that if someone is interested in
+;;- doing serious floating point work on the sun fpa, I would advise
+;;- the use of the "asm" instruction in gcc to allow you to use the
+;;- sin, cos, and exponential functions on the fpa board.
+
+;;- END FPA Explanation Section.
+
+
+;;- Some of these insn's are composites of several m68000 op codes.
+;;- The assembler (or final @@??) insures that the appropriate one is
+;;- selected.
+
+(define_insn ""
+ [(set (match_operand:DF 0 "push_operand" "=m")
+ (match_operand:DF 1 "general_operand" "ro<>fyF"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %f1,%0\";
+ if (FPA_REG_P (operands[1]))
+ return \"fpmove%.d %1, %x0\";
+ return output_move_double (operands);
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "push_operand" "=m")
+ (match_operand:DI 1 "general_operand" "ro<>Fy"))]
+ ""
+ "*
+{
+ return output_move_double (operands);
+}")
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+#ifdef ISI_OV
+ /* ISI's assembler fails to handle tstl a0. */
+ if (! ADDRESS_REG_P (operands[0]))
+#else
+ if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+#endif
+ return \"tst%.l %0\";
+ /* If you think that the 68020 does not support tstl a0,
+ reread page B-167 of the 68020 manual more carefully. */
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef HPUX_ASM
+ return \"cmp%.w %0,%#0\";
+#else
+ return \"cmp%.w %#0,%0\";
+#endif
+}")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "rm"))]
+ ""
+ "*
+{
+#ifdef ISI_OV
+ if (! ADDRESS_REG_P (operands[0]))
+#else
+ if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+#endif
+ return \"tst%.w %0\";
+#ifdef HPUX_ASM
+ return \"cmp%.w %0,%#0\";
+#else
+ return \"cmp%.w %#0,%0\";
+#endif
+}")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "dm"))]
+ ""
+ "tst%.b %0")
+
+(define_expand "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" ""))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2,
+ gen_rtx (SET, VOIDmode,
+ cc0_rtx, operands[0]),
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_reg_rtx (SImode)))));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "xmdF"))
+ (clobber (match_operand:SI 1 "general_operand" "d"))]
+ "TARGET_FPA"
+ "fptst%.s %x0\;fpmove fpastatus,%1\;movw %1,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "fdm"))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+ if (FP_REG_P (operands[0]))
+ return \"ftst%.x %0\";
+ return \"ftst%.s %0\";
+}")
+
+(define_expand "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" ""))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ if (TARGET_FPA)
+ {
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, gen_rtx (SET, VOIDmode,
+ cc0_rtx, operands[0]),
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_reg_rtx (SImode)))));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "xrmF"))
+ (clobber (match_operand:SI 1 "general_operand" "d"))]
+ "TARGET_FPA"
+ "fptst%.d %x0\;fpmove fpastatus,%1\;movw %1,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "fm"))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+ if (FP_REG_P (operands[0]))
+ return \"ftst%.x %0\";
+ return \"ftst%.d %0\";
+}")
+
+;; compare instructions.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+;; A composite of the cmp, cmpa, & cmpi m68000 op codes.
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "rKs,mr,>")
+ (match_operand:SI 1 "general_operand" "mr,Ksr,>")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.l %1,%0\";
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef HPUX_ASM
+ return \"cmp%.l %d1,%d0\";
+#else
+ return \"cmp%.l %d0,%d1\";
+#endif
+ }
+#ifdef HPUX_ASM
+ return \"cmp%.l %d0,%d1\";
+#else
+ return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "rnm,d,n,m")
+ (match_operand:HI 1 "general_operand" "d,rnm,m,n")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.w %1,%0\";
+ if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef HPUX_ASM
+ return \"cmp%.w %d1,%d0\";
+#else
+ return \"cmp%.w %d0,%d1\";
+#endif
+ }
+#ifdef HPUX_ASM
+ return \"cmp%.w %d0,%d1\";
+#else
+ return \"cmp%.w %d1,%d0\";
+#endif
+}")
+
+(define_insn "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "dn,md,>")
+ (match_operand:QI 1 "general_operand" "dm,nd,>")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ return \"cmpm%.b %1,%0\";
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef HPUX_ASM
+ return \"cmp%.b %d1,%d0\";
+#else
+ return \"cmp%.b %d0,%d1\";
+#endif
+ }
+#ifdef HPUX_ASM
+ return \"cmp%.b %d0,%d1\";
+#else
+ return \"cmp%.b %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ if (TARGET_FPA)
+ {
+ rtx set = gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, set,
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_reg_rtx (SImode)))));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "x,y")
+ (match_operand:DF 1 "general_operand" "xH,rmF")))
+ (clobber (match_operand:SI 2 "general_operand" "d,d"))]
+ "TARGET_FPA"
+ "fpcmp%.d %y1,%0\;fpmove fpastatus,%2\;movw %2,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "f,mG")
+ (match_operand:DF 1 "general_operand" "fmG,f")))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+#ifdef HPUX_ASM
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %0,%1\";
+ else
+ return \"fcmp%.d %0,%f1\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.d %1,%f0\";
+#else
+ if (REG_P (operands[0]))
+ {
+ if (REG_P (operands[1]))
+ return \"fcmp%.x %1,%0\";
+ else
+ return \"fcmp%.d %f1,%0\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.d %f0,%1\";
+#endif
+}")
+
+(define_expand "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "
+{
+ if (TARGET_FPA)
+ {
+ rtx set = gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, VOIDmode, operands[0], operands[1]));
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, set,
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_reg_rtx(SImode)))));
+ DONE;
+ }
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "x,y")
+ (match_operand:SF 1 "general_operand" "xH,rmF")))
+ (clobber (match_operand:SI 2 "general_operand" "d,d"))]
+ "TARGET_FPA"
+ "fpcmp%.s %w1,%x0\;fpmove fpastatus,%2\;movw %2,cc")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "f,mdG")
+ (match_operand:SF 1 "general_operand" "fmdG,f")))]
+ "TARGET_68881"
+ "*
+{
+ cc_status.flags = CC_IN_68881;
+#ifdef HPUX_ASM
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fcmp%.x %0,%1\";
+ else
+ return \"fcmp%.s %0,%f1\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.s %1,%f0\";
+#else
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fcmp%.x %1,%0\";
+ else
+ return \"fcmp%.s %f1,%0\";
+ }
+ cc_status.flags |= CC_REVERSED;
+ return \"fcmp%.s %f0,%1\";
+#endif
+}")
+
+;; Recognizers for btst instructions.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 1 "general_operand" "di"))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; The following two patterns are like the previous two
+;; except that they use the fact that bit-number operands
+;; are automatically masked to 3 or 5 bits.
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (and:SI
+ (match_operand:SI 1 "general_operand" "d")
+ (const_int 7)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (and:SI
+ (match_operand:SI 1 "general_operand" "d")
+ (const_int 31)))))]
+ ""
+ "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
+
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) < 8"
+ "*
+{
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+}")
+
+(define_insn ""
+ ;; The constraint "o,d" here means that a nonoffsettable memref
+ ;; will match the first alternative, and its address will be reloaded.
+ ;; Copying the memory contents into a reg would be incorrect if the
+ ;; bit position is over 7.
+ [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "o,d")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i,i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 15 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 15);
+}")
+
+(define_insn ""
+ [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[1]) / 8);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 7 - INTVAL (operands[1]) % 8);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ 31 - INTVAL (operands[1]));
+ return output_btst (operands, operands[1], operands[0], insn, 31);
+}")
+
+(define_insn ""
+ [(set (cc0) (subreg:SI (lshiftrt:QI (match_operand:QI 0 "nonimmediate_operand" "dm")
+ (const_int 7))
+ 0))]
+ ""
+ "*
+{
+ cc_status.flags = CC_Z_IN_NOT_N | CC_NOT_NEGATIVE;
+ return \"tst%.b %0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "dm")))
+ (match_operand:SI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) < 0x100
+ && exact_log2 (INTVAL (operands[1])) >= 0)"
+ "*
+{ register int log = exact_log2 (INTVAL (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, log);
+ return output_btst (operands, operands[1], operands[0], insn, 7);
+}")
+
+;; move instructions
+
+;; A special case in which it is not desirable
+;; to reload the constant into a data register.
+(define_insn ""
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "general_operand" "J"))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -0x8000
+ && INTVAL (operands[1]) < 0x8000"
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clr%.l %0\";
+ return \"pea %a1\";
+}")
+
+;This is never used.
+;(define_insn "swapsi"
+; [(set (match_operand:SI 0 "general_operand" "r")
+; (match_operand:SI 1 "general_operand" "r"))
+; (set (match_dup 1) (match_dup 0))]
+; ""
+; "exg %1,%0")
+
+;; Special case of fullword move when source is zero.
+;; The reason this is special is to avoid loading a zero
+;; into a data reg with moveq in order to store it elsewhere.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (const_int 0))]
+ ;; clr insns on 68000 read before writing.
+ ;; This isn't so on the 68010, but we have no alternative for it.
+ "(TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ return \"sub%.l %0,%0\";
+ /* moveq is faster on the 68000. */
+ if (DATA_REG_P (operands[0]) && !TARGET_68020)
+#ifdef MOTOROLA
+ return \"moveq%.l %#0,%0\";
+#else
+ return \"moveq %#0,%0\";
+#endif
+ return \"clr%.l %0\";
+}")
+
+;; General case of fullword move. The register constraints
+;; force integer constants in range for a moveq to be reloaded
+;; if they are headed for memory.
+(define_insn "movsi"
+ ;; Notes: make sure no alternative allows g vs g.
+ ;; We don't allow f-regs since fixed point cannot go in them.
+ ;; We do allow y and x regs since fixed point is allowed in them.
+ [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
+ (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
+ ""
+ "*
+{
+ if (which_alternative == 3)
+ return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
+ if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
+ return \"fpmove%.l %x1,%x0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no alternative for it. */
+ && (TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.l %0\";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#ifdef MOTOROLA
+ return \"moveq%.l %1,%0\";
+#else
+ return \"moveq %1,%0\";
+#endif
+ }
+ else if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"move%.w %1,%0\";
+ else if (push_operand (operands[0], SImode)
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"pea %a1\";
+ }
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && push_operand (operands[0], SImode))
+ return \"pea %a1\";
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && ADDRESS_REG_P (operands[0]))
+ return \"lea %a1,%0\";
+ return \"move%.l %1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no alternative for it. */
+ && (TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.w %0\";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#ifdef MOTOROLA
+ return \"moveq%.l %1,%0\";
+#else
+ return \"moveq %1,%0\";
+#endif
+ }
+ else if (INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return \"move%.w %1,%0\";
+ }
+ else if (CONSTANT_P (operands[1]))
+ return \"move%.l %1,%0\";
+#ifndef SONY_ASM
+ /* Recognize the insn before a tablejump, one that refers
+ to a table of offsets. Such an insn will need to refer
+ to a label on the insn. So output one. Use the label-number
+ of the table of offsets to generate this label. */
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+ || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF)
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS)
+ {
+ rtx labelref;
+ if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF)
+ labelref = XEXP (XEXP (operands[1], 0), 0);
+ else
+ labelref = XEXP (XEXP (operands[1], 0), 1);
+#if defined (MOTOROLA) && ! defined (SGS_3B1)
+#ifdef SGS
+ fprintf (asm_out_file, \"\\tset %s%d,.+2\\n\", \"LI\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#else /* not SGS */
+ fprintf (asm_out_file, \"\\t.set %s%d,.+2\\n\", \"LI\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#endif /* not SGS */
+#else /* SGS_3B1 or not MOTOROLA */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+ /* For sake of 3b1, set flag saying we need to define the symbol
+ LD%n (with value L%n-LI%n) at the end of the switch table. */
+ RTX_INTEGRATED_P (next_real_insn (XEXP (labelref, 0))) = 1;
+#endif /* SGS_3B1 or not MOTOROLA */
+ }
+#endif /* SONY_ASM */
+ return \"move%.w %1,%0\";
+}")
+
+(define_insn "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
+ (match_operand:HI 1 "general_operand" "rmn"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no alternative for it. */
+ && (TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.w %0\";
+ }
+ return \"move%.w %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a")
+ (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))]
+ ""
+ "*
+{
+ rtx xoperands[4];
+ if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
+ {
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx (MEM, QImode,
+ gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
+ xoperands[3] = stack_pointer_rtx;
+ /* Just pushing a byte puts it in the high byte of the halfword. */
+ /* We must put it in the low half, the second byte. */
+ output_asm_insn (\"subq%.w %#2,%3\;move%.b %1,%2\", xoperands);
+ return \"move%.w %+,%0\";
+ }
+ if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
+ {
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx (MEM, QImode,
+ gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
+ xoperands[3] = stack_pointer_rtx;
+ output_asm_insn (\"move%.w %1,%-\;move%.b %2,%0\;addq%.w %#2,%3\", xoperands);
+ return \"\";
+ }
+ /* clr and st insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no alternative for it. */
+ if (TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
+ {
+ if (operands[1] == const0_rtx)
+ return \"clr%.b %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ {
+ CC_STATUS_INIT;
+ return \"st %0\";
+ }
+ }
+ if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
+ return \"move%.l %1,%0\";
+ if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
+ return \"move%.w %1,%0\";
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
+ (match_operand:QI 1 "general_operand" "dmn"))]
+ ""
+ "*
+{
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no alternative for it. */
+ && (TARGET_68020
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.b %0\";
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
+ (match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
+; [(set (match_operand:SF 0 "general_operand" "=rmf")
+; (match_operand:SF 1 "general_operand" "rmfF"))]
+ ""
+ "*
+{
+ if (which_alternative >= 4)
+ return \"fpmove%.s %1,fpa0\;fpmove%.s fpa0,%0\";
+ if (FPA_REG_P (operands[0]))
+ {
+ if (FPA_REG_P (operands[1]))
+ return \"fpmove%.s %x1,%x0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_single (operands);
+ else if (FP_REG_P (operands[1]))
+ return \"fmove%.s %1,sp@-\;fpmove%.d sp@+, %0\";
+ return \"fpmove%.s %x1,%x0\";
+ }
+ if (FPA_REG_P (operands[1]))
+ {
+ if (FP_REG_P (operands[0]))
+ return \"fpmove%.s %x1,sp@-\;fmove%.s sp@+,%0\";
+ else
+ return \"fpmove%.s %x1,%x0\";
+ }
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ else if (ADDRESS_REG_P (operands[1]))
+ return \"move%.l %1,%-\;fmove%.s %+,%0\";
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_single (operands);
+ return \"fmove%.s %f1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (ADDRESS_REG_P (operands[0]))
+ return \"fmove%.s %1,%-\;move%.l %+,%0\";
+ return \"fmove%.s %f1,%0\";
+ }
+ return \"move%.l %1,%0\";
+}")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm")
+ (match_operand:DF 1 "general_operand" "rf,m,rofF<>,rmF,y,xH,rm,x"))]
+; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
+; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
+ ""
+ "*
+{
+ if (which_alternative == 6)
+ return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
+ if (FPA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.d %1,sp@-\;fpmove%.d sp@+,%x0\";
+ return \"fpmove%.d %x1,%x0\";
+ }
+ else if (FPA_REG_P (operands[1]))
+ {
+ if (FP_REG_P(operands[0]))
+ return \"fpmove%.d %x1,sp@-\;fmoved sp@+,%0\";
+ else
+ return \"fpmove%.d %x1,%x0\";
+ }
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ return \"fmove%.d %f1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ else
+ return \"fmove%.d %f1,%0\";
+ }
+ return output_move_double (operands);
+}
+")
+
+;; movdi can apply to fp regs in some cases
+(define_insn "movdi"
+ ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+ [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,y,rm,!*x,!rm")
+ (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
+; [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm")
+; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
+; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
+; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
+ ""
+ "*
+{
+ if (which_alternative == 8)
+ return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
+ if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
+ return \"fpmove%.d %x1,%x0\";
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmove%.x %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%-\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_move_const_double (operands);
+ return \"fmove%.d %f1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ else
+ return \"fmove%.d %f1,%0\";
+ }
+ return output_move_double (operands);
+}
+")
+
+;; Thus goes after the move instructions
+;; because the move instructions are better (require no spilling)
+;; when they can apply. It goes before the add/sub insns
+;; so we will prefer it to them.
+
+(define_insn "pushasi"
+ [(set (match_operand:SI 0 "push_operand" "=m")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "pea %a1")
+
+;; truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:SI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the mov.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 3);
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm,d")
+ (truncate:QI
+ (match_operand:HI 1 "general_operand" "doJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG
+ && (GET_CODE (operands[1]) == MEM
+ || GET_CODE (operands[1]) == CONST_INT))
+ {
+ /* Must clear condition codes, since the mov.w bases them on
+ the entire 16 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.w %1,%0\";
+ }
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the mov.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 1);
+ return \"move%.b %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm,d")
+ (truncate:HI
+ (match_operand:SI 1 "general_operand" "roJ,i")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ {
+ /* Must clear condition codes, since the mov.l bases them on
+ the entire 32 bits, not just the desired 8 bits. */
+ CC_STATUS_INIT;
+ return \"move%.l %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ operands[1] = adj_offsettable_operand (operands[1], 2);
+ return \"move%.w %1,%0\";
+}")
+
+;; zero extension instructions
+
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:HI (match_dup 0) 0))
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "operands[1] = make_safe_from (operands[1], operands[0]);")
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:QI (match_dup 0) 0))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "operands[1] = make_safe_from (operands[1], operands[0]);")
+
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (const_int 0))
+ (set (strict_low_part (subreg:QI (match_dup 0) 0))
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ " operands[1] = make_safe_from (operands[1], operands[0]); ")
+
+;; Patterns to recognize zero-extend insns produced by the combiner.
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFFFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.w %1,%0\;and%.l %#0xFFFF,%0\";
+ return \"clr%.l %0\;move%.w %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"move%.w %1,%0\;clr%.w %0\";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.w %0\;move%.w %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.w %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ return \"move%.w %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=do<>")
+ (zero_extend:HI
+ (match_operand:QI 1 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.w %#0xFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.b %1,%0\;and%.w %#0xFF,%0\";
+ return \"clr%.w %0\;move%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ if (REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM)
+ {
+ output_asm_insn (\"clr%.w %-\", operands);
+ operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
+ plus_constant (stack_pointer_rtx, 1));
+ return \"move%.b %1,%0\";
+ }
+ else
+ return \"move%.b %1,%0\;clr%.b %0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.b %0\;move%.b %1,%0\";
+ else
+ {
+ output_asm_insn (\"clr%.b %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 1);
+ return \"move%.b %1,%0\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=do<>")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ if (DATA_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ return \"and%.l %#0xFF,%0\";
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.b %1,%0\;and%.l %#0xFF,%0\";
+ return \"clr%.l %0\;move%.b %1,%0\";
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+#ifdef MOTOROLA
+#ifdef SGS
+ return \"clr.l -(%0)\;move%.b %1,3(%0)\";
+#else
+ return \"clr.l -(%0)\;move%.b %1,(3,%0)\";
+#endif
+#else
+ return \"clrl %0@-\;moveb %1,%0@(3)\";
+#endif
+ }
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+#ifdef MOTOROLA
+#ifdef SGS
+ return \"clr.l (%0)+\;move%.b %1,-1(%0)\";
+#else
+ return \"clr.l (%0)+\;move%.b %1,(-1,%0)\";
+#endif
+#else
+ return \"clrl %0@+\;moveb %1,%0@(-1)\";
+#endif
+ }
+ else
+ {
+ output_asm_insn (\"clr%.l %0\", operands);
+ operands[0] = adj_offsettable_operand (operands[0], 3);
+ return \"move%.b %1,%0\";
+ }
+}")
+
+;; sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=*d,a")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "0,rmn")))]
+ ""
+ "*
+{
+ if (ADDRESS_REG_P (operands[0]))
+ return \"move%.w %1,%0\";
+ return \"ext%.l %0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "ext%.w %0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "0")))]
+ "TARGET_68020"
+ "extb%.l %0")
+
+;; Conversions between float and double.
+
+(define_expand "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpstod %w1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=*fdm,f")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "f,dmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ /* Extending float to double in an fp-reg is a no-op.
+ NOTICE_UPDATE_CC has already assumed that the
+ cc will be set. So cancel what it did. */
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"fmove%.x %1,%0\";
+ }
+ if (FP_REG_P (operands[0]))
+ return \"fmove%.s %f1,%0\";
+ if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1]))
+ {
+ output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"move%.l %+,%0\";
+ }
+ return \"fmove%.d %f1,%0\";
+}")
+
+;; This cannot output into an f-reg because there is no way to be
+;; sure of truncating in that case.
+;; But on the Sun FPA, we can be sure.
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpdtos %y1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=dm")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.s %f1,%0")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (float:SF (match_operand:SI 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=y,x")
+ (float:SF (match_operand:SI 1 "general_operand" "rmi,x")))]
+ "TARGET_FPA"
+ "fpltos %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:SI 1 "general_operand" "dmi")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_expand "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (float:DF (match_operand:SI 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=y,x")
+ (float:DF (match_operand:SI 1 "general_operand" "rmi,x")))]
+ "TARGET_FPA"
+ "fpltod %1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:SI 1 "general_operand" "dmi")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_insn "floathisf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:HI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "floathidf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:HI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "floatqisf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:QI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "floatqidf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:QI 1 "general_operand" "dmn")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+;; Convert a float to a float whose value is an integer.
+;; This is the first stage of converting it to an integer type.
+
+(define_insn "ftruncdf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fintrz%.x %f1,%0\";
+ return \"fintrz%.d %f1,%0\";
+}")
+
+(define_insn "ftruncsf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
+ "TARGET_68881"
+ "*
+{
+ if (FP_REG_P (operands[1]))
+ return \"fintrz%.x %f1,%0\";
+ return \"fintrz%.s %f1,%0\";
+}")
+
+;; Convert a float whose value is an integer
+;; to an actual integer. Second stage of converting float to integer type.
+(define_insn "fixsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "fixsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "fixsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (match_operand:SF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+(define_insn "fixdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (fix:QI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.b %1,%0")
+
+(define_insn "fixdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (fix:HI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.w %1,%0")
+
+(define_insn "fixdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (fix:SI (match_operand:DF 1 "general_operand" "f")))]
+ "TARGET_68881"
+ "fmove%.l %1,%0")
+
+;; Convert a float to an integer.
+;; On the Sun FPA, this is done in one step.
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=x,y")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "xH,rmF"))))]
+ "TARGET_FPA"
+ "fpstol %w1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=x,y")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "xH,rmF"))))]
+ "TARGET_FPA"
+ "fpdtol %y1,%0")
+
+;; add instructions
+
+;; Note that the last two alternatives are near-duplicates
+;; in order to handle insns generated by reload.
+;; This is needed since they are not themselves reloaded,
+;; so commutativity won't apply to them.
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,r,!a,!a")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,0,a,rJK")
+ (match_operand:SI 2 "general_operand" "dIKLs,mrIKLs,rJK,a")))]
+ ""
+ "*
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (!ADDRESS_REG_P (operands[1]))
+ {
+ rtx tmp = operands[1];
+
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+
+ /* These insns can result from reloads to access
+ stack slots over 64k from the frame pointer. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
+ return \"move%.l %2,%0\;add%.l %1,%0\";
+#ifdef SGS
+ if (GET_CODE (operands[2]) == REG)
+ return \"lea 0(%1,%2.l),%0\";
+ else
+ return \"lea %c2(%1),%0\";
+#else /* not SGS */
+#ifdef MOTOROLA
+ if (GET_CODE (operands[2]) == REG)
+ return \"lea (%1,%2.l),%0\";
+ else
+ return \"lea (%c2,%1),%0\";
+#else /* not MOTOROLA (MIT syntax) */
+ if (GET_CODE (operands[2]) == REG)
+ return \"lea %1@(0,%2:l),%0\";
+ else
+ return \"lea %1@(%c2),%0\";
+#endif /* not MOTOROLA */
+#endif /* not SGS */
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return (ADDRESS_REG_P (operands[0])
+ ? \"addq%.w %2,%0\"
+ : \"addq%.l %2,%0\");
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]));
+ return (ADDRESS_REG_P (operands[0])
+ ? \"subq%.w %2,%0\"
+ : \"subq%.l %2,%0\");
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ return \"add%.w %2,%0\";
+ }
+ return \"add%.l %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (plus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))]
+ ""
+ "add%.w %2,%0")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ ""
+ "*
+{
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.w %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]));
+ return \"subq%.w %2,%0\";
+ }
+ }
+#endif
+ return \"add%.w %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (plus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ ""
+ "add%.w %1,%0")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "*
+{
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"addq%.b %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
+ return \"subq%.b %2,%0\";
+ }
+ }
+#endif
+ return \"add%.b %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (plus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ ""
+ "add%.b %1,%0")
+
+(define_expand "adddf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (plus:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (plus:DF (match_operand:DF 1 "general_operand" "%xH,y")
+ (match_operand:DF 2 "general_operand" "xH,dmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpadd%.d %y2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpadd%.d %y1,%0\";
+ if (which_alternative == 0)
+ return \"fpadd3%.d %w2,%w1,%0\";
+ return \"fpadd3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (plus:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fadd%.x %2,%0\";
+ return \"fadd%.d %f2,%0\";
+}")
+
+(define_expand "addsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (plus:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (plus:SF (match_operand:SF 1 "general_operand" "%xH,y")
+ (match_operand:SF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpadd%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpadd%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpadd3%.s %w2,%w1,%0\";
+ return \"fpadd3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (plus:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"fadd%.x %2,%0\";
+ return \"fadd%.s %f2,%0\";
+}")
+
+;; subtract instructions
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs")
+ (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))]
+ ""
+ "*
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ {
+#ifndef NO_ADDSUB_Q
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= 8)
+ return \"subq%.l %1,%0\;neg%.l %0\";
+ }
+#endif
+ return \"sub%.l %1,%0\;neg%.l %0\";
+ }
+ /* This case is matched by J, but negating -0x8000
+ in an lea would give an invalid displacement.
+ So do this specially. */
+ if (INTVAL (operands[2]) == -0x8000)
+ return \"move%.l %1,%0\;sub%.l %2,%0\";
+#ifdef SGS
+ return \"lea %n2(%1),%0\";
+#else
+#ifdef MOTOROLA
+ return \"lea (%n2,%1),%0\";
+#else /* not MOTOROLA (MIT syntax) */
+ return \"lea %1@(%n2),%0\";
+#endif /* not MOTOROLA */
+#endif /* not SGS */
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return \"subq%.l %2,%0\";
+#endif
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ return \"sub%.w %2,%0\";
+ }
+ return \"sub%.l %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "general_operand" "rmn"))))]
+ ""
+ "sub%.w %2,%0")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "general_operand" "dn,rmn")))]
+ ""
+ "sub%.w %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
+ (minus:HI (match_dup 0)
+ (match_operand:HI 1 "general_operand" "dn,rmn")))]
+ ""
+ "sub%.w %1,%0")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "sub%.b %2,%0")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
+ (minus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "dn,dmn")))]
+ ""
+ "sub%.b %1,%0")
+
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (minus:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ (minus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF")
+ (match_operand:DF 2 "general_operand" "xH,dmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprsub%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpsub%.d %y2,%0\";
+ if (which_alternative == 0)
+ return \"fpsub3%.d %w2,%w1,%0\";
+ return \"fpsub3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fsub%.x %2,%0\";
+ return \"fsub%.d %f2,%0\";
+}")
+
+(define_expand "subsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (minus:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ (minus:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
+ (match_operand:SF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprsub%.s %w1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpsub%.s %w2,%0\";
+ if (which_alternative == 0)
+ return \"fpsub3%.s %w2,%w1,%0\";
+ return \"fpsub3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"fsub%.x %2,%0\";
+ return \"fsub%.s %f2,%0\";
+}")
+
+;; multiply instructions
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"muls.w %2,%0\";
+#else
+ return \"muls %2,%0\";
+#endif
+}")
+
+(define_insn "mulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"muls.w %2,%0\";
+#else
+ return \"muls %2,%0\";
+#endif
+}")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "muls%.l %2,%0")
+
+(define_insn "umulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"mulu.w %2,%0\";
+#else
+ return \"mulu %2,%0\";
+#endif
+}")
+
+(define_insn "umulhisi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (umult:SI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"mulu.w %2,%0\";
+#else
+ return \"mulu %2,%0\";
+#endif
+}")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (umult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "mulu%.l %2,%0")
+
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (mult:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (mult:DF (match_operand:DF 1 "general_operand" "%xH,y")
+ (match_operand:DF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"fpsqr%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpmul%.d %y2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpmul%.d %y1,%0\";
+ if (which_alternative == 0)
+ return \"fpmul3%.d %w2,%w1,%0\";
+ return \"fpmul3%.d %x2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (mult:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fmul%.x %2,%0\";
+ return \"fmul%.d %f2,%0\";
+}")
+
+(define_expand "mulsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (mult:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (mult:SF (match_operand:SF 1 "general_operand" "%xH,y")
+ (match_operand:SF 2 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"fpsqr%.s %w1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpmul%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fpmul%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpmul3%.s %w2,%w1,%0\";
+ return \"fpmul3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (mult:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"fsglmul%.x %2,%0\";
+ return \"fsglmul%.s %f2,%0\";
+}")
+
+;; divide instructions
+
+(define_insn "divhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (div:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"ext.l %0\;divs.w %2,%0\";
+#else
+ return \"extl %0\;divs %2,%0\";
+#endif
+}")
+
+(define_insn "divhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (div:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"divs.w %2,%0\";
+#else
+ return \"divs %2,%0\";
+#endif
+}")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "divs%.l %2,%0")
+
+(define_insn "udivhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (udiv:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"and.l %#0xFFFF,%0\;divu.w %2,%0\";
+#else
+ return \"andl %#0xFFFF,%0\;divu %2,%0\";
+#endif
+}")
+
+(define_insn "udivhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (udiv:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ return \"divu.w %2,%0\";
+#else
+ return \"divu %2,%0\";
+#endif
+}")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))]
+ "TARGET_68020"
+ "divu%.l %2,%0")
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (div:DF (match_operand:DF 1 "general_operand" "")
+ (match_operand:DF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y,y")
+ (div:DF (match_operand:DF 1 "general_operand" "xH,y,rmF")
+ (match_operand:DF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprdiv%.d %y1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpdiv%.d %y2,%0\";
+ if (which_alternative == 0)
+ return \"fpdiv3%.d %w2,%w1,%0\";
+ return \"fpdiv3%.d %x2,%x1,%x0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmG")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"fdiv%.x %2,%0\";
+ return \"fdiv%.d %f2,%0\";
+}")
+
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (div:SF (match_operand:SF 1 "general_operand" "")
+ (match_operand:SF 2 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y,y")
+ (div:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
+ (match_operand:SF 2 "general_operand" "xH,rmF,0")))]
+ "TARGET_FPA"
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"fpdiv%.s %w2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"fprdiv%.s %w1,%0\";
+ if (which_alternative == 0)
+ return \"fpdiv3%.s %w2,%w1,%0\";
+ return \"fpdiv3%.s %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
+ return \"fsgldiv%.x %2,%0\";
+ return \"fsgldiv%.s %f2,%0\";
+}")
+
+;; Remainder instructions.
+
+(define_insn "modhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mod:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef SGS_3B1
+ return \"ext.l %0\;divs.w %2,%0\;swap.w %0\";
+#else
+ return \"ext.l %0\;divs.w %2,%0\;swap %0\";
+#endif
+#else
+ return \"extl %0\;divs %2,%0\;swap %0\";
+#endif
+}")
+
+(define_insn "modhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (mod:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef SGS_3B1
+ return \"divs.w %2,%0\;swap.w %0\";
+#else
+ return \"divs.w %2,%0\;swap %0\";
+#endif
+#else
+ return \"divs %2,%0\;swap %0\";
+#endif
+}")
+
+(define_insn "umodhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umod:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef SGS_3B1
+ return \"and.l %#0xFFFF,%0\;divu.w %2,%0\;swap.w %0\";
+#else
+ return \"and.l %#0xFFFF,%0\;divu.w %2,%0\;swap %0\";
+#endif
+#else
+ return \"andl %#0xFFFF,%0\;divu %2,%0\;swap %0\";
+#endif
+}")
+
+(define_insn "umodhisi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (umod:HI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dmn")))]
+ ""
+ "*
+{
+ /* The swap insn produces cc's that don't correspond to the result. */
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifdef SGS_3B1
+ return \"divu.w %2,%0\;swap.w %0\";
+#else
+ return \"divu.w %2,%0\;swap %0\";
+#endif
+#else
+ return \"divu %2,%0\;swap %0\";
+#endif
+}")
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020"
+ "divsl%.l %2,%3:%0")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (udiv:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dmsK")))
+ (set (match_operand:SI 3 "general_operand" "=d")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_68020"
+ "divul%.l %2,%3:%0")
+
+;; logical-and instructions
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (operands[2] == const0_rtx)
+ return \"clr%.w %0\";
+ return \"and%.w %2,%0\";
+ }
+ return \"and%.l %2,%0\";
+}")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (and:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ ""
+ "and%.w %2,%0")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "and%.b %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
+ "and%.w %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "dm"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
+ "and%.b %1,%0")
+
+;; inclusive-or instructions
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
+ ""
+ "*
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ return \"or%.w %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
+ }
+ return \"bset %1,%0\";
+ }
+ return \"or%.l %2,%0\";
+}")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=m,d")
+ (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "dn,dmn")))]
+ ""
+ "or%.w %2,%0")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=m,d")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "dn,dmn")))]
+ ""
+ "or%.b %2,%0")
+
+;; xor instructions
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=do,m")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "di,dKs")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
+ {
+ if (! DATA_REG_P (operands[0]))
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ return \"eor%.w %2,%0\";
+ }
+ return \"eor%.l %2,%0\";
+}")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "dn")))]
+ ""
+ "eor%.w %2,%0")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (xor:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "dn")))]
+ ""
+ "eor%.b %2,%0")
+
+;; negation instructions
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "neg%.l %0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "neg%.w %0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "neg%.b %0")
+
+(define_expand "negsf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (neg:SF (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (neg:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpneg%.s %w1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (neg:SF (match_operand:SF 1 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fneg%.x %1,%0\";
+ return \"fneg%.s %f1,%0\";
+}")
+
+(define_expand "negdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (neg:DF (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (neg:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpneg%.d %y1, %0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (neg:DF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fneg%.x %1,%0\";
+ return \"fneg%.d %f1,%0\";
+}")
+
+;; Absolute value instructions
+
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (abs:SF (match_operand:SF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=x,y")
+ (abs:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpabs%.s %y1,%0")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (abs:SF (match_operand:SF 1 "general_operand" "fdmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fabs%.x %1,%0\";
+ return \"fabs%.s %f1,%0\";
+}")
+
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (abs:DF (match_operand:DF 1 "general_operand" "")))]
+ "TARGET_68881 || TARGET_FPA"
+ "")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=x,y")
+ (abs:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
+ "TARGET_FPA"
+ "fpabs%.d %y1,%0")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_68881"
+ "*
+{
+ if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
+ return \"fabs%.x %1,%0\";
+ return \"fabs%.d %f1,%0\";
+}")
+
+;; one complement instructions
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=dm")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ ""
+ "not%.l %0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=dm")
+ (not:HI (match_operand:HI 1 "general_operand" "0")))]
+ ""
+ "not%.w %0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=dm")
+ (not:QI (match_operand:QI 1 "general_operand" "0")))]
+ ""
+ "not%.b %0")
+
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+ && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+ "*
+{
+ if (TARGET_68020)
+ return \"move%.b %1,%0\;extb%.l %0\";
+ return \"move%.b %1,%0\;ext%.w %0\;ext%.l %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+ && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+ "*
+{
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"move%.b %1,%0\;and%.l %#0xFF,%0\";
+ return \"clr%.l %0\;move%.b %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24))))]
+ "(GET_CODE (operands[0]) == CONST_INT
+ && (INTVAL (operands[0]) & ~0xff) == 0)"
+ "* cc_status.flags |= CC_REVERSED;
+#ifdef HPUX_ASM
+ return \"cmp%.b %1,%0\";
+#else
+ return \"cmp%.b %0,%1\";
+#endif
+")
+
+(define_insn ""
+ [(set (cc0) (compare (lshiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+ (const_int 24))
+ (match_operand:QI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & ~0xff) == 0)"
+ "*
+#ifdef HPUX_ASM
+ return \"cmp%.b %0,%1\";
+#else
+ return \"cmp%.b %1,%0\";
+#endif
+")
+
+(define_insn ""
+ [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24))))]
+ "(GET_CODE (operands[0]) == CONST_INT
+ && ((INTVAL (operands[0]) + 0x80) & ~0xff) == 0)"
+ "* cc_status.flags |= CC_REVERSED;
+#ifdef HPUX_ASM
+ return \"cmp%.b %1,%0\";
+#else
+ return \"cmp%.b %0,%1\";
+#endif
+")
+
+(define_insn ""
+ [(set (cc0) (compare (ashiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+ (const_int 24))
+ (match_operand:QI 1 "general_operand" "i")))]
+ "(GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) + 0x80) & ~0xff) == 0)"
+ "*
+#ifdef HPUX_ASM
+ return \"cmp%.b %0,%1\";
+#else
+ return \"cmp%.b %1,%0\";
+#endif
+")
+
+;; arithmetic shift instructions
+;; We don't need the shift memory by 1 bit instruction
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "asl%.l %2,%0")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (ashift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "asl%.w %2,%0")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ashift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "asl%.b %2,%0")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "asr%.l %2,%0")
+
+(define_insn "ashrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "asr%.w %2,%0")
+
+(define_insn "ashrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "asr%.b %2,%0")
+
+;; logical shift instructions
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.l %2,%0")
+
+(define_insn "lshlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (lshift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.w %2,%0")
+
+(define_insn "lshlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lshift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "lsl%.b %2,%0")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.l %2,%0")
+
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.w %2,%0")
+
+(define_insn "lshrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "lsr%.b %2,%0")
+
+;; rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (rotate:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "rol%.l %2,%0")
+
+(define_insn "rotlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (rotate:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "rol%.w %2,%0")
+
+(define_insn "rotlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (rotate:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "rol%.b %2,%0")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (rotatert:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "dI")))]
+ ""
+ "ror%.l %2,%0")
+
+(define_insn "rotrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=d")
+ (rotatert:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "dI")))]
+ ""
+ "ror%.w %2,%0")
+
+(define_insn "rotrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (rotatert:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "dI")))]
+ ""
+ "ror%.b %2,%0")
+
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do")
+ (match_operand:SI 1 "immediate_operand" "i")
+ (match_operand:SI 2 "immediate_operand" "i"))
+ (match_operand:SI 3 "general_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+ && (GET_CODE (operands[0]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
+ return \"bfins %3,%0{%b2:%b1}\";
+ }
+ else
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ if (GET_CODE (operands[3]) == MEM)
+ operands[3] = adj_offsettable_operand (operands[3],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[1]) == 8)
+ return \"move%.b %3,%0\";
+ return \"move%.w %3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=&d")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfextu %1{%b3:%b2},%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ output_asm_insn (\"clr%.l %0\", operands);
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[2]) == 8)
+ return \"move%.b %1,%0\";
+ return \"move%.w %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"bfexts %1{%b3:%b2},%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"move%.b %1,%0\;extb%.l %0\";
+ return \"move%.w %1,%0\;ext%.l %0\";
+}")
+
+;; Bit field instructions, general cases.
+;; "o,d" constraint causes a nonoffsettable memref to match the "o"
+;; so that its address is reloaded.
+
+(define_insn "extv"
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
+ (match_operand:SI 2 "general_operand" "di,di")
+ (match_operand:SI 3 "general_operand" "di,di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts %1{%b3:%b2},%0")
+
+(define_insn "extzv"
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
+ (match_operand:SI 2 "general_operand" "di,di")
+ (match_operand:SI 3 "general_operand" "di,di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ return \"bfextu %1{%b3:%b2},%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
+ (match_operand 3 "immediate_operand" "i,i")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[3]) == CONST_INT
+ && (INTVAL (operands[3]) == -1
+ || (GET_CODE (operands[1]) == CONST_INT
+ && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfchg %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset %0{%b2:%b1}\";
+}")
+
+(define_insn "insv"
+ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
+ (match_operand:SI 1 "general_operand" "di,di")
+ (match_operand:SI 2 "general_operand" "di,di"))
+ (match_operand:SI 3 "general_operand" "d,d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfins %3,%0{%b2:%b1}")
+
+;; Now recognize bit field insns that operate on registers
+;; (or at least were intended to do so).
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "bfexts %1{%b3:%b2},%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ cc_status.flags |= CC_NOT_NEGATIVE;
+ return \"bfextu %1{%b3:%b2},%0\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int 0))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfclr %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (const_int -1))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bfset %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (match_operand:SI 3 "general_operand" "d"))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "*
+{
+#if 0
+ /* These special cases are now recognized by a specific pattern. */
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16)
+ return \"move%.w %3,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)
+ return \"move%.b %3,%0\";
+#endif
+ return \"bfins %3,%0{%b2:%b1}\";
+}")
+
+;; Special patterns for optimizing bit-field instructions.
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:QI
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:HI
+ (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+;;; now handle the register cases
+(define_insn ""
+ [(set (cc0)
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di")))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:QI
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (subreg:HI
+ (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ 0))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (operands[1] == const1_rtx
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int width = GET_CODE (operands[0]) == REG ? 31 : 7;
+ return output_btst (operands,
+ gen_rtx (CONST_INT, VOIDmode,
+ width - INTVAL (operands[2])),
+ operands[0],
+ insn, 1000);
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ }
+ if (INTVAL (operands[1]) != 32)
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"bftst %0{%b2:%b1}\";
+}")
+
+(define_insn "seq"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
+")
+
+(define_insn "sne"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
+")
+
+(define_insn "sgt"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
+")
+
+(define_insn "sgtu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"shi %0\"; ")
+
+(define_insn "slt"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
+
+(define_insn "sltu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"scs %0\"; ")
+
+(define_insn "sge"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
+
+(define_insn "sgeu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"scc %0\"; ")
+
+(define_insn "sle"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+ cc_status = cc_prev_status;
+ OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
+")
+
+(define_insn "sleu"
+ [(set (match_operand:QI 0 "general_operand" "=d")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "* cc_status = cc_prev_status;
+ return \"sls %0\"; ")
+
+;; Basic conditional jump instructions.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
+#else
+ OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
+#endif
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
+#else
+ OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
+#endif
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", 0);
+#endif
+")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbhi %l0\";
+#else
+ return \"jhi %l0\";
+#endif
+")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jblt %l0\", \"fblt %l0\", \"jbmi %l0\");
+#else
+ OUTPUT_JUMP (\"jlt %l0\", \"fjlt %l0\", \"jmi %l0\");
+#endif
+")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcs %l0\";
+#else
+ return \"jcs %l0\";
+#endif
+")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbge %l0\", \"fbge %l0\", \"jbpl %l0\");
+#else
+ OUTPUT_JUMP (\"jge %l0\", \"fjge %l0\", \"jpl %l0\");
+#endif
+")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcc %l0\";
+#else
+ return \"jcc %l0\";
+#endif
+")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", 0);
+#endif
+")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbls %l0\";
+#else
+ return \"jls %l0\";
+#endif
+")
+
+;; Negated conditional jump instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
+#else
+ OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
+#else
+ OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", 0);
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbls %l0\";
+#else
+ return \"jls %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbge %l0\", \"fbnlt %l0\", \"jbpl %l0\");
+#else
+ OUTPUT_JUMP (\"jge %l0\", \"fjnlt %l0\", \"jpl %l0\");
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcc %l0\";
+#else
+ return \"jcc %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jblt %l0\", \"fbnge %l0\", \"jbmi %l0\");
+#else
+ OUTPUT_JUMP (\"jlt %l0\", \"fjnge %l0\", \"jmi %l0\");
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbcs %l0\";
+#else
+ return \"jcs %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", 0);
+#else
+ OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", 0);
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbhi %l0\";
+#else
+ return \"jhi %l0\";
+#endif
+")
+
+;; Subroutines of "casesi".
+
+(define_expand "casesi_1"
+ [(set (match_operand:SI 3 "general_operand" "")
+ (plus:SI (match_operand:SI 0 "general_operand" "")
+ ;; Note operand 1 has been negated!
+ (match_operand:SI 1 "immediate_operand" "")))
+ (set (cc0) (compare (match_operand:SI 2 "general_operand" "")
+ (match_dup 3)))
+ (set (pc) (if_then_else (ltu (cc0) (const_int 0))
+ (label_ref (match_operand 4 "" "")) (pc)))]
+ ""
+ "")
+
+(define_expand "casesi_2"
+ [(set (match_operand:SI 0 "" "") (mem:HI (match_operand:SI 1 "" "")))
+ ;; The USE here is so that at least one jump-insn will refer to the label,
+ ;; to keep it alive in jump_optimize.
+ (parallel [(set (pc)
+ (plus:SI (pc) (match_dup 0)))
+ (use (label_ref (match_operand 2 "" "")))])]
+ ""
+ "")
+
+;; Operand 0 is index (in bytes); operand 1 is minimum, operand 2 themaximum;
+;; operand 3 is CODE_LABEL for the table;
+;; operand 4 is the CODE_LABEL to go to if index out of range.
+(define_expand "casesi"
+ ;; We don't use these for generating the RTL, but we must describe
+ ;; the operands here.
+ [(match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "immediate_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand 3 "" "")
+ (match_operand 4 "" "")]
+ ""
+ "
+{
+ rtx table_elt_addr;
+ rtx index_diff;
+
+ operands[1] = negate_rtx (SImode, operands[1]);
+ index_diff = gen_reg_rtx (SImode);
+ /* Emit the first few insns. */
+ emit_insn (gen_casesi_1 (operands[0], operands[1], operands[2],
+ index_diff, operands[4]));
+ /* Construct a memory address. This may emit some insns. */
+ table_elt_addr
+ = memory_address_noforce
+ (HImode,
+ gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, index_diff,
+ gen_rtx (CONST_INT, VOIDmode, 2)),
+ gen_rtx (LABEL_REF, VOIDmode, operands[3])));
+ /* Emit the last few insns. */
+ emit_insn (gen_casesi_2 (gen_reg_rtx (HImode), table_elt_addr, operands[3]));
+ DONE;
+}")
+
+;; Recognize one of the insns resulting from casesi_2.
+(define_insn ""
+ [(set (pc)
+ (plus:SI (pc) (match_operand:HI 0 "general_operand" "r")))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+{
+#ifdef ASM_RETURN_CASE_JUMP
+ ASM_RETURN_CASE_JUMP;
+#else
+#ifdef SGS
+#ifdef ASM_OUTPUT_CASE_LABEL
+ return \"jmp 6(%%pc,%0.w)\";
+#else
+ return \"jmp 2(%%pc,%0.w)\";
+#endif
+#else /* not SGS */
+#ifdef MOTOROLA
+ return \"jmp (2,pc,%0.w)\";
+#else
+ return \"jmp pc@(2,%0:w)\";
+#endif
+#endif
+#endif /* no ASM_RETURN_CASE_JUMP */
+}")
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jbra %l0\";
+#else
+ return \"jra %l0\";
+#endif
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (plus:HI (match_operand:HI 0 "general_operand" "=g")
+ (const_int -1))
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ {
+#ifdef MOTOROLA
+#ifdef NO_ADDSUB_Q
+ return \"sub%.w %#1,%0\;jbcc %l1\";
+#else
+ return \"subq%.w %#1,%0\;jbcc %l1\";
+#endif
+#else /* not MOTOROLA */
+ return \"subqw %#1,%0\;jcc %l1\";
+#endif
+ }
+#ifdef MOTOROLA
+#ifdef HPUX_ASM
+#ifndef NO_ADDSUB_Q
+ return \"sub%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
+#else
+ return \"subq%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
+#endif
+#else /* not HPUX_ASM */
+ return \"subq%.w %#1,%0\;cmp%.w %#-1,%0\;jbne %l1\";
+#endif
+#else /* not MOTOROLA */
+ return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\";
+#endif
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (plus:SI (match_operand:SI 0 "general_operand" "=g")
+ (const_int -1))
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifndef NO_ADDSUB_Q
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr.w %0\;sub.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"sub.l %#1,%0\;jbcc %l1\";
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr.w %0\;subq.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq.l %#1,%0\;jbcc %l1\";
+#endif /* not NO_ADDSUB_Q */
+#ifdef HPUX_ASM
+#ifndef NO_ADDSUB_Q
+ return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#else
+ return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#endif
+#else
+ return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
+#endif
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subql %#1,%0\;jcc %l1\";
+ return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
+#endif
+}")
+
+;; dbra patterns that use REG_NOTES info generated by strength_reduce.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "general_operand" "=g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "find_reg_note (insn, REG_NONNEG, 0)"
+ "*
+{
+ CC_STATUS_INIT;
+#ifdef MOTOROLA
+#ifndef NO_ADDSUB_Q
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr.w %0\;sub.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"sub.l %#1,%0\;jbcc %l1\";
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clr.w %0\;subq.l %#1,%0\;jbcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subq.l %#1,%0\;jbcc %l1\";
+#endif
+#ifdef HPUX_ASM
+#ifndef NO_ADDSUB_Q
+ return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#else
+ return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
+#endif
+#else
+ return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
+#endif
+#else
+ if (DATA_REG_P (operands[0]))
+ return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\";
+ if (GET_CODE (operands[0]) == MEM)
+ return \"subql %#1,%0\;jcc %l1\";
+ return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
+#endif
+}")
+
+;; Call subroutine with no return value.
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "o")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;; Operand 1 not really used on the m68000.
+
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jsr %0\";
+#else
+ return \"jbsr %0\";
+#endif
+")
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:QI 1 "general_operand" "o")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;; Operand 2 not really used on the m68000.
+ ""
+ "*
+#ifdef MOTOROLA
+ return \"jsr %1\";
+#else
+ return \"jbsr %1\";
+#endif
+")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;; This should not be used unless the add/sub insns can't be.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "lea %a1,%0")
+
+;; This is the first machine-dependent peephole optimization.
+;; It is useful when a floating value is returned from a function call
+;; and then is moved into an FP register.
+;; But it is mainly intended to test the support for these optimizations.
+
+(define_peephole
+ [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
+ (set (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "ad"))]
+ "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
+ "*
+{
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"move%.l %1,%@\", xoperands);
+ output_asm_insn (\"move%.l %1,%-\", operands);
+ return \"fmove%.d %+,%0\";
+}
+")
+
+;; FPA multiply and add.
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (plus:DF (mult:DF (match_operand:DF 1 "general_operand" "%x,dmF,y")
+ (match_operand:DF 2 "general_operand" "xH,y,y"))
+ (match_operand:DF 3 "general_operand" "xH,y,dmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpma%.d %1,%w2,%w3,%0\";
+ return \"fpma%.d %x1,%x2,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (plus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF")
+ (mult:DF (match_operand:DF 2 "general_operand" "%x,dmF,y")
+ (match_operand:DF 3 "general_operand" "xH,y,y"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpma%.d %2,%w3,%w1,%0\";
+ return \"fpma%.d %x2,%x3,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (plus:SF (mult:SF (match_operand:SF 1 "general_operand" "%x,ydmF,y")
+ (match_operand:SF 2 "general_operand" "xH,y,ydmF"))
+ (match_operand:SF 3 "general_operand" "xH,ydmF,ydmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpma%.s %1,%w2,%w3,%0\";
+ return \"fpma%.s %1,%2,%3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (plus:SF (match_operand:SF 1 "general_operand" "xH,ydmF,ydmF")
+ (mult:SF (match_operand:SF 2 "general_operand" "%x,ydmF,y")
+ (match_operand:SF 3 "general_operand" "xH,y,ydmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpma%.s %2,%w3,%w1,%0\";
+ return \"fpma%.s %2,%3,%1,%0\";
+}")
+
+;; FPA Multiply and subtract
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (minus:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
+ (mult:DF (match_operand:DF 2 "register_operand" "%xH,y,y")
+ (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpms%.d %3,%w2,%w1,%0\";
+ return \"fpms%.d %x3,%2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
+ (mult:SF (match_operand:SF 2 "register_operand" "%xH,rmF,y")
+ (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpms%.s %3,%w2,%w1,%0\";
+ return \"fpms%.s %3,%2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "%xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpmr%.d %2,%w1,%w3,%0\";
+ return \"fpmr%.d %x2,%1,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpmr%.s %2,%w1,%w3,%0\";
+ return \"fpmr%.s %x2,%1,%x3,%0\";
+}")
+
+;; FPA Add and multiply
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (plus:DF (match_operand:DF 1 "register_operand" "%xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpam%.d %2,%w1,%w3,%0\";
+ return \"fpam%.d %x2,%1,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
+ (plus:DF (match_operand:DF 2 "register_operand" "%xH,y,y")
+ (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpam%.d %3,%w2,%w1,%0\";
+ return \"fpam%.d %x3,%2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (plus:SF (match_operand:SF 1 "register_operand" "%xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpam%.s %2,%w1,%w3,%0\";
+ return \"fpam%.s %x2,%1,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
+ (plus:SF (match_operand:SF 2 "register_operand" "%xH,rmF,y")
+ (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpam%.s %3,%w2,%w1,%0\";
+ return \"fpam%.s %x3,%2,%x1,%0\";
+}")
+
+;;FPA Subtract and multiply
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (minus:DF (match_operand:DF 1 "register_operand" "xH,y,y")
+ (match_operand:DF 2 "general_operand" "x,y,rmF"))
+ (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpsm%.d %2,%w1,%w3,%0\";
+ return \"fpsm%.d %x2,%1,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=x,y,y")
+ (mult:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
+ (minus:DF (match_operand:DF 2 "register_operand" "xH,y,y")
+ (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpsm%.d %3,%w2,%w1,%0\";
+ return \"fpsm%.d %x3,%2,%x1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (minus:SF (match_operand:SF 1 "register_operand" "xH,rmF,y")
+ (match_operand:SF 2 "general_operand" "x,y,yrmF"))
+ (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpsm%.s %2,%w1,%w3,%0\";
+ return \"fpsm%.s %x2,%1,%x3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=x,y,y")
+ (mult:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
+ (minus:SF (match_operand:SF 2 "register_operand" "xH,rmF,y")
+ (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
+ "TARGET_FPA"
+ "*
+{
+ if (which_alternative == 0)
+ return \"fpsm%.s %3,%w2,%w1,%0\";
+ return \"fpsm%.s %x3,%2,%x1,%0\";
+}")
+
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- comment-start-skip: ";+- *"
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/m88k.md b/gcc-1.40/config/m88k.md
new file mode 100644
index 0000000..366ac90
--- /dev/null
+++ b/gcc-1.40/config/m88k.md
@@ -0,0 +1,2273 @@
+;;- Machine description for the Motorola 88000 for GNU C compiler
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+;; Contributed by Michael Tiemann (tiemann@mcc.com)
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+
+;; Compare instructions.
+;; This pattern is used for generating an "insn"
+;; which does just a compare and sets a (fictitious) condition code.
+
+;; The actual the m88000 insns are compare-and-conditional-jump.
+;; The define_peephole's below recognize the combinations of
+;; compares and jumps, and output each pair as a single assembler insn.
+
+;; This controls RTL generation and register allocation.
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "arith_operand" "rI")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == CONST_INT)
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cmp r25,%1,%0\";
+ }
+ return \"cmp r25,%0,%1\";
+}")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "nonmemory_operand" "rG")
+ (match_operand:DF 1 "nonmemory_operand" "rG")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == CONST_DOUBLE)
+ {
+ cc_status.flags |= CC_REVERSED | CC_IN_FCCR;
+ return \"fcmp.sdd r25,%1,%0\";
+ }
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmp.sdd r25,%0,%1\";
+}")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "nonmemory_operand" "rG")
+ (match_operand:SF 1 "nonmemory_operand" "rG")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == CONST_DOUBLE)
+ {
+ cc_status.flags |= CC_REVERSED | CC_IN_FCCR;
+ return \"fcmp.sss r25,%1,%0\";
+ }
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmp.sss r25,%0,%1\";
+}")
+;; We have to have this because cse can optimize the previous pattern
+;; into this one.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "cmp r25,%0,0")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "register_operand" "r"))]
+ ""
+ "*
+{
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmp.sds r25,%0,r0\";
+}")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "r"))]
+ ""
+ "*
+{
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmp.sss r25,%0,r0\";
+}")
+
+;; These control RTL generation for conditional jump insns
+;; and match them for register allocation.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 eq,r25,%l0")
+
+(define_peephole
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))
+ (set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bcnd eq0,%0,%l1\";
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 ne,r25,%l0")
+
+(define_peephole
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))
+ (set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bcnd ne0,%0,%l1\";
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 gt,r25,%l0")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 hi,r25,%l0")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 lt,r25,%l0")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 lo,r25,%l0")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 ge,r25,%l0")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 hs,r25,%l0")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 le,r25,%l0")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bb1 ls,r25,%l0")
+
+;; These match inverted jump insns for register allocation.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 eq,r25,%l0")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bcnd ne0,%0,%l1\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 ne,r25,%l0")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"bcnd eq0,%0,%l1\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 gt,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 hi,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 lt,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 lo,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 ge,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 hs,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 le,r25,%l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bb0 ls,r25,%l0")
+
+;; Move instructions
+
+(define_insn "swapsi"
+ [(set (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (set (match_dup 1) (match_dup 0))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ {
+ CC_STATUS_INIT;
+ return \"ld r25,%0\;xmem r25,%1\;st r25,%0\";
+ }
+ if (! REG_P (operands[1]))
+ return \"xmem %0,%1\";
+ if (REG_P (operands[0]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"\";
+ return \"xor %0,%0,%1\;xor %1,%1,%0\;xor %0,%0,%1\";
+ }
+ return \"xmem %1,%0\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "memory_operand" "m"))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (match_operand:SI 3 "memory_operand" "m"))
+ (set (match_dup 1) (match_dup 2))
+ (set (match_dup 3) (match_dup 0))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"ld r25,%1\;xmem r25,%3\;st r25,%1\";
+}")
+
+(define_insn "swapqi"
+ [(set (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g"))
+ (set (match_dup 1) (match_dup 0))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ {
+ CC_STATUS_INIT;
+ return \"ld.bu r25,%0\;xmem.bu r25,%1\;st.bu r25,%0\";
+ }
+ if (! REG_P (operands[1]))
+ return \"xmem.bu %0,%1\";
+ if (REG_P (operands[0]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"\";
+ return \"xor %0,%0,%1\;xor %1,%1,%0\;xor %0,%0,%1\";
+ }
+ return \"xmem.bu %1,%0\";
+}")
+
+(define_peephole
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (match_operand:QI 1 "memory_operand" "m"))
+ (set (match_operand:QI 2 "register_operand" "=r")
+ (match_operand:QI 3 "memory_operand" "m"))
+ (set (match_dup 1) (match_dup 2))
+ (set (match_dup 3) (match_dup 0))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"ld.bu r25,%1\;xmem.bu r25,%3\;st.bu r25,%1\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "g")
+ (const_int 0))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ return \"or %0,r0,0\";
+ return \"st r0,%0\";
+}")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g,r")
+ (match_operand:SI 1 "general_operand" "r,mi"))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld %0,%1\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ if (GET_CODE (operands[1]) == LABEL_REF
+ || GET_CODE (operands[1]) == SYMBOL_REF)
+ return \"lda %0,r0,%1\";
+ return \"or %0,r0,%1\";
+ }
+ return \"st %1,%0\";
+}")
+
+;; Simulate pre inc. Post inc/dec is automatically optimized
+;; by sheer luck. ?? In which phase should this really be done??
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI"))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "ld %0,%1,%2\\t;; pipelined!\;addu %1,%1,%2\\t;; /")
+
+(define_insn ""
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ ""
+ "st %2,%0,%1\\t;; pipelined!\;addu %0,%0,%1\\t;; /")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "g")
+ (const_int 0))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ return \"or %0,r0,0\";
+ return \"st.h r0,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g,r")
+ (match_operand:HI 1 "general_operand" "r,mn"))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld.h %0,%1\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (HImode, operands);
+ return \"or %0,r0,%1\";
+ }
+ return \"st.h %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (sign_extend:SI
+ (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "ld.h %0,%1,%2\\t;; pipelined!\;addu %1,%1,%2\\t;; /")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (zero_extend:SI
+ (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "ld.hu %0,%1,%2\\t;; pipelined!\;addu %1,%1,%2\\t;; /")
+
+(define_insn ""
+ [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ ""
+ "st.h %2,%0,%1\\t;; pipelined!\;addu %0,%0,%1\\t;; /")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "g")
+ (const_int 0))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ return \"or %0,r0,0\";
+ return \"st.b r0,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=g,r")
+ (match_operand:QI 1 "general_operand" "r,mn"))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld.b %0,%1\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (QImode, operands);
+ return \"or %0,r0,%1\";
+ }
+ return \"st.b %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (sign_extend:SI
+ (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "ld.b %0,%1,%2\\t;; pipelined!\;addu %1,%1,%2\\t;; /")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (zero_extend:SI
+ (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "ld.bu %0,%1,%2\\t;; pipelined!\;addu %1,%1,%2\\t;; /")
+
+(define_insn ""
+ [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (match_operand:SI 2 "register_operand" "r"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ ""
+ "st.b %2,%0,%1\\t;; pipelined!\;addu %0,%0,%1\\t;; /")
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+(define_insn "movstrsi"
+ [(set (match_operand:BLK 0 "general_operand" "=g")
+ (match_operand:BLK 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "arith32_operand" "rn"))
+ (clobber (reg:SI 10))
+ (clobber (reg:SI 11))
+ (clobber (reg:SI 12))]
+ ""
+ "* output_block_move (operands);")
+
+;; This pattern forces (set (reg:DF ...) (const_double ...))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general movdf pattern.
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=r,o")
+ (match_operand:DF 1 "" "mG,G"))]
+ "GET_CODE (operands[1]) == CONST_DOUBLE"
+ "*
+{
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
+ {
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"add %0,r0,0\;add %1,r0,0\";
+ }
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"st r0,%0\;st r0,%1\";
+ }
+ return output_move_double (operands);
+}
+")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=r,m")
+ (match_operand:DF 1 "general_operand" "rm,r"))]
+ ""
+ "* return output_move_double (operands);")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=r,m")
+ (match_operand:DI 1 "general_operand" "rm,r"))]
+ ""
+ "* return output_move_double (operands);")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=g,r")
+ (match_operand:SF 1 "general_operand" "r,mF"))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld %0,%1\";
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return output_store_const_float (SFmode, operands);
+ return \"or %0,r0,%1\";
+ }
+ return \"st %1,%0\";
+}")
+
+;;- load effective address
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "lda.b %0,%a1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:HI 1 "address_operand" "p"))]
+ ""
+ "lda.w %0,%a1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "lda %0,%a1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:DI 1 "address_operand" "p"))]
+ ""
+ "lda.d %0,%a1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SF 1 "address_operand" "p"))]
+ ""
+ "lda %0,%a1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:DF 1 "address_operand" "p"))]
+ ""
+ "lda.d %0,%a1")
+
+;;- truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st.b %1,%0\";
+ return \"or %0,r0,%1\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st.b %1,%0\";
+ return \"or %0,r0,%1\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (truncate:HI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st.h %1,%0\";
+ return \"or %0,r0,%1\";
+}")
+
+;;- zero extension instructions
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"mask %0,%1,0xffff\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.hu %0,%1\";
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"mask %0,%1,0xff\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.bu %0,%1\";
+}")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"mask %0,%1,0xff\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.bu %0,%1\";
+}")
+
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"ext %0,%1,16<0>\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.h %0,%1\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"ext %0,%1,8<0>\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.b %0,%1\";
+}")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"ext %0,%1,8<0>\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_store_const_int (SImode, operands);
+ return \"ld.b %0,%1\";
+}")
+
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=r")
+ (float_extend:DF
+ (match_operand:SF 1 "general_operand" "r")))]
+ ""
+ "fadd.dss %0,r0,%1")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=r")
+ (float_truncate:SF
+ (match_operand:DF 1 "general_operand" "r")))]
+ ""
+ "fadd.ssd %0,r0,%1")
+;; Conversions between floating point and integer
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=r")
+ (float:DF (match_operand:SI 1 "general_operand" "r")))]
+ ""
+ "flt.ds %0,%1")
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=r")
+ (float:SF (match_operand:SI 1 "general_operand" "r")))]
+ ""
+ "flt.ss %0,%1")
+
+(define_insn "fixdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "r"))))]
+ ""
+ "int.sd %0,%1")
+
+(define_insn "fixsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "r"))))]
+ ""
+ "int.ss %0,%1")
+
+;;- arithmetic instructions
+;;- add instructions
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "arith32_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"addu %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"addu %0,%1,%2\";
+ if (INT_FITS_16_BITS (-i))
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, -i);
+ return \"subu %0,%1,%2\";
+ }
+ return \"or.u %0,r0,hi16(%2)\;or %0,%0,lo16(%2)\;addu %0,%1,%0\";
+}")
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (plus:DF (match_operand:DF 1 "register_operand" "%r")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "fadd.ddd %0,%1,%2")
+
+;; a bunch more can go in here!
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (plus:SF (match_operand:SF 1 "register_operand" "%r")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "fadd.sss %0,%1,%2")
+
+;;- subtract instructions
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"subu %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"subu %0,%1,%2\";
+ if (INT_FITS_16_BITS (-i))
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, -i);
+ return \"addu %0,%1,%2\";
+ }
+ return \"or.u %0,r0,hi16(%2)\;or %0,%0,lo16(%2)\;subu %0,%1,%0\";
+}")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (minus:DF (match_operand:DF 1 "register_operand" "%r")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "fsub.ddd %0,%1,%2")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (minus:SF (match_operand:SF 1 "register_operand" "%r")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "fsub.sss %0,%1,%2")
+
+;;- multiply instructions
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"mul %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"mul %0,%1,%2\";
+ return \"or.u %0,r0,hi16(%2)\;or %0,%0,lo16(%2)\;mul %0,%1,%0\";
+}")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umult:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "mul %0,%1,%2")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (mult:DF (match_operand:DF 1 "register_operand" "%r")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "fmul.ddd %0,%1,%2")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (mult:SF (match_operand:SF 1 "register_operand" "%r")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "fmul.sss %0,%1,%2")
+
+;;- divide instructions
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"div %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"div %0,%1,%2\";
+ return \"or.u %0,r0,hi16(%2)\;or %0,%0,lo16(%2)\;div %0,%1,%0\";
+}")
+
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "div %0,%1,%2")
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (div:DF (match_operand:DF 1 "register_operand" "r")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "fdiv.ddd %0,%1,%2")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (div:SF (match_operand:SF 1 "register_operand" "r")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "fdiv.sss %0,%1,%2")
+
+;; Remainder instructions.
+
+(define_insn "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"div %0,%1,%2\;mul %0,%0,%2\;sub %0,%1,%0\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"div %0,%1,%2\;mul %0,%0,%2\;sub %0,%1,%0\";
+ if (INT_FITS_16_BITS (-i))
+ fatal (\"implement negative case for mod\");
+ fatal (\"implement 32 bit case for mod\");
+}")
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"div %0,%1,%2\;mul %0,%0,%2\;sub %0,%1,%0\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"div %0,%1,%2\;mul %0,%0,%2\;sub %0,%1,%0\";
+ if (INT_FITS_16_BITS (-i))
+ fatal (\"implement negative case for umod\");
+ fatal (\"implement 32 bit case for umod\");
+}")
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "div %0,%1,%2\;mul %3,%0,%2\;sub %3,%1,%3")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (umod:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "div %0,%1,%2\;mul %3,%0,%2\;sub %3,%1,%3")
+
+;;- and instructions (with complement also)
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"and %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"mask %0,%1,%2\";
+ if (INT_FITS_16_BITS (-i))
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, i & 0xffff);
+ return \"and %0,%1,%2\";
+ }
+ return \"and.u %0,%1,hi16(%2)\;and %0,%1,lo16(%2)\";
+}")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "%r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "and.c %0,%1,%2")
+
+;;- Bit set (inclusive or) instructions (with complement also)
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"or %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"or %0,%1,%2\";
+ return \"or.u %0,%1,hi16(%2)\;or %0,%1,lo16(%2)\";
+}")
+
+(define_insn "iorcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "or.c %0,%1,%2")
+
+;;- xor instructions (with complement also)
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ unsigned int i;
+
+ if (REG_P (operands[2]))
+ return \"xor %0,%1,%2\";
+ i = INTVAL (operands[2]);
+ if (INT_FITS_16_BITS (i))
+ return \"xor %0,%1,%2\";
+ if ((i & 0xffff) == 0)
+ return \"xor.u %0,%1,hi16(%2)\";
+ return \"xor.u %0,%1,hi16(%2)\;xor %0,%1,lo16(%2)\";
+}")
+
+(define_insn "xorcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "xor.c %0,%1,%2")
+
+;;- one complement instructions
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "xor.c %0,%1,r0")
+
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ ""
+ "ld.b %0,%1")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ ""
+ "ld.bu %0,%1")
+
+;;- arithmetic shift instructions
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"mak %0,%1,0<%2>\";
+ return \"mask %0,%2,0x1f\;mak %0,%1,%0\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"ext %0,%1,0<%2>\";
+ return \"mask %0,%2,0x1f\;ext %0,%1,%0\";
+}")
+
+;;- logical shift instructions
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"extu %0,%1,0<%2>\";
+ return \"mask %0,%2,0x1f\;extu %0,%1,%0\";
+}")
+
+;;- rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[2] = gen_rtx (CONST_INT, SImode, 32 - INTVAL (operands[2]));
+ return \"rot %0,%1,%2\";
+ }
+ return \"or %0,r0,32\;sub %0,%2,%0\;rot %0,%1,%0\";
+}")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "rot %0,%1,%2")
+
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+ro")
+ (match_operand:SI 1 "int5_operand" "K")
+ (match_operand:SI 2 "int5_operand" "K"))
+ (match_operand:SI 3 "register_operand" "r"))]
+ "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
+ return \"mak %0,%3,%1<%2>\";
+ }
+ else
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ if (GET_CODE (operands[3]) == MEM)
+ operands[3] = adj_offsettable_operand (operands[3],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[1]) == 8)
+ return \"st.b %3,%0\";
+ return \"st.w %3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "ro")
+ (match_operand:SI 2 "int5_operand" "K")
+ (match_operand:SI 3 "int5_operand" "K")))]
+ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"extu %0,%1,%2<%3>\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[0] = adj_offsettable_operand (operands[0],
+ (32 - INTVAL (operands[1])) / 8);
+ if (INTVAL (operands[2]) == 8)
+ return \"ld.bu %0,%1\";
+ return \"ld.hu %0,%1\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "ro")
+ (match_operand:SI 2 "int5_operand" "K")
+ (match_operand:SI 3 "int5_operand" "K")))]
+ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
+ return \"extu %0,%1,%2<%3>\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"ld.b %0,%1\";
+ return \"ld.h %0,%1\";
+}")
+
+;; Bit field instructions.
+
+(define_insn "extv"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extract:SI (match_operand:QI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_operand" "K,rK")
+ (match_operand:SI 3 "arith_operand" "K,&r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[3]) == CONST_INT)
+ return \"ext %0,%1,%2<%3>\";
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) & 0x1f) << 5);
+ return \"mask %3,%3,0x1f\;or %3,%3,%2\;ext %0,%1,%3\";
+ }
+ return \"mak %0,%2,5<5>\;mask %3,%3,0x1f\;or %3,%3,%0\;ext %0,%1,%3\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_operand" "K,rK")
+ (match_operand:SI 3 "arith_operand" "K,&r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[3]) == CONST_INT)
+ return \"ext %0,%1,%2<%3>\";
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) & 0x1f) << 5);
+ return \"mask %3,%3,0x1f\;or %3,%3,%2\;ext %0,%1,%3\";
+ }
+ return \"mak %0,%2,5<5>\;mask %3,%3,0x1f\;or %3,%3,%0\;ext %0,%1,%3\";
+}")
+
+(define_insn "extzv"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (match_operand:QI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_operand" "K,Kr")
+ (match_operand:SI 3 "arith_operand" "K,&r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[3]) == CONST_INT)
+ return \"extu %0,%1,%2<%3>\";
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) & 0x1f) << 5);
+ return \"mask %3,%3,0x1f\;or %3,%3,%2\;extu %0,%1,%3\";
+ }
+ return \"mak %0,%2,5<5>\;mask %3,%3,0x1f\;or %3,%3,%0\;ext %0,%1,%3\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_operand" "K,Kr")
+ (match_operand:SI 3 "arith_operand" "K,&r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[3]) == CONST_INT)
+ return \"extu %0,%1,%2<%3>\";
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[2]) & 0x1f) << 5);
+ return \"mask %3,%3,0x1f\;or %3,%3,%2\;extu %0,%1,%3\";
+ }
+ return \"mak %0,%2,5<5>\;mask %3,%3,0x1f\;or %3,%3,%0\;ext %0,%1,%3\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r,r")
+ (match_operand:SI 1 "arith_operand" "K,K,&r")
+ (match_operand:SI 2 "arith_operand" "K,&r,&"))
+ (const_int 0))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"clr %0,%0,%1<%2>\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[1]) & 0x1f) << 5);
+ return \"mask %2,%2,0x1f\;or %2,%2,%1\;clr %0,%0,%2\";
+ }
+ return \"mak %1,%1,5<5>\;mask %2,%2,0x1f\;or %2,%2,%1\;clr %0,%0,%2\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r,r")
+ (match_operand:SI 1 "arith_operand" "K,K,&r")
+ (match_operand:SI 2 "arith_operand" "K,&r,&r"))
+ (const_int -1))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"set %0,%0,%1<%2>\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[1]) & 0x1f) << 5);
+ return \"mask %2,%2,0x1f\;or %2,%2,%1\;set %0,%0,%2\";
+ }
+ return \"mak %1,%1,5<5>\;mask %2,%2,0x1f\;or %2,%2,%1\;set %0,%0,%2\";
+}")
+
+(define_insn "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r,r")
+ (match_operand:SI 1 "arith_operand" "K,K,&r")
+ (match_operand:SI 2 "arith_operand" "K,&r,&r"))
+ (match_operand:SI 3 "register_operand" "&r,&r,r"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"mak %3,%3,%1<%2>\;clr %0,%0,%1<%2>\;or %0,%0,%3\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[1]) & 0x1f) << 5);
+ return \"mask %2,%2,0x1f\;or %2,%2,%1\;mak %3,%3,%2\;clr %0,%0,%2\;or %0,%0,%3\";
+ }
+ return \"mak %1,%1,5<5>\;mask %2,%2,0x1f\;or %2,%2,%1\;mak %1,%3,%2\;clr %0,%0,%2\;or %0,%0,%1\";
+}")
+
+;; negate insns
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "sub %0,r0,%1")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+ ""
+ "fsub.dsd %0,r0,%1")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (neg:SF (match_operand:SF 1 "register_operand" "r")))]
+ ""
+ "fsub.sss %0,r0,%1")
+
+;; Store condition code values into registers
+(define_insn "seq"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<eq>\";
+ return \"extu r25,r25,1<eq>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<eq>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<eq>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<eq>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<eq>\;st r25,%2\";
+}")
+
+(define_insn "sne"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<ne>\";
+ return \"extu r25,r25,1<ne>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<ne>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<ne>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<ne>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<ne>\;st r25,%2\";
+}")
+
+(define_insn "sgt"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<gt>\";
+ return \"extu r25,r25,1<gt>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<gt>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<gt>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<gt>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<gt>\;st r25,%2\";
+}")
+
+(define_insn "sgtu"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<hi>\";
+ return \"extu r25,r25,1<hi>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<hi>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<hi>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<hi>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<hi>\;st r25,%2\";
+}")
+
+(define_insn "slt"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<lt>\";
+ return \"extu r25,r25,1<lt>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<lt>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<lt>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<lt>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<lt>\;st r25,%2\";
+}")
+
+(define_insn "sltu"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<lo>\";
+ return \"extu r25,r25,1<lo>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<lo>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<lo>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<lo>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<lo>\;st r25,%2\";
+}")
+
+(define_insn "sge"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<ge>\";
+ return \"extu r25,r25,1<ge>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<ge>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<ge>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<ge>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<ge>\;st r25,%2\";
+}")
+
+(define_insn "sgeu"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<hs>\";
+ return \"extu r25,r25,1<hs>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<hs>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<hs>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<hs>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<hs>\;st r25,%2\";
+}")
+
+(define_insn "sle"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<le>\";
+ return \"extu r25,r25,1<le>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<le>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<le>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (le (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<le>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<le>\;st r25,%2\";
+}")
+
+(define_insn "sleu"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[0]))
+ return \"extu %0,r25,1<ls>\";
+ return \"extu r25,r25,1<ls>\;st r25,%0\";
+}")
+
+(define_peephole
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))
+ (set (match_operand:SI 1 "general_operand" "=g")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[1]))
+ return \"cmp r25,%0,0\;extu %1,r25,1<ls>\";
+ return \"cmp r25,%0,0\;extu r25,r25,1<ls>\;st r25,%1\";
+}")
+
+(define_peephole
+ [(set (cc0)
+ (compare
+ (match_operand:SI 0 "arith_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (REG_P (operands[2]))
+ return \"cmp r25,%0,%1\;extu %2,r25,1<ls>\";
+ return \"cmp r25,%0,%1\;extu r25,r25,1<ls>\;st r25,%2\";
+}")
+
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "br %l0")
+
+(define_insn ""
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))
+ (clobber (const_int 1))]
+ ""
+ "br.n %l0")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp %0")
+
+;;- jump to subroutine
+(define_insn "call"
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "general_operand" "g"))
+ (use (reg:SI 1))]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "*
+{
+ operands[0] = XEXP (operands[0], 0);
+ if (REG_P (operands[0]))
+ return \"jsr %0\";
+ return \"bsr %0\";
+}")
+
+(define_insn ""
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "general_operand" "g"))
+ (clobber (const_int 1))
+ (use (reg:SI 1))]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "*
+{
+ operands[0] = XEXP (operands[0], 0);
+ if (REG_P (operands[0]))
+ return \"jsr.n %0\";
+ return \"bsr.n %0\";
+}")
+
+;;- jump to subroutine
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=r")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "general_operand" "g")))
+ (use (reg:SI 1))]
+ ;;- Don't use operand 2 for most machines.
+ ""
+ "*
+{
+ operands[1] = XEXP (operands[1], 0);
+ if (REG_P (operands[1]))
+ return \"jsr %1\";
+ return \"bsr %1\";
+}")
+
+(define_insn ""
+ [(set (match_operand 0 "" "=r")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "general_operand" "g")))
+ (use (reg:SI 1))
+ (clobber (const_int 2))]
+ ;;- Don't use operand 2 for most machines.
+ ""
+ "*
+{
+ operands[1] = XEXP (operands[1], 0);
+ if (REG_P (operands[1]))
+ return \"jsr.n %1\";
+ return \"bsr.n %1\";
+}")
+
+;; A memory ref with constant address is not normally valid.
+;; But it is valid in a call insns. This pattern allows the
+;; loading of the address to combine with the call.
+(define_insn ""
+ [(call (mem:SI (match_operand:SI 0 "" "i"))
+ (match_operand:SI 1 "general_operand" "g"))
+ (use (reg:SI 1))]
+ ;;- Don't use operand 1 for most machines.
+ "GET_CODE (operands[0]) == SYMBOL_REF"
+ "bsr %0")
+
+(define_insn ""
+ [(call (mem:SI (match_operand:SI 0 "" "i"))
+ (match_operand:SI 1 "general_operand" "g"))
+ (clobber (const_int 1))
+ (use (reg:SI 1))]
+ ;;- Don't use operand 1 for most machines.
+ "GET_CODE (operands[0]) == SYMBOL_REF"
+ "bsr.n %0")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;; Recognize jbs and jbc instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "bb1 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "bb0 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "bb0 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "bb1 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "bb1 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "bb0 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "exact_log2 (INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"bb1 %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "exact_log2 (INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"bb0 %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "exact_log2 (INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"bb0 %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "exact_log2 (INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"bb1 %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "bb0 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "int5_operand" "K"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "bb1 %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "bb1 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "bb0 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "bb0 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "bb1 0,%0,%l1")
+
+;; These four entries allow a jlbc or jlbs,to be made
+;; by combination with a bic.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "bb1 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "bb0 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "bb0 0,%0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "bb1 0,%0,%l1")
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/mips.md b/gcc-1.40/config/mips.md
new file mode 100644
index 0000000..82b4a50
--- /dev/null
+++ b/gcc-1.40/config/mips.md
@@ -0,0 +1,1957 @@
+;; Mips.md Naive version of Machine Description for MIPS
+;; Contributed by A. Lichnewsky, lich@inria.inria.fr
+;; Changes by Michael Meissner, meissner@osf.org
+;; Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;;
+;;------------------------------------------------------------------------
+;;
+
+;;
+;; ....................
+;;
+;; Peephole Optimizations for
+;;
+;; ARITHMETIC
+;;
+;; ....................
+;;
+ ;;- The following peepholes are
+ ;;- motivated by the fact that
+ ;;- stack movement result in some
+ ;;- cases in embarrassing sequences
+ ;;- of addiu SP,SP,int
+ ;;- addiu SP,SP,other_int
+
+ ;;- --------------------
+ ;;- REMARK: this would be done better
+ ;;- by analysis of dependencies in
+ ;;- basic blocks, prior to REG ALLOC,
+ ;;- and simplification of trees:
+ ;;- (+ (+ REG const) const)
+ ;;- -> (+ REG newconst)
+ ;;- --------------------
+ ;;- Merged peephole code from
+ ;;- raeburn@ATHENA.MIT.EDU
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator 1 "additive_op"
+ [(match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "small_int" "I")]))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (match_operator 5 "additive_op"
+ [(match_dup 0)
+ (match_operand:SI 6 "small_int" "I")]))]
+ "(REGNO (operands[0]) == REGNO (operands[4])
+ || dead_or_set_p (insn, operands[0]))"
+ "*
+{
+ int addend;
+ /* compute sum, with signs */
+ addend = INTVAL (operands[3]) * (GET_CODE (operands[1]) == PLUS ? 1 : -1);
+ addend += INTVAL (operands[6]) * (GET_CODE (operands[5]) == PLUS ? 1 : -1);
+ if (addend != 0)
+ {
+ operands[0] = gen_rtx (CONST_INT, VOIDmode, addend);
+ return \"addi%:\\t%4,%2,%0\";
+ }
+ /* value is zero; copy */
+ if (REGNO (operands[4]) != REGNO (operands[2]))
+ return \"add%:\\t%4,%2,$0\";
+ /* copying to self; punt */
+ return \" # null operation: additive operands cancel (%0,%2)\";
+}")
+
+;;
+;; ....................
+;;
+;; ARITHMETIC
+;;
+;; ....................
+;;
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "add.d\\t%0,%1,%2")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "add.s\\t%0,%1,%2")
+
+;; The following is generated when omiting the frame pointer
+;; and for referencing large auto arrays during optimization.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx"
+ "*
+{
+ int number;
+ if (GET_CODE (operands[2]) != CONST_INT)
+ return \"add%:\\t%0,%1,%2\";
+
+ number = INTVAL (operands[2]);
+ if (((unsigned) (number + 0x8000) > 0xffff))
+ {
+ operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */
+ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tadd%:\\t%0,%1,%3\\n\\t.set\\tat\";
+ }
+
+ return (number < 0) ? \"sub%:\\t%0,%1,%n2\" : \"add%:\\t%0,%1,%2\";
+}")
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ ? \"sub%:\\t%0,%1,%n2\"
+ : \"add%:\\t%0,%1,%2\";
+}")
+
+
+;;- All kinds of subtract instructions.
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (minus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "sub.d\\t%0,%1,%2")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (minus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "sub.s\\t%0,%1,%2")
+
+;; The following is generated when omiting the frame pointer
+;; and for referencing large auto arrays during optimization.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx"
+ "*
+{
+ int number;
+ if (GET_CODE (operands[2]) != CONST_INT)
+ return \"sub%:\\t%0,%1,%2\";
+
+ number = INTVAL (operands[2]);
+ if (((unsigned) (number + 0x8000) > 0xffff))
+ {
+ operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */
+ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tsub%:\\t%0,%1,%3\\n\\t.set\\tat\";
+ }
+
+ return (number < 0) ? \"add%:\\t%0,%1,%n2\" : \"sub%:\\t%0,%1,%2\";
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ ? \"add%:\\t%0,%1,%n2\"
+ : \"sub%:\\t%0,%1,%2\";
+}")
+
+
+;;- Multiply instructions.
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "mul.d\\t%0,%1,%2")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "mul.s\\t%0,%1,%2")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "mul\\t%0,%1,%2")
+
+
+;;- Divide instructions.
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "div.d\\t%0,%1,%2")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "div.s\\t%0,%1,%2")
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mod:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "div\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "div\\t%0,%1,%2")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (umod:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "divu\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "divu\\t%0,%1,%2")
+
+
+;; Remainder instructions
+
+
+(define_insn "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "rem\\t%0,%1,%2")
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "remu\\t%0,%1,%2")
+
+
+;; Absoluate value instructions -- Don't use the integer abs,
+;; since that signals an exception on -2147483648 (sigh).
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "abs.s\\t%0,%1")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "abs.d\\t%0,%1")
+
+;;
+;; ....................
+;;
+;; LOGICAL
+;;
+;; ....................
+;;
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (and:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "and\\t%0,%1,%2\;and\\t%D0,%D1,%D2")
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rK")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"andi\\t%0,%1,%x2\"
+ : \"and\\t%0,%1,%2\";
+}")
+
+
+;; Simple hack to recognize the "nor" instruction on the MIPS
+;; [rms: I don't think the following is actually required.]
+;; This must appear before the normal or patterns, so that the
+;; combiner will correctly fold things.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (ior:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r"))))]
+ ""
+ "nor\\t%0,%1,%2\;nor\\t%D0,%D1,%D2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (ior:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "nor\\t%0,%1,%2")
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (ior:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "or\\t%0,%1,%2\;or\\t%D0,%D1,%D2")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rJ")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"ori\\t%0,%1,%x2\"
+ : \"or\\t%0,%1,%2\";
+}")
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (xor:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "xor\\t%0,%1,%2\;xor\\t%D0,%D1,%D2")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rK")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"xori\\t%0,%1,%x2\"
+ : \"xor\\t%0,%1,%2\";
+}")
+
+;;
+;; ....................
+;;
+;; TRUNCATION
+;;
+;; ....................
+
+;; Extension and truncation insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "andi\\t%0,%1,0xff\\t#truncsiqi2\\t %1 -> %0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#truncsihi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x10\\t#truncsihi2\\t %1 -> %0\";
+")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "andi\\t%0,%1,0xff\\t#trunchiqi2\\t %1 -> %0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "cvt.s.d\\t%0,%1\\t#truncdfsf2\\t %1 -> %0")
+
+;;
+;; ....................
+;;
+;; ZERO EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#zero_extendhisi2\\t %1 -> %0\",
+ operands);
+ return \"srl\\t%0,%0,0x10\\t#zero_extendhisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lhu\\t%0,%1\\t#zero extendhisi2 %1 -> %0\";
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#zero_extendqihi2\\t %1 -> %0\",
+ operands);
+ return \"srl\\t%0,%0,0x18\\t#zero_extendqihi2\\t %1 -> %0\";
+ ")
+
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ return \"andi\\t%0,%1,0xff\\t#zero_extendqisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lbu\\t%0,%1\\t#zero extendqisi2 %1 -> %0\";
+}")
+
+
+;;
+;; ....................
+;;
+;; SIGN EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#sign extendhisi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x10\\t#sign extendhisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lh\\t%0,%1\\t#sign extendhisi2 %1 -> %0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqihi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x18\\t#sign extendqihi2\\t %1 -> %0\";
+ ")
+
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqisi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x18\\t#sign extendqisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lb\\t%0,%1\\t#sign extendqisi2 %1 -> %0\";
+}")
+
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "cvt.d.s\\t%0,%1\\t#extendsfdf2\\t %1 -> %0")
+
+
+;;
+;; ....................
+;;
+;; CONVERSIONS
+;;
+;; ....................
+
+
+(define_insn "fix_truncdfsi2_internal"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (fix:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ ""
+ "trunc.w.d %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ ""
+ "mfc1\\t%0,%1")
+
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (DFmode); /* fp reg that gets trunc result */
+ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */
+ emit_insn (gen_fix_truncdfsi2_internal (reg1, operands[1], reg2));
+ operands[1] = reg1;
+ /* Fall through and generate default code */
+}")
+
+(define_insn "fix_truncsfsi2_internal"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (fix:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ ""
+ "trunc.w.s %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ ""
+ "mfc1\\t%0,%1")
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (SFmode); /* fp reg that gets trunc result */
+ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */
+ emit_insn (gen_fix_truncsfsi2_internal (reg1, operands[1], reg2));
+ operands[1] = reg1;
+ /* Fall through and generate default code */
+}")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "mtc1\\t%1,%0\\t\\t#floatsidf2\\t%1 -> %0\;cvt.d.w\\t%0,%0")
+
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "mtc1\\t%1,%0\\t\\t#floatsisf2\\t%1 -> %0\;cvt.s.w\\t%0,%0")
+
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (DFmode);
+ rtx reg2 = gen_reg_rtx (DFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
+
+ if (reg1) /* turn off complaints about unreached code */
+ {
+ emit_move_insn (reg1, immed_real_const_1 (offset, DFmode));
+ do_pending_stack_adjust ();
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, DFmode, operands[1], reg1)));
+
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
+ gen_rtx (LABEL_REF, VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx (MINUS, DFmode, operands[1], reg1));
+ emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+ DONE;
+ }
+}")
+
+(define_expand "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (SFmode);
+ rtx reg2 = gen_reg_rtx (SFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
+
+ if (reg1) /* turn off complaints about unreached code */
+ {
+ emit_move_insn (reg1, immed_real_const_1 (offset, SFmode));
+ do_pending_stack_adjust ();
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, SFmode, operands[1], reg1)));
+
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
+ gen_rtx (LABEL_REF, VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx (MINUS, SFmode, operands[1], reg1));
+ emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+ DONE;
+ }
+}")
+
+ ;;- Wild things used when
+ ;;- unions make double and int
+ ;;- overlap.
+ ;;-
+ ;;- This must be supported
+ ;;- since corresponding code
+ ;;- gets generated
+
+(define_insn ""
+ [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0)
+ (match_operand:DF 1 "register_operand" "rf"))
+ (clobber (match_operand 2 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0)
+ (match_operand:DF 1 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=rf")
+ (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0))
+ (clobber (match_operand 2 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=rf")
+ (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+;;
+;; ....................
+;;
+;; MOVES
+;;
+;; and
+;;
+;; LOADS AND STORES
+;;
+;; ....................
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=r,*r,*m")
+ (match_operand:DI 1 "general_operand" "r,*miF,*r"))]
+ ""
+ "*
+{
+ extern rtx adj_offsettable_operand ();
+ extern int offsettable_address_p ();
+
+ if (which_alternative == 0)
+ {
+ /* Move REGISTER <- REGISTER */
+ if (REGNO (operands[0]) != (REGNO (operands[1])+1))
+ return \"move\\t%0,%1\\n\\tmove\\t%D0,%D1\";
+ else
+ return \"move\\t%D0,%D1\\n\\tmove\\t%0,%1\";
+ }
+
+ else if (which_alternative == 1)
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ /* REGISTER <- MEMORY */
+ if (offsettable_address_p (1, DImode, XEXP (operands[1], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[1], 4);
+ return \"lw\\t%0,%1\;lw\\t%D0,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%1\;lw\\t%0,0(%2)\;lw\\t%D0,4(%2)\;set\\tat\";
+ }
+ }
+
+ /* REGISTER <- small integer constant */
+ else if (CONSTANT_P (operands[1]))
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >= 0 ? 0 : -1);
+ return \"li\\t%M0,%2\;li\\t%L0,%1\";
+ }
+
+ /* Register <- large integer constant */
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[1]));
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (operands[1]));
+ return \"li\\t%M0,%3\;li\\t%L0,%2\";
+ }
+ }
+
+ else if (which_alternative == 2 && GET_CODE (operands[0]) == MEM)
+ {
+ /* Memory <- Register */
+ if (offsettable_address_p (1, DImode, XEXP (operands[0], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ return \"sw\\t%1,%0\;sw\\t%D1,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%0\;sw\\t%1,0(%2)\;sw\\t%D1,4(%2)\;set\\tat\";
+ }
+ }
+
+ abort_with_insn (insn, \"impossible case in movdi\");
+ return \"\";
+}")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r,r,m,r,r,m,*r")
+ (match_operand:SI 1 "general_operand" "r,m,r,i,J,J,*p"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lw\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sw\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sw\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movsi\");
+ return 0;
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=r,r,m,r,r,m")
+ (match_operand:HI 1 "general_operand" "r,m,r,i,J,J"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lh\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sh\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sh\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movhi\");
+ return 0;
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=r,r,m,r,r,m")
+ (match_operand:QI 1 "general_operand" "r,m,r,i,J,J"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lb\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sb\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sb\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movqi\");
+ return 0;
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=f,f,m,fy,*f,*y,*y,*m")
+ (match_operand:SF 1 "general_operand" "f,m,f,F,*y,*f,*m,*y"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG)
+ {
+ if (code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"mov.s\\t%0,%1\";
+ else
+ return \"mtc1\\t%1,%0\\t\\t# Calling sequence trick\";
+ }
+
+ else if (FP_REG_P (REGNO (operands[1])))
+ return \"mfc1\\t%0,%1\\t\\t# Calling sequence trick\";
+
+ else
+ return \"move\\t%0,%1\";
+ }
+
+ else if (code1 == CONST_DOUBLE)
+ return \"li.s\\t%0,%1\";
+
+ else if (code1 == MEM)
+ return (GP_REG_P (REGNO (operands[0]))) ? \"lw\\t%0,%1\" : \"l.s\\t%0,%1\";
+ }
+
+ else if (code0 == MEM && code1 == REG)
+ return (GP_REG_P (REGNO (operands[1]))) ? \"sw\\t%1,%0\" : \"s.s\\t%1,%0\";
+
+ abort_with_insn (insn, \"Bad movsf\");
+ return \"\";
+}")
+
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=f,f,m,fy,*f,*y,&*y,*m")
+ (match_operand:DF 1 "general_operand" "f,m,f,F,*y,*f,*m,*y"))]
+ ""
+ "*
+{
+ extern rtx adj_offsettable_operand ();
+ extern int offsettable_address_p ();
+
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG)
+ {
+ if (code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"mov.d\\t%0,%1\";
+ else
+ return \"mtc1\\t%L1,%0\\t\\t# Calling sequence trick\;mtc1\\t%M1,%D0\";
+ }
+
+ else if (FP_REG_P (REGNO (operands[1])))
+ return \"mfc1\\t%L0,%1\\t\\t# Calling sequence trick\;mfc1\\t%M0,%D1\";
+
+ else if (REGNO (operands[0]) != (REGNO (operands[1])+1))
+ return \"move\\t%0,%1\\n\\tmove\\t%D0,%D1\";
+
+ else
+ return \"move\\t%D0,%D1\\n\\tmove\\t%0,%1\";
+ }
+
+ else if (code1 == CONST_DOUBLE)
+ return \"li.d\\t%0,%1\";
+
+ else if (code1 == MEM)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ return \"l.d\\t%0,%1\";
+
+ else if (offsettable_address_p (1, DFmode, XEXP (operands[1], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[1], 4);
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"lw\\t%D0,%2\;lw\\t%0,%1\";
+ else
+ return \"lw\\t%0,%1\;lw\\t%D0,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%1\;lw\\t%0,0(%2)\;lw\\t%D0,4(%2)\;set\\tat\";
+ }
+ }
+ }
+
+ else if (code0 == MEM && code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"s.d\\t%1,%0\";
+
+ else if (offsettable_address_p (1, DFmode, XEXP (operands[0], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ return \"sw\\t%1,%0\;sw\\t%D1,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%0\;sw\\t%1,0(%2)\;sw\\t%D1,4(%2)\;set\\tat\";
+ }
+ }
+
+ abort_with_insn (insn, \"Bad movdf\");
+ return \"\";
+}")
+
+
+;;
+;; ....................
+;;
+;; OTHER ARITHMETIC AND SHIFT
+;;
+;; ....................
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"sll\\t%0,%1,%2\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"sra\\t%0,%1,%2\";
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"srl\\t%0,%1,%2\";
+}")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "sub%:\\t%0,$0,%1")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "neg.d\\t%0,%1")
+
+(define_insn "negsf2"
+
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "neg.s\\t%0,%1")
+
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "nor\\t%0,$0,%1")
+
+;;
+;; ....................
+;;
+;; COMPARISONS
+;;
+;; ....................
+
+ ;;- Order is significant here
+ ;;- because there are untyped
+ ;;- comparisons generated by
+ ;;- the optimizer
+ ;;- (set (cc0)
+ ;;- (compare (const_int 2)
+ ;;- (const_int 1)))
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "*
+ compare_collect (SImode, operands[0], operands[1]);
+ return \"\\t\\t\\t\\t# cmpsi\\t%0,%1\";
+")
+
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "*
+ compare_collect (SImode, operands[0], gen_rtx (REG, SImode, 0));
+ return \"\\t\\t\\t\\t# (set (cc0)\\t%0)\";
+")
+
+;; These patterns are hopelessly invalid, because
+;; comparing subword values properly requires extending them.
+
+;; (define_insn "cmphi"
+;; [(set (cc0)
+;; (compare (match_operand:HI 0 "register_operand" "r")
+;; (match_operand:HI 1 "register_operand" "r")))]
+;; ""
+;; "*
+;; compare_collect (HImode, operands[0], operands[1]);
+;; return \" #\\tcmphi\\t%0,%1\";
+;; ")
+;;
+;; (define_insn "cmpqi"
+;; [(set (cc0)
+;; (compare (match_operand:QI 0 "register_operand" "r")
+;; (match_operand:QI 1 "register_operand" "r")))]
+;; ""
+;; "*
+;; compare_collect (QImode, operands[0], operands[1]);
+;; return \" #\\tcmpqi\\t%0,%1\";
+;; ")
+;;
+;; (define_insn ""
+;; [(set (cc0)
+;; (match_operand:QI 0 "register_operand" "r"))]
+;; ""
+;; "*
+;; compare_collect (QImode, operands[0], gen_rtx (REG, QImode, 0));
+;; return \" #\\t (set (cc0)\\t%0)\";
+;; ")
+;;
+;; (define_insn ""
+;; [(set (cc0)
+;; (match_operand:HI 0 "register_operand" "r"))]
+;; ""
+;; "*
+;; compare_collect (HImode, operands[0], gen_rtx (REG, HImode, 0));
+;; return \" #\\t (set (cc0)\\t%0)\";
+;; ")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+ compare_collect (DFmode, operands[0], operands[1]);
+ return \" #\\t\\t\\t\\tcmpdf\\t%0,%1\" ;
+")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+ compare_collect (SFmode, operands[0], operands[1]);
+ return \"\\t\\t\\t\\t# cmpsf\\t%0,%1\" ;
+")
+
+;;
+;; ....................
+;;
+;; BRANCHES
+;;
+;; ....................
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ return \"j\\t%0\";
+ else
+ return \"j\\t%l0\";
+}")
+
+
+(define_insn "tablejump"
+ [(set (pc)
+ (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "j\\t%0")
+
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"beq\\t%0,%1,%2\\t\\t# beq\", br_ops);
+ }
+ return \"\";
+}
+ ")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bne\\t%0,%1,%2\\t\\t# bne\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt branch %0 > %1\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgt\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt branch %0 > %1\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgt\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgt\\t%0,%1,%2\\t\\t# bgt\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# blt\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# blt\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"blt\\t%0,%1,%2\\t\\t# blt\", br_ops);
+ }
+ return \" #\\tblt\\t%l0\\t\\t# blt\";
+}
+")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgtu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgtu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgtu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgtu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgtu\\t%0,%1,%2\\t\\t# bgtu\", br_ops);
+ }
+ return \" #\\tbgtu\\t%l0\\t\\t# bgtu\";
+}
+")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bltu\\t%0,%1,%2\\t\\t# bltu\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bge\\t%0,%1,%2\\t\\t# bge\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bgeu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bgeu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgeu\\t%0,%1,%2\\t\\t# bgeu\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"ble\\t%0,%1,%2\\t\\t# ble\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bleu\\t%0,%1,%2\\t\\t# bleu\", br_ops);
+ }
+ return \" #\\tbleu\\t%l0\\t\\t# bleu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"beq\\t%0,%1,%2\\t\\t# beq Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bne\\t%0,%1,%2\\t\\t# bne Inv.\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgt\\t%0,%1,%2\\t\\t# bgt Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgtu\\t%0,%1,%2\\t\\t# bgtu Inv.\", br_ops);
+ }
+ return \" #\\tbgtu\\t%l0\\t\\t# bgtu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"blt\\t%0,%1,%2\\t\\t# blt Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bltu\\t%0,%1,%2\\t\\t# bltu Inv.\", br_ops);
+ }
+ return \" #\\tbltu\\t%l0\\t\\t# bltu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge (DF) Inv.\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge (SF) Inv.\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bge\\t%0,%1,%2\\t\\t# bge Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu (DF) Inv.\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu (SF )Inv.\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgeu\\t%0,%1,%2\\t\\t# bgeu Inv.\", br_ops);
+ }
+ return \" #\\tbgeu\\t%l0\\t\\t# bgeu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"ble\\t%0,%1,%2\\t\\t# ble Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bleu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bleu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bleu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bleu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bleu\\t%0,%1,%2\\t\\t# bleu Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+;;
+;; ....................
+;;
+;; LINKAGE
+;;
+;; ....................
+
+(define_insn "call"
+ [(call (match_operand 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 31))]
+ ""
+ "*
+{
+ register rtx target = XEXP (operands[0], 0);
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ return \"jal\\t%0\";
+
+ else
+ {
+ operands[0] = target;
+ return \"jal\\t$31,%0\";
+ }
+}")
+
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 31))]
+ ""
+ "*
+{
+ register rtx target = XEXP (operands[1], 0);
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ return \"jal\\t%1\";
+
+ else
+ {
+ operands[1] = target;
+ return \"jal\\t$31,%1\";
+ }
+}")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ ".set\\tnoreorder\;nop\;.set\\treorder")
+
+(define_insn "probe"
+ [(mem:SI (reg:SI 29))]
+ ""
+ "*
+{
+ operands[0] = gen_rtx (REG, SImode, 1);
+ operands[1] = stack_pointer_rtx;
+ return \".set\\tnoat\;lw\\t%0,0(%1)\\t\\t# stack probe\;.set\\tat\";
+}")
+
+;;
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/ns32k.md b/gcc-1.40/config/ns32k.md
new file mode 100644
index 0000000..f5693de
--- /dev/null
+++ b/gcc-1.40/config/ns32k.md
@@ -0,0 +1,2636 @@
+;; BUGS:
+;; Insert no-op between an insn with memory read-write operands
+;; following by a scale-indexing operation.
+;; The Sequent assembler does not allow addresses to be used
+;; except in insns which explicitly compute an effective address.
+;; I.e., one cannot say "cmpd _p,@_x"
+;; Implement unsigned multiplication??
+
+;;- Machine descrption for GNU compiler
+;;- ns32000 Version
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+;; Contributed by Michael Tiemann (tiemann@mcc.com)
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- Instruction patterns. When multiple patterns apply,
+;;- the first one in the file is chosen.
+;;-
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+;;-
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+; tstsi is first test insn so that it is the one to match
+; a constant argument.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "rmn"))]
+ ""
+ "*
+{ cc_status.flags |= CC_REVERSED;
+ operands[1] = const0_rtx;
+ return \"cmpqd %1,%0\"; }")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "g"))]
+ ""
+ "*
+{ cc_status.flags |= CC_REVERSED;
+ operands[1] = const0_rtx;
+ return \"cmpqw %1,%0\"; }")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "g"))]
+ ""
+ "*
+{ cc_status.flags |= CC_REVERSED;
+ operands[1] = const0_rtx;
+ return \"cmpqb %1,%0\"; }")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "fmF"))]
+ "TARGET_32081"
+ "*
+{ cc_status.flags |= CC_REVERSED;
+ operands[1] = dconst0_rtx;
+ return \"cmpl %1,%0\"; }")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "fmF"))]
+ "TARGET_32081"
+ "*
+{ cc_status.flags |= CC_REVERSED;
+ operands[1] = fconst0_rtx;
+ return \"cmpf %1,%0\"; }")
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "rmn")
+ (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int i = INTVAL (operands[1]);
+ if (i <= 7 && i >= -8)
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cmpqd %1,%0\";
+ }
+ }
+ cc_status.flags &= ~CC_REVERSED;
+ if (GET_CODE (operands[0]) == CONST_INT)
+ {
+ int i = INTVAL (operands[0]);
+ if (i <= 7 && i >= -8)
+ return \"cmpqd %0,%1\";
+ }
+ return \"cmpd %0,%1\";
+}")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "g")
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ short i = INTVAL (operands[1]);
+ if (i <= 7 && i >= -8)
+ {
+ cc_status.flags |= CC_REVERSED;
+ if (INTVAL (operands[1]) > 7)
+ operands[1] = gen_rtx(CONST_INT, VOIDmode, i);
+ return \"cmpqw %1,%0\";
+ }
+ }
+ cc_status.flags &= ~CC_REVERSED;
+ if (GET_CODE (operands[0]) == CONST_INT)
+ {
+ short i = INTVAL (operands[0]);
+ if (i <= 7 && i >= -8)
+ {
+ if (INTVAL (operands[0]) > 7)
+ operands[0] = gen_rtx(CONST_INT, VOIDmode, i);
+ return \"cmpqw %0,%1\";
+ }
+ }
+ return \"cmpw %0,%1\";
+}")
+
+(define_insn "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ char i = INTVAL (operands[1]);
+ if (i <= 7 && i >= -8)
+ {
+ cc_status.flags |= CC_REVERSED;
+ if (INTVAL (operands[1]) > 7)
+ operands[1] = gen_rtx(CONST_INT, VOIDmode, i);
+ return \"cmpqb %1,%0\";
+ }
+ }
+ cc_status.flags &= ~CC_REVERSED;
+ if (GET_CODE (operands[0]) == CONST_INT)
+ {
+ char i = INTVAL (operands[0]);
+ if (i <= 7 && i >= -8)
+ {
+ if (INTVAL (operands[0]) > 7)
+ operands[0] = gen_rtx(CONST_INT, VOIDmode, i);
+ return \"cmpqb %0,%1\";
+ }
+ }
+ return \"cmpb %0,%1\";
+}")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "fmF")
+ (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "cmpl %0,%1")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "fmF")
+ (match_operand:SF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "cmpf %0,%1")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=&fg<")
+ (match_operand:DF 1 "general_operand" "fFg"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"movl %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"movd %1,tos\", xoperands);
+ output_asm_insn (\"movd %1,tos\", operands);
+ return \"movl tos,%0\";
+ }
+ return \"movl %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"movd tos,%0\";
+ }
+ else
+ return \"movl %1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=fg<")
+ (match_operand:SF 1 "general_operand" "fFg"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
+ return \"movd %1,tos\;movf tos,%0\";
+ else
+ return \"movf %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ return \"movf %1,tos\;movd tos,%0\";
+ return \"movf %1,%0\";
+ }
+#ifndef GAS_SYNTAX
+ /* GAS understands floating constants in ordinary movd instructions
+ * but other assembers might object.
+ */
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ union {int i[2]; float f; double d;} convrt;
+ convrt.i[0] = CONST_DOUBLE_LOW (operands[1]);
+ convrt.i[1] = CONST_DOUBLE_HIGH (operands[1]);
+ convrt.f = convrt.d;
+
+ /* Is there a better machine-independent way to to this? */
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, convrt.i[0]);
+ return \"movd %1,%0\";
+ }
+#endif
+ else return \"movd %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:TI 0 "memory_operand" "=m")
+ (match_operand:TI 1 "memory_operand" "m"))]
+ ""
+ "movmd %1,%0,4")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=&g<,*f,g")
+ (match_operand:DI 1 "general_operand" "gF,g,*f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"movl %1,%0\";
+ if (REG_P (operands[1]))
+ {
+ rtx xoperands[2];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"movd %1,tos\", xoperands);
+ output_asm_insn (\"movd %1,tos\", operands);
+ return \"movl tos,%0\";
+ }
+ return \"movl %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ {
+ output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"movd tos,%0\";
+ }
+ else
+ return \"movl %1,%0\";
+ }
+ return output_move_double (operands);
+}")
+
+;; This special case must precede movsi.
+(define_insn ""
+ [(set (reg:SI 17)
+ (match_operand:SI 0 "general_operand" "rmn"))]
+ ""
+ "lprd sp,%0")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g<,*f,g")
+ (match_operand:SI 1 "general_operand" "gx,g,*f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
+ return \"movd %1,tos\;movf tos,%0\";
+ else
+ return \"movf %1,%0\";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (REG_P (operands[0]))
+ return \"movf %1,tos\;movd tos,%0\";
+ return \"movf %1,%0\";
+ }
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int i = INTVAL (operands[1]);
+ if (i <= 7 && i >= -8)
+ return \"movqd %1,%0\";
+ if (i < 0x4000 && i >= -0x4000)
+#ifdef GNX_V3
+ return \"addr %c1,%0\";
+#else
+ return \"addr @%c1,%0\";
+#endif
+ return \"movd %1,%0\";
+ }
+ else if (GET_CODE (operands[1]) == REG)
+ {
+ if (REGNO (operands[1]) < 16)
+ return \"movd %1,%0\";
+ else if (REGNO (operands[1]) == FRAME_POINTER_REGNUM)
+ {
+ if (GET_CODE(operands[0]) == REG)
+ return \"sprd fp,%0\";
+ else
+ return \"addr 0(fp),%0\" ;
+ }
+ else if (REGNO (operands[1]) == STACK_POINTER_REGNUM)
+ {
+ if (GET_CODE(operands[0]) == REG)
+ return \"sprd sp,%0\";
+ else
+ return \"addr 0(sp),%0\" ;
+ }
+ else abort (0);
+ }
+ else if (GET_CODE (operands[1]) == MEM)
+ return \"movd %1,%0\";
+ /* Check if this effective address can be
+ calculated faster by pulling it apart. */
+ if (REG_P (operands[0])
+ && GET_CODE (operands[1]) == MULT
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
+ && (INTVAL (XEXP (operands[1], 1)) == 2
+ || INTVAL (XEXP (operands[1], 1)) == 4))
+ {
+ rtx xoperands[3];
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (operands[1], 0);
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (XEXP (operands[1], 1)) >> 1);
+ return output_shift_insn (xoperands);
+ }
+ return \"addr %a1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ short i = INTVAL (operands[1]);
+ if (i <= 7 && i >= -8)
+ {
+ if (INTVAL (operands[1]) > 7)
+ operands[1] =
+ gen_rtx (CONST_INT, VOIDmode, i);
+ return \"movqw %1,%0\";
+ }
+ }
+ return \"movw %1,%0\";
+}")
+
+(define_insn "movstricthi"
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "+r"))
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL(operands[1]) <= 7 && INTVAL(operands[1]) >= -8)
+ return \"movqw %1,%0\";
+ return \"movw %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ char char_val = (char)INTVAL (operands[1]);
+ if (char_val <= 7 && char_val >= -8)
+ {
+ if (INTVAL (operands[1]) > 7)
+ operands[1] =
+ gen_rtx (CONST_INT, VOIDmode, char_val);
+ return \"movqb %1,%0\";
+ }
+ }
+ return \"movb %1,%0\";
+}")
+
+(define_insn "movstrictqi"
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "+r"))
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL(operands[1]) < 8 && INTVAL(operands[1]) > -9)
+ return \"movqb %1,%0\";
+ return \"movb %1,%0\";
+}")
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+(define_insn "movstrsi"
+ [(set (match_operand:BLK 0 "general_operand" "=g")
+ (match_operand:BLK 1 "general_operand" "g"))
+ (use (match_operand:SI 2 "general_operand" "rmn"))
+ (clobber (reg:SI 0))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ abort ();
+ operands[0] = XEXP (operands[0], 0);
+ operands[1] = XEXP (operands[1], 0);
+ if (GET_CODE (operands[0]) == MEM)
+ if (GET_CODE (operands[1]) == MEM)
+ output_asm_insn (\"movd %0,r2\;movd %1,r1\", operands);
+ else
+ output_asm_insn (\"movd %0,r2\;addr %a1,r1\", operands);
+ else if (GET_CODE (operands[1]) == MEM)
+ output_asm_insn (\"addr %a0,r2\;movd %1,r1\", operands);
+ else
+ output_asm_insn (\"addr %a0,r2\;addr %a1,r1\", operands);
+
+ if (GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) & 0x3) == 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) >> 2);
+ if ((unsigned) INTVAL (operands[2]) <= 7)
+ return \"movqd %2,r0\;movsd\";
+ else
+ return \"movd %2,r0\;movsd\";
+ }
+ else
+ {
+ return \"movd %2,r0\;movsb\";
+ }
+}")
+
+;; Extension and truncation insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (truncate:QI (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "movb %1,%0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (truncate:HI (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "movw %1,%0")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (truncate:QI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "movb %1,%0")
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "movxwd %1,%0")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movxbw %1,%0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (sign_extend:SI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movxbd %1,%0")
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm<")
+ (float_extend:DF (match_operand:SF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "movfl %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "movlf %1,%0")
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "movzwd %1,%0")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movzbw %1,%0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (zero_extend:SI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movzbd %1,%0")
+
+;; Fix-to-float conversion insns.
+;; Note that the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+;; Rumor has it that the National part does not correctly convert
+;; constant ints to floats. This conversion is therefore disabled.
+;; A register must be used to perform the conversion.
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (float:SF (match_operand:SI 1 "general_operand" "rm")))]
+ "TARGET_32081"
+ "movdf %1,%0")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm<")
+ (float:DF (match_operand:SI 1 "general_operand" "rm")))]
+ "TARGET_32081"
+ "movdl %1,%0")
+
+(define_insn "floathisf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (float:SF (match_operand:HI 1 "general_operand" "rm")))]
+ "TARGET_32081"
+ "movwf %1,%0")
+
+(define_insn "floathidf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm<")
+ (float:DF (match_operand:HI 1 "general_operand" "rm")))]
+ "TARGET_32081"
+ "movwl %1,%0")
+
+(define_insn "floatqisf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (float:SF (match_operand:QI 1 "general_operand" "rm")))]
+ "TARGET_32081"
+ "movbf %1,%0")
+
+; Some assemblers warn that this insn doesn't work.
+; Maybe they know something we don't.
+;(define_insn "floatqidf2"
+; [(set (match_operand:DF 0 "general_operand" "=fm<")
+; (float:DF (match_operand:QI 1 "general_operand" "rm")))]
+; "TARGET_32081"
+; "movbl %1,%0")
+
+;; Float-to-fix conversion insns.
+;; The sequent compiler always generates "trunc" insns.
+
+(define_insn "fixsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfb %1,%0")
+
+(define_insn "fixsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfw %1,%0")
+
+(define_insn "fixsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfd %1,%0")
+
+(define_insn "fixdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "trunclb %1,%0")
+
+(define_insn "fixdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "trunclw %1,%0")
+
+(define_insn "fixdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncld %1,%0")
+
+;; Unsigned
+
+(define_insn "fixunssfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (unsigned_fix:QI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfb %1,%0")
+
+(define_insn "fixunssfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (unsigned_fix:HI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfw %1,%0")
+
+(define_insn "fixunssfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (unsigned_fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncfd %1,%0")
+
+(define_insn "fixunsdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (unsigned_fix:QI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "trunclb %1,%0")
+
+(define_insn "fixunsdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (unsigned_fix:HI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "trunclw %1,%0")
+
+(define_insn "fixunsdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (unsigned_fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ "TARGET_32081"
+ "truncld %1,%0")
+
+;;; These are not yet used by GCC
+(define_insn "fix_truncsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (fix:QI (match_operand:SF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "truncfb %1,%0")
+
+(define_insn "fix_truncsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (fix:HI (match_operand:SF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "truncfw %1,%0")
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (fix:SI (match_operand:SF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "truncfd %1,%0")
+
+(define_insn "fix_truncdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (fix:QI (match_operand:DF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "trunclb %1,%0")
+
+(define_insn "fix_truncdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (fix:HI (match_operand:DF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "trunclw %1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (fix:SI (match_operand:DF 1 "general_operand" "fm")))]
+ "TARGET_32081"
+ "truncld %1,%0")
+
+;;- All kinds of add instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "general_operand" "=fm")
+ (plus:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "addl %2,%0")
+
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "general_operand" "=fm")
+ (plus:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "addf %2,%0")
+
+(define_insn ""
+ [(set (reg:SI 17)
+ (plus:SI (reg:SI 17)
+ (match_operand:SI 0 "immediate_operand" "i")))]
+ "GET_CODE (operands[0]) == CONST_INT"
+ "*
+{
+#ifndef SEQUENT_ADJUST_STACK
+ if (INTVAL (operands[0]) == 8)
+ return \"cmpd tos,tos\";
+ if (INTVAL (operands[0]) == 4)
+ return \"cmpqd %$0,tos\";
+#endif
+ if (INTVAL (operands[0]) < 64 && INTVAL (operands[0]) > -64)
+ return \"adjspb %$%n0\";
+ else if (INTVAL (operands[0]) < 8192 && INTVAL (operands[0]) >= -8192)
+ return \"adjspw %$%n0\";
+ return \"adjspd %$%n0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (plus:SI (reg:SI 16)
+ (match_operand:SI 1 "immediate_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "addr %c1(fp),%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (plus:SI (reg:SI 17)
+ (match_operand:SI 1 "immediate_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "addr %c1(sp),%0")
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g,=g<")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,%r")
+ (match_operand:SI 2 "general_operand" "rmn,n")))]
+ ""
+ "*
+{
+ if (which_alternative == 1)
+ {
+ int i = INTVAL (operands[2]);
+ if ( i < 0x40000000 && i >= -0x40000000 )
+ return \"addr %c2(%1),%0\";
+ else
+ return \"movd %1,%0\;addd %2,%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+
+ if (i <= 7 && i >= -8)
+ return \"addqd %2,%0\";
+ else if (GET_CODE (operands[0]) == REG
+ && i < 0x4000 && i >= -0x4000)
+ return \"addr %c2(%0),%0\";
+ }
+ return \"addd %2,%0\";
+}")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (plus:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+ if (i <= 7 && i >= -8)
+ return \"addqw %2,%0\";
+ }
+ return \"addw %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "=r"))
+ (plus:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8)
+ return \"addqw %1,%0\";
+ return \"addw %1,%0\";
+}")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+ if (i <= 7 && i >= -8)
+ return \"addqb %2,%0\";
+ }
+ return \"addb %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "=r"))
+ (plus:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8)
+ return \"addqb %1,%0\";
+ return \"addb %1,%0\";
+}")
+
+;;- All kinds of subtract instructions.
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "general_operand" "=fm")
+ (minus:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "subl %2,%0")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "general_operand" "=fm")
+ (minus:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "subf %2,%0")
+
+(define_insn ""
+ [(set (reg:SI 17)
+ (minus:SI (reg:SI 17)
+ (match_operand:SI 0 "immediate_operand" "i")))]
+ "GET_CODE (operands[0]) == CONST_INT"
+ "*
+{
+ if (GET_CODE(operands[0]) == CONST_INT && INTVAL(operands[0]) < 64
+ && INTVAL(operands[0]) > -64)
+ return \"adjspb %0\";
+ return \"adjspd %0\";
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+
+ if (i <= 8 && i >= -7)
+ return \"addqd %$%n2,%0\";
+ }
+ return \"subd %2,%0\";
+}")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (minus:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+
+ if (i <= 8 && i >= -7)
+ return \"addqw %$%n2,%0\";
+ }
+ return \"subw %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:HI 0 "general_operand" "=r"))
+ (minus:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9)
+ return \"addqw %$%n1,%0\";
+ return \"subw %1,%0\";
+}")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (minus:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+
+ if (i <= 8 && i >= -7)
+ return \"addqb %$%n2,%0\";
+ }
+ return \"subb %2,%0\";
+}")
+
+(define_insn ""
+ [(set (strict_low_part (match_operand:QI 0 "general_operand" "=r"))
+ (minus:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9)
+ return \"addqb %$%n1,%0\";
+ return \"subb %1,%0\";
+}")
+
+;;- Multiply instructions.
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "general_operand" "=fm")
+ (mult:DF (match_operand:DF 1 "general_operand" "%0")
+ (match_operand:DF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "mull %2,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "general_operand" "=fm")
+ (mult:SF (match_operand:SF 1 "general_operand" "%0")
+ (match_operand:SF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "mulf %2,%0")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "muld %2,%0")
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (mult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "mulw %2,%0")
+
+(define_insn "mulqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (mult:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "mulb %2,%0")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (umult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "muld %2,%0")
+
+(define_insn "umulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (umult:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "mulw %2,%0")
+
+(define_insn "umulqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (umult:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "mulb %2,%0")
+
+(define_insn "umulsidi3"
+ [(set (match_operand:DI 0 "general_operand" "=g")
+ (umult:DI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "meid %2,%0")
+
+;;- Divide instructions.
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "general_operand" "=fm")
+ (div:DF (match_operand:DF 1 "general_operand" "0")
+ (match_operand:DF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "divl %2,%0")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "general_operand" "=fm")
+ (div:SF (match_operand:SF 1 "general_operand" "0")
+ (match_operand:SF 2 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "divf %2,%0")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (div:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "quod %2,%0")
+
+(define_insn "divhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (div:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "quow %2,%0")
+
+(define_insn "divqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (div:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "quob %2,%0")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (subreg:SI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"deid %2,%0\;movd %1,%0\";
+}")
+
+(define_insn "udivhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (udiv:HI (subreg:HI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ operands[1] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
+ return \"deiw %2,%0\;movw %1,%0\";
+}")
+
+(define_insn "udivqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (udiv:QI (subreg:QI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ operands[1] = gen_rtx (REG, QImode, REGNO (operands[0]) + 1);
+ return \"deib %2,%0\;movb %1,%0\";
+}")
+
+;; Remainder instructions.
+
+(define_insn "modsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (mod:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "remd %2,%0")
+
+(define_insn "modhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (mod:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "remw %2,%0")
+
+(define_insn "modqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (mod:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "remb %2,%0")
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (subreg:SI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "deid %2,%0")
+
+(define_insn "umodhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (umod:HI (subreg:HI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "deiw %2,%0")
+
+(define_insn "umodqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (umod:QI (subreg:QI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "deib %2,%0")
+
+; This isn't be usable in its current form.
+;(define_insn "udivmoddisi4"
+; [(set (subreg:SI (match_operand:DI 0 "general_operand" "=r") 1)
+; (udiv:SI (match_operand:DI 1 "general_operand" "0")
+; (match_operand:SI 2 "general_operand" "rmn")))
+; (set (subreg:SI (match_dup 0) 0)
+; (umod:SI (match_dup 1) (match_dup 2)))]
+; ""
+; "deid %2,%0")
+
+;;- Logical Instructions: AND
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((INTVAL (operands[2]) | 0xff) == 0xffffffff)
+ {
+ if (INTVAL (operands[2]) == 0xffffff00)
+ return \"movqb %$0,%0\";
+ else
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xff);
+ return \"andb %2,%0\";
+ }
+ }
+ if ((INTVAL (operands[2]) | 0xffff) == 0xffffffff)
+ {
+ if (INTVAL (operands[2]) == 0xffff0000)
+ return \"movqw %$0,%0\";
+ else
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff);
+ return \"andw %2,%0\";
+ }
+ }
+ }
+ return \"andd %2,%0\";
+}")
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) | 0xff) == 0xffffffff)
+ {
+ if (INTVAL (operands[2]) == 0xffffff00)
+ return \"movqb %$0,%0\";
+ else
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xff);
+ return \"andb %2,%0\";
+ }
+ }
+ return \"andw %2,%0\";
+}")
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "andb %2,%0")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "0")
+ (not:SI (match_operand:SI 2 "general_operand" "rmn"))))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((INTVAL (operands[2]) & 0xffffff00) == 0)
+ return \"bicb %2,%0\";
+ if ((INTVAL (operands[2]) & 0xffff0000) == 0)
+ return \"bicw %2,%0\";
+ }
+ return \"bicd %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (not:SI (match_operand:SI 1 "general_operand" "rmn"))
+ (match_operand:SI 2 "general_operand" "0")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if ((INTVAL (operands[1]) & 0xffffff00) == 0)
+ return \"bicb %1,%0\";
+ if ((INTVAL (operands[1]) & 0xffff0000) == 0)
+ return \"bicw %1,%0\";
+ }
+ return \"bicd %1,%0\";
+}")
+
+(define_insn "andcbhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "0")
+ (not:HI (match_operand:HI 2 "general_operand" "g"))))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) & 0xffffff00) == 0)
+ return \"bicb %2,%0\";
+ return \"bicw %2,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (not:HI (match_operand:HI 1 "general_operand" "g"))
+ (match_operand:HI 2 "general_operand" "0")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & 0xffffff00) == 0)
+ return \"bicb %1,%0\";
+ return \"bicw %1,%0\";
+}")
+
+(define_insn "andcbqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "0")
+ (not:QI (match_operand:QI 2 "general_operand" "g"))))]
+ ""
+ "bicb %2,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (not:QI (match_operand:QI 1 "general_operand" "g"))
+ (match_operand:QI 2 "general_operand" "0")))]
+ ""
+ "bicb %1,%0")
+
+;;- Bit set instructions.
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT) {
+ if ((INTVAL (operands[2]) & 0xffffff00) == 0)
+ return \"orb %2,%0\";
+ if ((INTVAL (operands[2]) & 0xffff0000) == 0)
+ return \"orw %2,%0\";
+ }
+ return \"ord %2,%0\";
+}")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (ior:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE(operands[2]) == CONST_INT &&
+ (INTVAL(operands[2]) & 0xffffff00) == 0)
+ return \"orb %2,%0\";
+ return \"orw %2,%0\";
+}")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "orb %2,%0")
+
+;;- xor instructions.
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT) {
+ if ((INTVAL (operands[2]) & 0xffffff00) == 0)
+ return \"xorb %2,%0\";
+ if ((INTVAL (operands[2]) & 0xffff0000) == 0)
+ return \"xorw %2,%0\";
+ }
+ return \"xord %2,%0\";
+}")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (GET_CODE(operands[2]) == CONST_INT &&
+ (INTVAL(operands[2]) & 0xffffff00) == 0)
+ return \"xorb %2,%0\";
+ return \"xorw %2,%0\";
+}")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (xor:QI (match_operand:QI 1 "general_operand" "%0")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "xorb %2,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm<")
+ (neg:DF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "negl %1,%0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (neg:SF (match_operand:SF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "negf %1,%0")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (neg:SI (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "negd %1,%0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (neg:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "negw %1,%0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (neg:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "negb %1,%0")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (not:SI (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "comd %1,%0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (not:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "comw %1,%0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (not:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "comb %1,%0")
+
+;; arithmetic left and right shift operations
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g,g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "r,0")
+ (match_operand:SI 2 "general_operand" "I,rmn")))]
+ ""
+ "* return output_shift_insn (operands);")
+
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (ashift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ if (INTVAL (operands[2]) == 1)
+ return \"addw %0,%0\";
+ else if (INTVAL (operands[2]) == 2)
+ return \"addw %0,%0\;addw %0,%0\";
+ return \"ashw %2,%0\";
+}")
+
+(define_insn "ashlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ashift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ if (INTVAL (operands[2]) == 1)
+ return \"addb %1,%0\";
+ else if (INTVAL (operands[2]) == 2)
+ return \"addb %1,%0\;addb %0,%0\";
+ return \"ashb %2,%0\";
+}")
+
+;; Arithmetic right shift on the 32k works by negating the shift count.
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "ashrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (ashift:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "ashrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ashift:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+;; logical shift instructions
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (lshift:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "lshd %2,%0")
+
+(define_insn "lshlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (lshift:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "lshw %2,%0")
+
+(define_insn "lshlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (lshift:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "lshb %2,%0")
+
+;; Logical right shift on the 32k works by negating the shift count.
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (lshift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "lshrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (lshift:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "lshrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (lshift:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+;; Rotate instructions
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (rotate:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "rotd %2,%0")
+
+(define_insn "rotlhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (rotate:HI (match_operand:HI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "rotw %2,%0")
+
+(define_insn "rotlqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (rotate:QI (match_operand:QI 1 "general_operand" "0")
+ (match_operand:SI 2 "general_operand" "rmn")))]
+ ""
+ "rotb %2,%0")
+
+;; Right rotate on the 32k works by negating the shift count.
+(define_expand "rotrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (rotate:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "rotrhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (rotate:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+(define_expand "rotrqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (rotate:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (SImode, operands[2]);
+}")
+
+;;- load or push effective address
+;; These come after the move, add, and multiply patterns
+;; because we don't want pushl $1 turned into pushad 1.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (REG_P (operands[0])
+ && GET_CODE (operands[1]) == MULT
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
+ && (INTVAL (XEXP (operands[1], 1)) == 2
+ || INTVAL (XEXP (operands[1], 1)) == 4))
+ {
+ rtx xoperands[3];
+ xoperands[0] = operands[0];
+ xoperands[1] = XEXP (operands[1], 0);
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (XEXP (operands[1], 1)) >> 1);
+ return output_shift_insn (xoperands);
+ }
+ return \"addr %a1,%0\";
+}")
+
+;;; Index insns. These are about the same speed as multiply-add counterparts.
+;;; but slower then using power-of-2 shifts if we can use them
+;
+;(define_insn ""
+; [(set (match_operand:SI 0 "register_operand" "=r")
+; (plus:SI (match_operand:SI 1 "general_operand" "rmn")
+; (mult:SI (match_operand:SI 2 "register_operand" "0")
+; (plus:SI (match_operand:SI 3 "general_operand" "rmn") (const_int 1)))))]
+; "GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) > 8"
+; "indexd %0,%3,%1")
+;
+;(define_insn ""
+; [(set (match_operand:SI 0 "register_operand" "=r")
+; (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
+; (plus:SI (match_operand:SI 2 "general_operand" "rmn") (const_int 1)))
+; (match_operand:SI 3 "general_operand" "rmn")))]
+; "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 8"
+; "indexd %0,%2,%3")
+
+;; Set, Clear, and Invert bit
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ior:SI
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn"))
+ (match_dup 0)))]
+ ""
+ "sbitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ior:SI
+ (match_dup 0)
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn"))))]
+ ""
+ "sbitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ior:QI
+ (subreg:QI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn")) 0)
+ (match_dup 0)))]
+ ""
+ "sbitb %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ior:QI
+ (match_dup 0)
+ (subreg:QI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn")) 0)))]
+ ""
+ "sbitb %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI
+ (not:SI
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn")))
+ (match_dup 0)))]
+ ""
+ "cbitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI
+ (match_dup 0)
+ (not:SI
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn")))))]
+ ""
+ "cbitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI
+ (subreg:QI
+ (not:SI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn"))) 0)
+ (match_dup 0)))]
+ ""
+ "cbitb %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI
+ (match_dup 0)
+ (subreg:QI
+ (not:SI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn"))) 0)))]
+ ""
+ "cbitb %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (xor:SI
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn"))
+ (match_dup 0)))]
+ ""
+ "ibitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (xor:SI
+ (match_dup 0)
+ (ashift:SI (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn"))))]
+ ""
+ "ibitd %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (xor:QI
+ (subreg:QI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn")) 0)
+ (match_dup 0)))]
+ ""
+ "ibitb %1,%0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (xor:QI
+ (match_dup 0)
+ (subreg:QI
+ (ashift:SI (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn")) 0)))]
+ ""
+ "ibitb %1,%0")
+
+;; Recognize jbs and jbc instructions.
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract (match_operand:SI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_F;
+ return \"tbitd %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (zero_extract (match_operand:SI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "rmn"))
+ (const_int 1)))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_NOT_F;
+ return \"tbitd %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract (match_operand:HI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_F;
+ return \"tbitw %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (zero_extract (match_operand:HI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:HI 1 "general_operand" "g"))
+ (const_int 1)))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_NOT_F;
+ return \"tbitw %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extract (match_operand:QI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_F;
+ return \"tbitb %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (zero_extract:SI (match_operand:QI 0 "general_operand" "rm")
+ (const_int 1)
+ (match_operand:QI 1 "general_operand" "rmn"))
+ (const_int 1)))]
+ ""
+ "*
+{ cc_status.flags = CC_Z_IN_NOT_F;
+ return \"tbitb %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "general_operand" "rm")
+ (match_operand:SI 1 "immediate_operand" "i")))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && exact_log2 (INTVAL (operands[1])) >= 0"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ cc_status.flags = CC_Z_IN_F;
+ return \"tbitd %1,%0\";
+}")
+
+;; extract(base, width, offset)
+;; Signed bitfield extraction is not supported in hardware on the
+;; NS 32032. It is therefore better to let GCC figure out a
+;; good strategy for generating the proper instruction sequence
+;; and represent it as rtl.
+
+;; Optimize the case of extracting a byte or word from a register.
+;; Otherwise we must load a register with the offset of the
+;; chunk we want, and perform an extract insn (each of which
+;; is very expensive). Since we use the stack to do our bit-twiddling
+;; we cannot use it for a destination. Perhaps things are fast
+;; enough on the 32532 that such hacks are not needed.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=ro")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int" "i")
+ (match_operand:SI 3 "const_int" "i")))]
+ "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && (INTVAL (operands[3]) == 8 || INTVAL (operands[3]) == 16 || INTVAL (operands[3]) == 24)"
+ "*
+{
+ output_asm_insn (\"movd %1,tos\", operands);
+ if (INTVAL (operands[2]) == 16)
+ {
+ if (INTVAL (operands[3]) == 8)
+ output_asm_insn (\"movzwd 1(sp),%0\", operands);
+ else
+ output_asm_insn (\"movzwd 2(sp),%0\", operands);
+ }
+ else
+ {
+ if (INTVAL (operands[3]) == 8)
+ output_asm_insn (\"movzbd 1(sp),%0\", operands);
+ else if (INTVAL (operands[3]) == 16)
+ output_asm_insn (\"movzbd 2(sp),%0\", operands);
+ else
+ output_asm_insn (\"movzbd 3(sp),%0\", operands);
+ }
+ return \"cmpqd %$0,tos\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=ro")
+ (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int" "i")
+ (match_operand:SI 3 "const_int" "i")))]
+ "INTVAL (operands[2]) == 8 && INTVAL (operands[3]) == 8"
+ "movw %1,tos\;movzbd 1(sp),%0\;adjspb %$-2")
+
+(define_insn "extzv"
+ [(set (match_operand:SI 0 "general_operand" "=g<,g<")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "rm,o")
+ (match_operand:SI 2 "const_int" "i,i")
+ (match_operand:SI 3 "general_operand" "rK,n")))]
+ ""
+ "*
+{ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ if (INTVAL (operands[3]) >= 8)
+ operands[1] = adj_offsettable_operand (operands[1],
+ INTVAL (operands[3]) >> 3);
+ return \"extsd %1,%0,%3,%2\";
+ }
+ else return \"extd %3,%1,%0,%2\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g<,g<")
+ (zero_extract:SI (match_operand:HI 1 "general_operand" "rm,o")
+ (match_operand:SI 2 "const_int" "i,i")
+ (match_operand:SI 3 "general_operand" "rK,n")))]
+ ""
+ "*
+{ if (GET_CODE (operands[3]) == CONST_INT)
+ {
+ if (INTVAL (operands[3]) >= 8)
+ operands[1] = adj_offsettable_operand (operands[1],
+ INTVAL (operands[3]) >> 3);
+ return \"extsd %1,%0,%3,%2\";
+ }
+ else return \"extd %3,%1,%0,%2\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (zero_extract:SI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:SI 2 "const_int" "i")
+ (match_operand:SI 3 "general_operand" "rn")))]
+ ""
+ "*
+{ if (GET_CODE (operands[3]) == CONST_INT)
+ return \"extsd %1,%0,%3,%2\";
+ else return \"extd %3,%1,%0,%2\";
+}")
+
+(define_insn "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+g,o")
+ (match_operand:SI 1 "const_int" "i,i")
+ (match_operand:SI 2 "general_operand" "rK,n"))
+ (match_operand:SI 3 "general_operand" "rm,rm"))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) >= 8)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[2]) / 8);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 8);
+ }
+ if (INTVAL (operands[1]) <= 8)
+ return \"inssb %3,%0,%2,%1\";
+ else if (INTVAL (operands[1]) <= 16)
+ return \"inssw %3,%0,%2,%1\";
+ else
+ return \"inssd %3,%0,%2,%1\";
+ }
+ return \"insd %2,%3,%0,%1\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:HI 0 "general_operand" "+g,o")
+ (match_operand:SI 1 "const_int" "i,i")
+ (match_operand:SI 2 "general_operand" "rK,n"))
+ (match_operand:SI 3 "general_operand" "rm,rm"))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) >= 8)
+ {
+ operands[0] = adj_offsettable_operand (operands[0],
+ INTVAL (operands[2]) / 8);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 8);
+ }
+ if (INTVAL (operands[1]) <= 8)
+ return \"inssb %3,%0,%2,%1\";
+ else if (INTVAL (operands[1]) <= 16)
+ return \"inssw %3,%0,%2,%1\";
+ else
+ return \"inssd %3,%0,%2,%1\";
+ }
+ return \"insd %2,%3,%0,%1\";
+}")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "general_operand" "=g")
+ (match_operand:SI 1 "const_int" "i")
+ (match_operand:SI 2 "general_operand" "rn"))
+ (match_operand:SI 3 "general_operand" "rm"))]
+ ""
+ "*
+{ if (GET_CODE (operands[2]) == CONST_INT)
+ if (INTVAL (operands[1]) <= 8)
+ return \"inssb %3,%0,%2,%1\";
+ else if (INTVAL (operands[1]) <= 16)
+ return \"inssw %3,%0,%2,%1\";
+ else
+ return \"inssd %3,%0,%2,%1\";
+ return \"insd %2,%3,%0,%1\";
+}")
+
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "br %l0")
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"bfc %l0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"bfs %l0\";
+ else return \"beq %l0\";
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"bfs %l0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"bfc %l0\";
+ else return \"bne %l0\";
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bgt %l0")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bhi %l0")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "blt %l0")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "blo %l0")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bge %l0")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bhs %l0")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "ble %l0")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "bls %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"bfs %l0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"bfc %l0\";
+ else return \"bne %l0\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"bfc %l0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"bfs %l0\";
+ else return \"beq %l0\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "ble %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bls %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bge %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bhs %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "blt %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "blo %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bgt %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "bhi %l0")
+
+;; Subtract-and-jump and Add-and-jump insns.
+;; These can actually be used for adding numbers in the range -8 to 7
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (minus:SI (match_operand:SI 0 "general_operand" "+g")
+ (match_operand:SI 1 "general_operand" "i"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (minus:SI (match_dup 0)
+ (match_dup 1)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) > -8 && INTVAL (operands[1]) <= 8"
+ "acbd %$%n1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (match_operand:SI 1 "general_operand" "i"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 8"
+ "acbd %1,%0,%l2")
+
+;; Reversed
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (minus:SI (match_operand:SI 0 "general_operand" "+g")
+ (match_operand:SI 1 "general_operand" "i"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))
+ (set (match_dup 0)
+ (minus:SI (match_dup 0)
+ (match_dup 1)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) > -8 && INTVAL (operands[1]) <= 8"
+ "acbd %$%n1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (match_operand:SI 1 "general_operand" "i"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_dup 1)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= -8 && INTVAL (operands[1]) < 8"
+ "acbd %1,%0,%l2")
+
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+#ifndef JSR_ALWAYS
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ rtx temp = XEXP (operands[0], 0);
+ if (CONSTANT_ADDRESS_P (temp))
+ {
+#ifdef GAS_SYNTAX
+ operands[0] = temp;
+ return \"bsr %0\";
+#else
+#ifdef GNX_V3
+ return \"bsr %0\";
+#else
+ return \"bsr %?%a0\";
+#endif
+#endif
+ }
+ if (GET_CODE (XEXP (operands[0], 0)) == REG)
+#if defined(GNX_V3) || defined(GAS_SYNTAX)
+ return \"jsr %0\";
+#else
+ return \"jsr %a0\";
+#endif
+ }
+#endif /* not JSR_ALWAYS */
+ return \"jsr %0\";
+}")
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=fg")
+ (call (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+#ifndef JSR_ALWAYS
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ rtx temp = XEXP (operands[0], 0);
+ if (CONSTANT_ADDRESS_P (temp))
+ {
+#ifdef GAS_SYNTAX
+ operands[0] = temp;
+ return \"bsr %1\";
+#else
+#ifdef GNX_V3
+ return \"bsr %1\";
+#else
+ return \"bsr %?%a1\";
+#endif
+#endif
+ }
+ if (GET_CODE (XEXP (operands[0], 0)) == REG)
+#if defined(GNX_V3) || defined(GAS_SYNTAX)
+ return \"jsr %1\";
+#else
+ return \"jsr %a1\";
+#endif
+ }
+#endif /* not JSR_ALWAYS */
+ return \"jsr %1\";
+}")
+
+(define_insn "return"
+ [(return)]
+ "0"
+ "ret 0")
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "general_operand" "=fm<")
+ (abs:SF (match_operand:SF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "absf %1,%0")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "general_operand" "=fm<")
+ (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
+ "TARGET_32081"
+ "absl %1,%0")
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (abs:SI (match_operand:SI 1 "general_operand" "rmn")))]
+ ""
+ "absd %1,%0")
+
+(define_insn "abshi2"
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (abs:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "absw %1,%0")
+
+(define_insn "absqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (abs:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "absb %1,%0")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;;(define_insn "tablejump"
+;; [(set (pc)
+;; (plus:SI (match_operand:SI 0 "general_operand" "g")
+;; (pc)))]
+;; ""
+;; "cased %0")
+
+(define_insn "tablejump"
+ [(set (pc)
+ (plus:SI (pc) (match_operand:HI 0 "general_operand" "g")))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "*
+{
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
+ CODE_LABEL_NUMBER (operands[1]));
+ return \"casew %0\";
+}")
+
+;;(define_insn ""
+;; [(set (pc)
+;; (plus:SI (match_operand:QI 0 "general_operand" "g")
+;; (pc)))]
+;; ""
+;; "caseb %0")
+
+;; Scondi instructions
+(define_insn "seq"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfcd %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfsd %0\";
+ else return \"seqd %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfcw %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfsw %0\";
+ else return \"seqw %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfcb %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfsb %0\";
+ else return \"seqb %0\";
+}")
+
+(define_insn "sne"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfsd %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfcd %0\";
+ else return \"sned %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfsw %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfcw %0\";
+ else return \"snew %0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "*
+{ if (cc_prev_status.flags & CC_Z_IN_F)
+ return \"sfsb %0\";
+ else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
+ return \"sfcb %0\";
+ else return \"sneb %0\";
+}")
+
+(define_insn "sgt"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "sgtd %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "sgtw %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (gt (cc0) (const_int 0)))]
+ ""
+ "sgtb %0")
+
+(define_insn "sgtu"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "shid %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "shiw %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (gtu (cc0) (const_int 0)))]
+ ""
+ "shib %0")
+
+(define_insn "slt"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "sltd %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "sltw %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (lt (cc0) (const_int 0)))]
+ ""
+ "sltb %0")
+
+(define_insn "sltu"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "slod %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "slow %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (ltu (cc0) (const_int 0)))]
+ ""
+ "slob %0")
+
+(define_insn "sge"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "sged %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "sgew %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (ge (cc0) (const_int 0)))]
+ ""
+ "sgeb %0")
+
+(define_insn "sgeu"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "shsd %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "shsw %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (geu (cc0) (const_int 0)))]
+ ""
+ "shsb %0")
+
+(define_insn "sle"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (le (cc0) (const_int 0)))]
+ ""
+ "sled %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (le (cc0) (const_int 0)))]
+ ""
+ "slew %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (le (cc0) (const_int 0)))]
+ ""
+ "sleb %0")
+
+(define_insn "sleu"
+ [(set (match_operand:SI 0 "general_operand" "=g<")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "slsd %0")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g<")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "slsw %0")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g<")
+ (leu (cc0) (const_int 0)))]
+ ""
+ "slsb %0")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/out-alliant.c b/gcc-1.40/config/out-alliant.c
new file mode 100644
index 0000000..63727ad
--- /dev/null
+++ b/gcc-1.40/config/out-alliant.c
@@ -0,0 +1,291 @@
+/* Subroutines for insn-output.c for Alliant FX computers.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Some output-actions in alliant.md need these. */
+#include <stdio.h>
+extern FILE *asm_out_file;
+
+/* Index into this array by (register number >> 3) to find the
+ smallest class which contains that register. */
+enum reg_class regno_reg_class[]
+ = { DATA_REGS, ADDR_REGS, FP_REGS };
+
+static rtx find_addr_reg ();
+
+char *
+output_btst (operands, countop, dataop, insn, signpos)
+ rtx *operands;
+ rtx countop, dataop;
+ rtx insn;
+ int signpos;
+{
+ operands[0] = countop;
+ operands[1] = dataop;
+
+ if (GET_CODE (countop) == CONST_INT)
+ {
+ register int count = INTVAL (countop);
+ /* If COUNT is bigger than size of storage unit in use,
+ advance to the containing unit of same size. */
+ if (count > signpos)
+ {
+ int offset = (count & ~signpos) / 8;
+ count = count & signpos;
+ operands[1] = dataop = adj_offsettable_operand (dataop, offset);
+ }
+ if (count == signpos)
+ cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
+ else
+ cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
+
+ if (count == 31
+ && next_insns_test_no_inequality (insn))
+ return "tst%.l %1";
+ if (count == 15
+ && next_insns_test_no_inequality (insn))
+ return "tst%.w %1";
+ if (count == 7
+ && next_insns_test_no_inequality (insn))
+ return "tst%.b %1";
+
+ cc_status.flags = CC_NOT_NEGATIVE;
+ }
+ return "btst %0,%1";
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (operands[1] != const0_rtx)
+ return "mov%.l %1,%0";
+ if (! ADDRESS_REG_P (operands[0]))
+ return "clr%.l %0";
+ return "sub%.l %0,%0";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ optype0 = POPOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ optype0 = PUSHOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
+ optype1 = POPOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ optype1 = PUSHOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If one operand is decrementing and one is incrementing
+ decrement the former register explicitly
+ and change that operand into ordinary indexing. */
+
+ if (optype0 == PUSHOP && optype1 == POPOP)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ output_asm_insn ("subq%.l %#8,%0", operands);
+ operands[0] = gen_rtx (MEM, DImode, operands[0]);
+ optype0 = OFFSOP;
+ }
+ if (optype0 == POPOP && optype1 == PUSHOP)
+ {
+ operands[1] = XEXP (XEXP (operands[1], 0), 0);
+ output_asm_insn ("subq%.l %#8,%1", operands);
+ operands[1] = gen_rtx (MEM, DImode, operands[1]);
+ optype1 = OFFSOP;
+ }
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If insn is effectively movd N(sp),-(sp) then we will do the
+ high word first. We should use the adjusted operand 1 (which is N+4(sp))
+ for the low word as well, to compensate for the first decrement of sp. */
+ if (optype0 == PUSHOP
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+ operands[1] = latehalf[1];
+
+ /* If one or both operands autodecrementing,
+ do the two words, high-numbered first. */
+
+ /* Likewise, the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == PUSHOP || optype1 == PUSHOP
+ || (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1])))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addql %#4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subql %#4,%0", &addreg1);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addql %#4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subql %#4,%0", &addreg1);
+
+ return "";
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+int
+standard_SunFPA_constant_p (x)
+ rtx x;
+{
+ return( 0 );
+}
+
diff --git a/gcc-1.40/config/out-convex.c b/gcc-1.40/config/out-convex.c
new file mode 100644
index 0000000..df6fb73
--- /dev/null
+++ b/gcc-1.40/config/out-convex.c
@@ -0,0 +1,219 @@
+/* Subroutines for insn-output.c for Convex.
+ Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Boolean to keep track of whether the current section is .text or not.
+ Used by .align handler in tm-convex.h. */
+
+int current_section_is_text;
+
+/*
+ * set_cmp (left_rtx, right_rtx, [bhwlsd])
+ * gen_cmp (label_rtx, cmpop, [tf])
+ *
+ * set_cmp saves the operands of a "cmp" insn,
+ * along with the type character to be used in the compare instruction.
+ *
+ * gen_cmp finds out what comparison is to be performed and
+ * outputs the necessary instructions, eg,
+ * "eq.w a1,a2 ! jbra.t L5"
+ * for (cmpsi a1 a2) (beq L5)
+ */
+
+static rtx xop0, xop1;
+static char typech, regch;
+
+char *
+set_cmp (op0, op1, typechr)
+ rtx op0, op1;
+ char typechr;
+{
+ xop0 = op0;
+ xop1 = op1;
+ typech = typechr;
+ if (GET_CODE (op0) == REG)
+ regch = REGNO_OK_FOR_BASE_P (REGNO (op0)) ? 'a' : 's';
+ else if (GET_CODE (op1) == REG)
+ regch = REGNO_OK_FOR_BASE_P (REGNO (op1)) ? 'a' : 's';
+ else abort ();
+ return "";
+}
+
+char *
+gen_cmp (label, cmpop, tf)
+ rtx label;
+ char *cmpop;
+ char tf;
+{
+ char buf[80];
+ char revop[4];
+ rtx ops[3];
+
+ ops[2] = label;
+
+ /* constant must be first; swap operands if necessary
+ if lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
+ and reverse the sense of the jump */
+
+ if (CONSTANT_P (xop1) || GET_CODE (xop1) == CONST_DOUBLE)
+ {
+ ops[0] = xop1;
+ ops[1] = xop0;
+ if (cmpop[0] == 'l')
+ {
+ bcopy (cmpop, revop, 4);
+ revop[1] ^= 'e' ^ 't';
+ tf ^= 't' ^ 'f';
+ cmpop = revop;
+ }
+ }
+ else
+ {
+ ops[0] = xop0;
+ ops[1] = xop1;
+ }
+
+ sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);
+ output_asm_insn (buf, ops);
+ return "";
+}
+
+/*
+ * Routines to look at CONST_DOUBLEs without sinful knowledge of
+ * what the inside of u.d looks like
+ *
+ * const_double_high_int -- high word of machine double or long long
+ * const_double_low_int -- low word
+ * const_double_float_int -- the word of a machine float
+ */
+
+static double frexp ();
+static void float_extract ();
+
+int
+const_double_high_int (x)
+ rtx x;
+{
+ if (GET_MODE (x) == DImode)
+ return CONST_DOUBLE_HIGH (x);
+ else
+ {
+ int sign, expd, expf;
+ unsigned fracdh, fracdl, fracf;
+ float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
+
+ if (fracdh == 0)
+ return 0;
+ if (expd < -01777 || expd > 01777)
+ return 1 << 31;
+ return sign << 31 | (expd + 02000) << 20 | fracdh - (1 << 20);
+ }
+}
+
+int
+const_double_low_int (x)
+ rtx x;
+{
+ if (GET_MODE (x) == DImode)
+ return CONST_DOUBLE_LOW (x);
+ else
+ {
+ int sign, expd, expf;
+ unsigned fracdh, fracdl, fracf;
+ float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
+ return fracdl;
+ }
+}
+
+int
+const_double_float_int (x)
+ rtx x;
+{
+ int sign, expd, expf;
+ unsigned fracdh, fracdl, fracf;
+ float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
+
+ if (fracf == 0)
+ return 0;
+ if (expf < -0177 || expf > 0177)
+ return 1 << 31;
+ return sign << 31 | (expf + 0200) << 20 | fracf - (1 << 23);
+}
+
+#define T21 ((double) (1 << 21))
+#define T24 ((double) (1 << 24))
+#define T53 ((double) (1 << 27) * (double) (1 << 26))
+
+static void
+float_extract (x, sign, expd, fracdh, fracdl, expf, fracf)
+ rtx x;
+ int *sign, *expd, *expf;
+ unsigned *fracdh, *fracdl, *fracf;
+{
+ int exp, round;
+ double d, r;
+ union real_extract u;
+
+ bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);
+
+ /* Get sign and exponent. */
+
+ if (*sign = u.d < 0)
+ u.d = -u.d;
+ d = frexp (u.d, &exp);
+
+ /* Get 21 fraction bits for high word and 32 for low word. */
+
+ for (round = 0; ; round = 1)
+ {
+ r = frexp (round ? d + 1.0 / T53 : d, expd);
+ *expd += exp;
+ *fracdh = r * T21;
+ *fracdl = (r - *fracdh / T21) * T53;
+ if (round || ((r - *fracdh / T21) - *fracdl / T53) < 0.5 * T53)
+ break;
+ }
+
+ /* Get 24 bits for float fraction. */
+
+ for (round = 0; ; round = 1)
+ {
+ r = frexp (round ? d + 1.0 / T24 : d, expf);
+ *expf += exp;
+ *fracf = r * T24;
+ if (round || (r - *fracf / T24) < 0.5 * T24)
+ break;
+ }
+}
+
+static double
+frexp (d, exp)
+ double d;
+ int *exp;
+{
+ int e = 0;
+
+ if (d > 0)
+ {
+ while (d < 0.5) d *= 2.0, e--;
+ while (d >= 1.0) d /= 2.0, e++;
+ }
+
+ *exp = e;
+ return d;
+}
diff --git a/gcc-1.40/config/out-i386.c b/gcc-1.40/config/out-i386.c
new file mode 100644
index 0000000..958d09f
--- /dev/null
+++ b/gcc-1.40/config/out-i386.c
@@ -0,0 +1,1418 @@
+/* Subroutines for insn-output.c for Intel 80386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILE
+#include <stdio.h>
+#endif
+
+#define FP_TOP (gen_rtx(REG, DFmode, FIRST_FLOAT_REG))
+
+#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx))
+#define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
+
+#define RET return ""
+
+/* #define RETCOM(X) fprintf (asm_out_file, "%sX fp_pop_level=%d\n", \
+ COMMENT_BEGIN, fp_pop_level); RET */
+#define RETCOM(X) return ""
+
+#define POP_ONE_FP \
+ { /* fp_pop_level--; */ \
+ fprintf (asm_out_file, "\tfstp %sst (0)\n", RP); }
+
+extern FILE *asm_out_file;
+static char *singlemove_string ();
+static void output_movf ();
+static void replace_float_constant ();
+static int mentions_fp_top ();
+static int call_top_dead_p ();
+static int fp_top_dead_p1 ();
+static rtx via_memory ();
+static void output_asm_insn_double_reg_op ();
+
+/* All output functions must increment or decrement this to indicate
+ the net number of pops or pushes which they perform. Note that it won't
+ necessarily balance with the optimize running, since we might have
+ two different calls with the same pop shared by cross jumping.
+ However on optimize the reg dead heuristic seems to work. */
+
+int fp_pop_level = 0;
+
+static char *hi_reg_name[] = HI_REGISTER_NAMES;
+static char *qi_reg_name[] = QI_REGISTER_NAMES;
+
+/* for fabs, fch, .. where the argument operand[1] must first be moved to
+ constraints "=fm" "0" */
+
+#define FP_CALL1(op) \
+ { if (FP_REG_P (operands[0])) \
+ return op; \
+ output_movf (FP_TOP, operands[1]); \
+ output_asm_insn (op, operands); \
+ /* fp_pop_level--; */ \
+ return "fstp%z0 %0"; }
+
+/* handle case of call where op0/op1 is "=mf" and opn is "mrf"
+ eg. fadd */
+#define FP_CALL(op, rev, n) \
+ return fp_call_internal (op, rev, n, operands, insn);
+
+static char *
+fp_call_internal (op, rev, n, operands, insn)
+ char *op;
+ char *rev;
+ int n;
+ rtx *operands;
+ rtx insn;
+{
+ if (!FP_REG_P (operands[0]))
+ {
+ /* Here destination is in memory
+ and source is in the fp stack. */
+ output_movf (FP_TOP, operands[0]);
+ output_asm_insn_double_reg_op (op, rev, insn);
+ return "fstp%z0 %0";
+ }
+
+ if (FP_REG_P (operands[n]))
+ {
+ rtx temp = operands[1];
+ char *tem1 = op;
+ operands[1] = operands[n];
+ op = rev;
+ operands[n] = temp;
+ rev = tem1;
+ }
+
+ if (REG_P (operands[n]))
+ {
+ rtx xops[2];
+ via_memory (operands[n]);
+ operands[n] = AT_SP (GET_MODE (operands[n]));
+ xops[0] = stack_pointer_rtx;
+ xops[1] = gen_rtx (CONST_INT, VOIDmode,
+ GET_MODE_SIZE (GET_MODE (operands[n])));
+ output_asm_insn (op, operands + n);
+ output_asm_insn (AS2 (add%L0,%1,%0), xops);
+ }
+ else
+ output_asm_insn (op, operands + n);
+
+ if (FP_REG_P (operands[0]))
+ {
+ /* It turns out not to work to use top_dead_p because
+ the death notes are not accurate enough.
+ But this ought to work, because the only thing that can
+ live across basic blocks is reg 8, and these insns
+ never involve reg 8 directly. */
+ if (fp_top_dead_p1 (insn))
+ POP_ONE_FP;
+ }
+
+ RET;
+}
+
+/* Output assembler code to perform insn OP
+ with two stack operands, and output on the stack.
+
+ REV is the assembler insn that does the same thing but
+ effectively interchanges the meanings of the two arguments.
+
+ Somewhat counterintuitively, the "first" operand was pushed last.
+
+ The output replaces either the top-of-stack or both of the arguments,
+ depending on whether the other argument is wanted after this insn. */
+
+static void
+output_asm_insn_double_reg_op (op, rev, insn)
+ char *op;
+ char *rev;
+ rtx insn;
+{
+ fputc ('\t', asm_out_file);
+ if (top_dead_p (insn))
+ {
+ /* Here we want the "reversed" insn, fsubr or fdivr.
+ But there is an assembler bug in all 80386 assemblers
+ which exchanges the meanings of fsubr and fsub, and of fdivr and fdiv!
+ So use the "unreversed" opcode (which will assemble into
+ the "reversed" insn). */
+ rev = op;
+
+ while (*rev && *rev != '%')
+ fputc (*rev++, asm_out_file);
+ /* fp_pop_level--; */
+
+ fprintf (asm_out_file, AS2 (p,%sst,%sst(1)), RP, RP);
+ }
+ else
+ {
+ while (*op && *op != '%')
+ fputc (*op++, asm_out_file);
+ fprintf (asm_out_file,AS2 ( ,%sst(1),%sst), RP, RP);
+ }
+ putc ('\n', asm_out_file);
+}
+
+/* Moves X to memory location 8 below stack pointer
+ and returns an RTX for that memory location.
+ X should be a register, in DFmode or SFmode. */
+
+static rtx
+via_memory (x)
+ rtx x;
+{
+ if (!REG_P (x))
+ abort ();
+ if (GET_MODE (x) == DFmode)
+ {
+ rtx xops[1];
+ xops[0] = gen_rtx (REG, SImode, REGNO (x) + 1);
+ output_asm_insn ("push%L0 %0", xops);
+ }
+ output_asm_insn ("push%L0 %0", &x);
+}
+
+/* Output an insn to copy the SFmode value in fp0 to OPERAND
+ without clobbering fp0. */
+
+void
+fp_store_sf (target)
+ rtx target;
+{
+ if (REG_P (target))
+ {
+ rtx xoperands[3];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = AT_SP (Pmode);
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, -4);
+ output_asm_insn (AS2 (add%L0,%2,%0), xoperands);
+ output_asm_insn ("fst%S0 %1", xoperands);
+ output_asm_insn ("pop%L0 %0", &target);
+ }
+ else if (GET_CODE (target) == MEM)
+ output_asm_insn ("fst%S0 %0", &target);
+}
+
+/* Output an insn to pop an SF value from fp0 into TARGET.
+ This destroys the value of fp0. */
+
+void
+fp_pop_sf (target)
+ rtx target;
+{
+ if (REG_P (target))
+ {
+ rtx xoperands[3];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = AT_SP (Pmode);
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, -4);
+ output_asm_insn (AS2 (add%L0,%2,%0), xoperands);
+ output_asm_insn ("fstp%S0 %1", xoperands);
+ output_asm_insn ("pop%L0 %0", &target);
+ /* fp_pop_level--; */
+ }
+ else if (GET_CODE (target) == MEM)
+ {
+ /* fp_pop_level--; */
+ output_asm_insn ("fstp%S0 %0", &target);
+ }
+ else abort ();
+}
+
+/* Copy the top of the fpu stack into TARGET, without popping. */
+
+void
+fp_store_df (target)
+ rtx target;
+{
+ if (REG_P (target))
+ {
+ rtx xoperands[4];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (target) + 1);
+ xoperands[2] = AT_SP (Pmode);
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, -8);
+ output_asm_insn (AS2 (add%L0,%3,%0), xoperands);
+ output_asm_insn ("fst%Q0 %2", xoperands);
+ output_asm_insn ("pop%L0 %0", &target);
+ output_asm_insn ("pop%L0 %1", xoperands);
+ }
+ else if (GET_CODE (target) == MEM)
+ output_asm_insn ("fst%Q0 %0", &target);
+}
+
+/* Copy the top of the fpu stack into TARGET, with popping. */
+
+void
+fp_pop_df (target)
+ rtx target;
+{
+ if (REG_P (target))
+ {
+ rtx xoperands[4];
+ xoperands[0] = stack_pointer_rtx;
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (target) + 1);
+ xoperands[2] = AT_SP (Pmode);
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, -8);
+ output_asm_insn (AS2 (add%L0,%3,%0), xoperands);
+ /* fp_pop_level--; */
+ output_asm_insn ("fstp%Q0 %2", xoperands);
+ output_asm_insn ("pop%L0 %0", &target);
+ output_asm_insn ("pop%L0 %1", xoperands);
+ }
+ else if (GET_CODE (target) == MEM)
+ {
+ /* fp_pop_level--; */
+ output_asm_insn ("fstp%z0 %0", &target);
+ }
+}
+
+#if 0
+/* Pop the fp stack, convert value to integer and store in TARGET.
+ TARGET may be memory or register, and may have QI, HI or SImode. */
+
+void
+fp_pop_int (target)
+ rtx target;
+{
+ if (REG_P (target) || GET_MODE (target) != SImode)
+ {
+ rtx xxops[2];
+ xxops[0] = stack_pointer_rtx;
+ xxops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
+ output_asm_insn (AS2 (sub%L0,%1,%0), xxops);
+ xxops[0] = AT_SP (Pmode);
+ /* fp_pop_level--; */
+ output_asm_insn ("fistp%L0 %0", xxops);
+ output_asm_insn ("pop%L0 %0", &target);
+ }
+ else if (GET_CODE (target) == MEM)
+ {
+ /* fp_pop_level--; */
+ output_asm_insn ("fistp%L0 %0", &target);
+ }
+ else abort ();
+}
+#endif
+
+/* Push the SFmode value X onto the fpu stack. */
+
+void
+fp_push_sf (x)
+ rtx x;
+{
+ /* fp_pop_level++; */
+ if (REG_P (x))
+ {
+ rtx xoperands[2];
+ rtx xfops[3];
+ output_asm_insn ("push%L0 %0", &x);
+ xfops[0] = AT_SP (Pmode);
+ xfops[2] = gen_rtx (CONST_INT, VOIDmode, 4);
+ xfops[1] = stack_pointer_rtx;
+ output_asm_insn ("fld%S0 %0 \n\tadd%L0 %2,%1", xfops);
+ }
+ else
+ output_asm_insn ("fld%S0 %0", &x);
+}
+
+/* Push the DFmode value X onto the fpu stack. */
+
+void
+fp_push_df (x)
+ rtx x;
+{
+ /* fp_pop_level++; */
+
+ if (REG_P (x))
+ {
+ rtx xoperands[2];
+ rtx xfops[3];
+ xoperands[0] = x;
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (x) + 1);
+ output_asm_insn ("push%L0 %1", xoperands);
+ output_asm_insn ("push%L0 %0", xoperands);
+ xfops[0] = AT_SP (Pmode);
+ xfops[2] = gen_rtx (CONST_INT, VOIDmode, 8);
+ xfops[1] = stack_pointer_rtx;
+ output_asm_insn ("fld%Q0 %0 \n\tadd%L0 %2,%1", xfops);
+ }
+ else if (GET_CODE (x) == MEM)
+ output_asm_insn ("fld%Q0 %0", &x);
+}
+
+static char *output_move_const_single ();
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ rtx x;
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ if (XEXP (x, 0) != stack_pointer_rtx)
+ abort ();
+ return "push%L0 %1";
+ }
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ return output_move_const_single (operands);
+ }
+ else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
+ return AS2 (mov%L0,%1,%0);
+ else if (CONSTANT_P (operands[1]))
+ return AS2 (mov%L0,%1,%0);
+ else
+ {
+ output_asm_insn ("push%L0 %1", operands);
+ return "pop%L0 %0";
+ }
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+/* Output an insn to add the constant N to the register X. */
+
+static void
+asm_add (n, x)
+ int n;
+ rtx x;
+{
+ rtx xops[2];
+ xops[1] = x;
+ if (n < 0)
+ {
+ xops[0] = gen_rtx (CONST_INT, VOIDmode, -n);
+ output_asm_insn (AS2 (sub%L0,%0,%1), xops);
+ }
+ else if (n > 0)
+ {
+ xops[0] = gen_rtx (CONST_INT, VOIDmode, n);
+ output_asm_insn (AS2 (add%L0,%0,%1), xops);
+ }
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ optype0 = POPOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ optype0 = PUSHOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
+ optype1 = POPOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ optype1 = PUSHOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If one operand is decrementing and one is incrementing
+ decrement the former register explicitly
+ and change that operand into ordinary indexing. */
+
+ if (optype0 == PUSHOP && optype1 == POPOP)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ asm_add (-8, operands[0]);
+ operands[0] = gen_rtx (MEM, DImode, operands[0]);
+ optype0 = OFFSOP;
+ }
+ if (optype0 == POPOP && optype1 == PUSHOP)
+ {
+ operands[1] = XEXP (XEXP (operands[1], 0), 0);
+ asm_add (-8, operands[1]);
+ operands[1] = gen_rtx (MEM, DImode, operands[1]);
+ optype1 = OFFSOP;
+ }
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If insn is effectively movd N (sp),-(sp) then we will do the
+ high word first. We should use the adjusted operand 1 (which is N+4 (sp))
+ for the low word as well, to compensate for the first decrement of sp. */
+ if (optype0 == PUSHOP
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+ operands[1] = latehalf[1];
+
+ /* If one or both operands autodecrementing,
+ do the two words, high-numbered first. */
+
+ /* Likewise, the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == PUSHOP || optype1 == PUSHOP
+ || (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1])))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ asm_add (4, addreg0);
+ if (addreg1)
+ asm_add (4, addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ asm_add (-4, addreg0);
+ if (addreg1)
+ asm_add (-4, addreg1);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ asm_add (4, addreg0);
+ if (addreg1)
+ asm_add (4, addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ asm_add (-4, addreg0);
+ if (addreg1)
+ asm_add (-4, addreg1);
+
+ return "";
+}
+
+int
+standard_80387_constant_p (x)
+ rtx x;
+{
+ union { double d; int i[2];} u;
+ register double d;
+ u.i[0] = XINT (x, 0);
+ u.i[1] = XINT (x, 1);
+ d = u.d;
+
+ if (d == 0)
+ return 1;
+ if (d == 1)
+ return 2;
+ /* Note that on the 80387, other constants, such as pi,
+ are much slower to load as standard constants
+ than to load from doubles in memory! */
+
+ return 0;
+}
+
+static char *
+output_move_const_double (operands)
+ rtx *operands;
+{
+ if (FP_REG_P (operands[0]))
+ {
+ int conval = standard_80387_constant_p (operands[1]);
+
+ /* fp_pop_level++; */
+ if (conval == 1)
+ return "fldz";
+ if (conval == 2)
+ return "fld1";
+ /* fp_pop_level--; */
+ }
+
+ output_move_double (operands);
+}
+
+
+static char *
+output_move_const_single (operands)
+ rtx *operands;
+{
+ if (FP_REG_P (operands[0]))
+ {
+ int conval = standard_80387_constant_p (operands[1]);
+
+ /* fp_pop_level++; */
+ if (conval == 1)
+ return "fldz";
+ if (conval == 2)
+ return "fld1";
+ /* fp_pop_level--; */
+ }
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ union { int i[2]; double d;} u1;
+ union { int i; float f;} u2;
+ u1.i[0] = CONST_DOUBLE_LOW (operands[1]);
+ u1.i[1] = CONST_DOUBLE_HIGH (operands[1]);
+ u2.f = u1.d;
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, u2.i);
+ }
+ return singlemove_string (operands);
+}
+
+/* Output an insn to move an SF value from FROM to TO.
+ The kinds of operands are not restricted
+ except that they may not both be in memory. */
+
+void
+output_movsf (to, from)
+ rtx from, to;
+{
+ rtx xops[2];
+ xops[0] = to;
+ xops[1] = from;
+ if (FP_REG_P (from) || FP_REG_P (to))
+ {
+ from = xops[1];
+ }
+
+ if (FP_REG_P (from))
+ {
+#if 0
+ {
+ if (REGNO (from) != REGNO (to))
+ {
+ output_asm_insn ("fld%S0 %1 \n\tfstp%S0 %0", xops);
+ }
+ }
+ else
+#endif
+
+ if (! FP_REG_P (to))
+ fp_pop_sf (to);
+ }
+ else if (FP_REG_P (to))
+ fp_push_sf (from);
+ else
+ output_asm_insn (singlemove_string (xops), xops);
+}
+
+/* Output an insn to move a DF value from FROM to TO.
+ The kinds of operands are not restricted
+ except that they may not both be in memory. */
+
+void
+output_movdf (to, from)
+ rtx from, to;
+{
+ rtx xops[2];
+ xops[0] = to;
+ xops[1] = from;
+ if (FP_REG_P (from) || FP_REG_P (to))
+ {
+ from = xops[1];
+ to = xops[0];
+ }
+ if (FP_REG_P (from))
+ {
+#if 0
+ {
+ if (REGNO (from) != REGNO (to))
+ abort ();
+/* output_asm_insn ("fld%Q0 %1 \n\t fstp%Q0 %0", xops);*/
+ }
+ else
+ {
+#endif
+ if (! FP_REG_P (to))
+ fp_pop_df (to);
+ }
+ else if (FP_REG_P (to))
+ fp_push_df (from);
+ else
+ output_asm_insn (output_move_double (xops), xops);
+}
+
+/* does move of FROM to TO where the mode is the minimum of the
+two */
+
+static void
+output_movf (to, from)
+ rtx to, from;
+{
+ if (GET_MODE (from) == SFmode || GET_MODE (to) == SFmode)
+ output_movsf (to, from);
+ else
+ output_movdf (to, from);
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+void
+function_prologue (file, size)
+ FILE *file;
+ int size;
+{
+ register int regno;
+ int nregs, limit;
+ rtx xops[4];
+ extern int frame_pointer_needed;
+
+ /* fp_pop_level = 0; */
+ xops[0] = stack_pointer_rtx;
+ xops[1] = frame_pointer_rtx;
+ xops[2] = gen_rtx (CONST_INT, VOIDmode, size);
+ if (frame_pointer_needed)
+ {
+ output_asm_insn ("push%L0 %1", xops);
+ output_asm_insn (AS2 (mov%L0,%0,%1), xops);
+ if (size)
+ output_asm_insn (AS2 (sub%L0,%2,%0), xops);
+ }
+
+ /* Note If use enter it is NOT reversed args.
+ This one is not reversed from intel!!
+ I think enter is slower. Also sdb doesn't like it.
+ But if you want it the code is:
+ {
+ xops[3] = const0_rtx;
+ output_asm_insn ("enter %2,%3", xops);
+ }
+ */
+ nregs = 0;
+ limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
+ for (regno = limit - 1; regno >= 0; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ fprintf (file, "\tpush%s %se%s\n", L_SIZE, RP, hi_reg_name[regno]);
+ }
+}
+
+void
+function_epilogue (file, size)
+ FILE *file;
+ int size;
+{
+ register int regno;
+ register int nregs, limit;
+ int assure_sp_pos;
+ int return_struct_adjust;
+ extern int frame_pointer_needed;
+ extern int current_function_pops_args;
+ extern int current_function_args_size;
+ extern int flag_pcc_struct_return;
+
+ limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
+ nregs = 0;
+
+ return_struct_adjust =
+ (current_function_returns_struct
+#ifdef STRUCT_RETURN_CALLER_POP
+ && !flag_pcc_struct_return
+#endif
+ ? 4 : 0);
+
+ for (regno = (limit -1); regno >= 0; regno--)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ nregs++;
+
+ /* sp is often unreliable so we must go off the frame pointer,
+ */
+
+ if (nregs && frame_pointer_needed)
+ {
+ rtx xops[2];
+ xops[0] = adj_offsettable_operand (AT_BP (Pmode),
+ -size -(nregs*(UNITS_PER_WORD)));
+ xops[1] = stack_pointer_rtx;
+ output_asm_insn (AS2 (lea%L0,%0,%1), xops);
+ }
+ for (regno = 0; regno < limit; regno++)
+ {
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ fprintf (file, "\tpop%s ", L_SIZE);
+ fprintf (file, "%se%s\n", RP, hi_reg_name[regno]);
+ }
+ }
+
+ if (frame_pointer_needed)
+ fprintf (file, "\tleave\n");
+ if (current_function_pops_args && current_function_args_size)
+ fprintf (file, "\tret %s%d\n", IP,
+ (current_function_args_size + return_struct_adjust));
+ else if (return_struct_adjust)
+ fprintf (file, "\tret %s%d\n", IP, return_struct_adjust);
+ else
+ fprintf (file, "\tret\n");
+}
+
+int
+hard_regno_mode_ok (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ return
+ (regno < 2 ? 1
+ /* Used to reject floating modes here */
+ : regno < 4 ? 1
+ : regno >= 8 ? mode == DFmode || mode == SFmode
+ : mode != QImode);
+}
+
+/* Print the name of a register based on its machine mode and number.
+ If CODE is 'w', pretend the mode is HImode.
+ If CODE is 'b', pretend the mode is QImode.
+ If CODE is 'k', pretend the mode is SImode. */
+
+#define PRINT_REG(X, CODE, FILE) \
+ do { fprintf (FILE, "%s", RP); \
+ switch ((CODE == 'w' ? 2 \
+ : CODE == 'b' ? 1 \
+ : CODE == 'k' ? 4 \
+ : GET_MODE_SIZE (GET_MODE (X)))) \
+ { \
+ case 4: \
+ case 8: \
+ if (!FP_REG_P (X)) fputs ("e", FILE); \
+ case 2: \
+ fputs (hi_reg_name[REGNO (X)], FILE); \
+ break; \
+ case 1: \
+ fputs (qi_reg_name[REGNO (X)], FILE); \
+ break; \
+ } \
+ } while (0)
+
+/* Meaning of CODE:
+ f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
+ L,W,B,Q,S -- print the opcode suffix for specified size of operand.
+ R -- print the prefix for register names.
+ z -- print the opcode suffix for the size of the current operand.
+ * -- print a star (in certain assembler syntax)
+ w -- print the operand as if it's a "word" (HImode) even if it isn't.
+ c -- don't print special prefixes before constant operands.
+*/
+
+void
+print_operand (file, x, code)
+ FILE *file;
+ rtx x;
+ int code;
+{
+ if (code)
+ {
+ switch (code)
+ {
+ case '*':
+ if (USE_STAR)
+ putc ('*', file);
+ return;
+
+ case 'L':
+ PUT_OP_SIZE (code, 'l', file);
+ return;
+
+ case 'W':
+ PUT_OP_SIZE (code, 'w', file);
+ return;
+
+ case 'B':
+ PUT_OP_SIZE (code, 'b', file);
+ return;
+
+ case 'Q':
+ PUT_OP_SIZE (code, 'l', file);
+ return;
+
+ case 'S':
+ PUT_OP_SIZE (code, 's', file);
+ return;
+
+ case 'R':
+ fprintf (file, "%s", RP);
+ return;
+
+ case 'z':
+ /* this is the size of op from size of operand */
+ switch (GET_MODE_SIZE (GET_MODE (x)))
+ {
+ case 2:
+ PUT_OP_SIZE ('W', 'w', file);
+ return;
+ case 4:
+ if (GET_MODE (x) == SFmode)
+ {
+ PUT_OP_SIZE ('S', 's', file);
+ return;
+ }
+ else
+ PUT_OP_SIZE ('L', 'l', file);
+ return;
+ case 8:
+ if (!FP_REG_P (x)) PUT_OP_SIZE ('Q', 'l', file);
+ return;
+ case 1:
+ PUT_OP_SIZE ('B', 'b', file);
+ return;
+ }
+ }
+ }
+ if (GET_CODE (x) == REG)
+ {
+ PRINT_REG (x, code, file);
+ }
+ else if (GET_CODE (x) == MEM)
+ {
+ PRINT_PTR (x, file);
+ if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
+ output_addr_const (file, XEXP (x, 0));
+ else
+ output_address (XEXP (x, 0));
+ }
+ else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
+ {
+ union { double d; int i[2]; } u;
+ union { float f; int i; } u1;
+ u.i[0] = CONST_DOUBLE_LOW (x);
+ u.i[1] = CONST_DOUBLE_HIGH (x);
+ u1.f = u.d;
+ if (code == 'f')
+ fprintf (file, "%.22e", u1.f);
+ else
+ {
+ PRINT_IMMED_PREFIX (file);
+ fprintf (file, "0x%x", u1.i);
+ }
+ }
+ else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
+ {
+ union { double d; int i[2]; } u;
+ u.i[0] = CONST_DOUBLE_LOW (x);
+ u.i[1] = CONST_DOUBLE_HIGH (x);
+ fprintf (file, "%.22e", u.d);
+ }
+ else
+ {
+ if (code != 'c')
+ {
+ if (GET_CODE (x) == CONST_INT)
+ PRINT_IMMED_PREFIX (file);
+ else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
+ || GET_CODE (x) == LABEL_REF)
+ PRINT_OFFSET_PREFIX (file);
+ }
+ output_addr_const (file, x);
+ }
+}
+
+/* Print a memory operand whose address is ADDR. */
+
+void
+print_operand_address (file, addr)
+ FILE *file;
+ register rtx addr;
+{
+ register rtx reg1, reg2, breg, ireg;
+ rtx offset;
+
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ ADDR_BEG (file);
+ fprintf (file, "%se", RP);
+ fputs (hi_reg_name[REGNO (addr)], file);
+ ADDR_END (file);
+ break;
+
+ case PLUS:
+ reg1 = 0;
+ reg2 = 0;
+ ireg = 0;
+ breg = 0;
+ offset = 0;
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) != PLUS) ;
+ else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ {
+ if (reg1 == 0) reg1 = addr;
+ else reg2 = addr;
+ addr = 0;
+ }
+ if (offset != 0)
+ {
+ if (addr != 0) abort ();
+ addr = offset;
+ }
+ if ((reg1 && GET_CODE (reg1) == MULT)
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+
+ if (ireg != 0 || breg != 0)
+ {
+ int scale = 1;
+
+ if (addr != 0)
+ {
+ if (GET_CODE (addr) == LABEL_REF)
+ output_asm_label (addr);
+ else
+ output_addr_const (file, addr);
+ }
+
+ if (ireg != 0 && GET_CODE (ireg) == MULT)
+ {
+ scale = INTVAL (XEXP (ireg, 1));
+ ireg = XEXP (ireg, 0);
+ }
+ /* output breg+ireg*scale */
+ PRINT_B_I_S (breg, ireg, scale, file);
+ break;
+ }
+
+ case MULT:
+ {
+ int scale;
+ if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
+ {
+ scale = INTVAL (XEXP (addr, 0));
+ ireg = XEXP (addr, 1);
+ }
+ else
+ {
+ scale = INTVAL (XEXP (addr, 1));
+ ireg = XEXP (addr, 0);
+ }
+ output_addr_const (file, const0_rtx);
+ PRINT_B_I_S ((rtx) 0, ireg, scale, file);
+ }
+ break;
+
+ default:
+ if (GET_CODE (addr) == CONST_INT
+ && INTVAL (addr) < 0x8000
+ && INTVAL (addr) >= -0x8000)
+ fprintf (file, "%d", INTVAL (addr));
+ else
+ output_addr_const (file, addr);
+ }
+}
+
+/* Set the cc_status for the results of an insn whose pattern is EXP.
+ On the 80386, we assume that only test and compare insns, as well
+ as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT,
+ ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
+ Also, we assume that jumps and moves don't affect the condition codes.
+ All else, clobbers the condition codes, by assumption.
+
+ We assume that ALL add, minus, etc. instructions effect the condition
+ codes. This MUST be consistent with i386.md. */
+
+notice_update_cc (exp)
+ rtx exp;
+{
+ if (GET_CODE (exp) == SET)
+ {
+ /* Jumps do not alter the cc's. */
+ if (SET_DEST (exp) == pc_rtx)
+ return;
+ /* Moving register or memory into a register:
+ it doesn't alter the cc's, but it might invalidate
+ the RTX's which we remember the cc's came from.
+ (Note that moving a constant 0 or 1 MAY set the cc's). */
+ if (REG_P (SET_DEST (exp))
+ && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
+ {
+ if (cc_status.value1
+ && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
+ cc_status.value1 = 0;
+ if (cc_status.value2
+ && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
+ cc_status.value2 = 0;
+ return;
+ }
+ /* Moving register into memory doesn't alter the cc's.
+ It may invalidate the RTX's which we remember the cc's came from. */
+ if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
+ {
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
+ cc_status.value1 = 0;
+ if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
+ cc_status.value2 = 0;
+ return;
+ }
+ /* Function calls clobber the cc's. */
+ else if (GET_CODE (SET_SRC (exp)) == CALL)
+ {
+ CC_STATUS_INIT;
+ return;
+ }
+ /* Tests and compares set the cc's in predictable ways. */
+ else if (SET_DEST (exp) == cc0_rtx)
+ {
+ CC_STATUS_INIT;
+ cc_status.value1 = SET_SRC (exp);
+ return;
+ }
+ /* Certain instructions effect the condition codes. */
+ else if (GET_MODE (SET_SRC (exp)) == SImode
+ || GET_MODE (SET_SRC (exp)) == HImode
+ || GET_MODE (SET_SRC (exp)) == QImode)
+ switch (GET_CODE (SET_SRC (exp)))
+ {
+ case ASHIFTRT: case LSHIFTRT:
+ case ASHIFT: case LSHIFT:
+ /* Shifts on the 386 don't set the condition codes if the
+ shift count is zero. */
+ if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
+ {
+ CC_STATUS_INIT;
+ break;
+ }
+ /* We assume that the CONST_INT is non-zero (this rtx would
+ have been deleted if it were zero. */
+
+ case PLUS: case MINUS: case NEG:
+ case AND: case IOR: case XOR:
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_SRC (exp);
+ cc_status.value2 = SET_DEST (exp);
+ break;
+
+ default:
+ CC_STATUS_INIT;
+ }
+ else
+ {
+ CC_STATUS_INIT;
+ }
+ }
+ else if (GET_CODE (exp) == PARALLEL
+ && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
+ {
+ if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
+ return;
+ if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
+ {
+ CC_STATUS_INIT;
+ cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
+ return;
+ }
+ CC_STATUS_INIT;
+ }
+ else
+ {
+ CC_STATUS_INIT;
+ }
+}
+
+/* Nonzero if the top of the fpu stack dies in this insn. */
+
+int
+top_dead_p (insn)
+ rtx insn;
+{
+ extern int optimize;
+ if (optimize)
+ return (find_regno_note (insn, REG_DEAD, FIRST_FLOAT_REG)
+ || find_regno_note (insn, REG_DEAD, FIRST_FLOAT_REG + 1));
+
+ if (GET_CODE (insn) == CALL_INSN)
+ return call_top_dead_p (insn);
+
+ return fp_top_dead_p1 (insn);
+}
+
+/* Following is used after a call_value insn
+ if obey_regdecls there will not be the REG_DEAD notes
+ to go by (there won't be any cross jumping to worry about
+ either), and we depend on seeing if the FP_TOP is used
+ in the next two insn's. Otherwise we depend on the
+ REG_DEAD notes.
+ */
+
+static int
+call_top_dead_p (insn)
+ rtx insn;
+{
+ int i;
+ for (i = 0; i < 3; i++)
+ {
+ insn = NEXT_INSN (insn);
+ if (insn == 0)
+ return 1;
+ if (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL)
+ continue;
+ if (GET_CODE (insn) == BARRIER)
+ abort ();
+ if (GET_CODE (PATTERN (insn)) == SET
+ && SET_DEST (PATTERN (insn)) != stack_pointer_rtx)
+ return (!(mentions_fp_top (SET_SRC (PATTERN (insn)))));
+ if (GET_CODE (PATTERN (insn)) == CALL)
+ return 1;
+ if (GET_CODE (PATTERN (insn)) == USE)
+ return (! FP_REG_P (XEXP (PATTERN (insn), 0)));
+ }
+ return 1;
+}
+
+/* Return 1 if current val of fpu top-of-stack appears unused
+ in rest of this basic block and also through a jump insn.
+ This is called from top_dead_p and from fp_call_internal. */
+
+static int
+fp_top_dead_p1 (insn)
+ rtx insn;
+{
+ extern int optimize;
+
+ int past_jump = 0;
+
+ for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
+ {
+ switch (GET_CODE (insn))
+ {
+ case CALL_INSN:
+ /* Function calls clobber this value, so it's dead. */
+ return 1;
+
+ case JUMP_INSN:
+ /* Follow one jump in case of cross-jumping,
+ which could insert such a jump into one basic block. */
+ if (! optimize)
+ /* Can't use JUMP_LABEL, but there's no cross-jumping either. */
+ return 1;
+ if (JUMP_LABEL (insn) == 0)
+ return 1;
+ /* Don't scan past a jump and another jump. */
+ if (past_jump)
+ return 1;
+ past_jump = 1;
+ insn = JUMP_LABEL (insn);
+ case CODE_LABEL:
+ if (! optimize)
+ return 1;
+ break;
+
+ case INSN:
+ if (GET_CODE (PATTERN (insn)) == SET)
+ {
+ if ((mentions_fp_top (SET_SRC (PATTERN (insn)))))
+ return 0;
+ else if (mentions_fp_top (SET_DEST (PATTERN (insn))))
+ return 1;
+ }
+ else if (mentions_fp_top (PATTERN (insn)))
+ return 0;
+ break;
+ }
+ }
+ return 1;
+}
+
+/* Return 1 if X involves an FPU register. */
+
+static int
+mentions_fp_top (x)
+ rtx x;
+{
+ register RTX_CODE code;
+
+ code = GET_CODE (x);
+ switch (code)
+ {
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST_INT:
+ case CONST:
+ case CC0:
+ case PC:
+ case CLOBBER:
+ case MEM:
+ return 0;
+
+ case REG:
+ return FP_REGNO_P (REGNO (x));
+ }
+
+ /* Recursively scan the operands of this expression. */
+ {
+ register char *fmt = GET_RTX_FORMAT (code);
+ register int i;
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ if (mentions_fp_top (XEXP (x, i)))
+ return 1;
+ }
+ if (fmt[i] == 'E')
+ {
+ register int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (mentions_fp_top (XVECEXP (x, i, j)))
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Some asm-dependent functions. */
+
+#ifdef MASM
+#include "masm386.c"
+#endif
diff --git a/gcc-1.40/config/out-i860.c b/gcc-1.40/config/out-i860.c
new file mode 100644
index 0000000..f531810
--- /dev/null
+++ b/gcc-1.40/config/out-i860.c
@@ -0,0 +1,1507 @@
+/* Subroutines for insn-output.c for Intel 860
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Derived from out-sparc.c.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Global variables for machine-dependend things. */
+
+/* This should go away if we pass floats to regs via
+ the stack instead of the frame, and if we learn how
+ to renumber all the registers when we don't do a save (hard!). */
+extern int frame_pointer_needed;
+
+static rtx find_addr_reg ();
+
+/* Return non-zero only if OP is a register of mode MODE,
+ or const0_rtx. */
+int
+reg_or_0_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (op == const0_rtx || register_operand (op, mode)
+ || op == CONST0_RTX (mode));
+}
+
+/* Return non-zero if this pattern, can be evaluated safely, even if it
+ was not asked for. */
+int
+safe_insn_src_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* Just experimenting. */
+
+ /* No floating point src is safe if it contains an arithmetic
+ operation, since that operation may trap. */
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ return 1;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return CONSTANT_ADDRESS_P (XEXP (op, 0));
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != SFmode && mode != DFmode);
+ case NOT:
+ case ZERO_EXTEND:
+ return 1;
+
+ case EQ:
+ case NE:
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ case LTU:
+ case GTU:
+ case LEU:
+ case GEU:
+ case MINUS:
+ case PLUS:
+ return (mode != SFmode && mode != DFmode);
+ case AND:
+ case IOR:
+ case XOR:
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
+ || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
+ return 0;
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return 1 if REG is clobbered in IN.
+ Return 2 if REG is used in IN.
+ Return 3 if REG is both used and clobbered in IN.
+ Return 0 if neither. */
+
+static int
+reg_clobbered_p (reg, in)
+ rtx reg;
+ rtx in;
+{
+ register enum rtx_code code;
+
+ if (in == 0)
+ return 0;
+
+ code = GET_CODE (in);
+
+ if (code == SET || code == CLOBBER)
+ {
+ rtx dest = SET_DEST (in);
+ int set = 0;
+ int used = 0;
+
+ while (GET_CODE (dest) == STRICT_LOW_PART
+ || GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == SIGN_EXTRACT
+ || GET_CODE (dest) == ZERO_EXTRACT)
+ dest = XEXP (dest, 0);
+
+ if (dest == reg)
+ set = 1;
+ else if (GET_CODE (dest) == REG
+ && refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ SET_DEST (in), 0))
+ {
+ set = 1;
+ /* Anything that sets just part of the register
+ is considered using as well as setting it.
+ But note that a straight SUBREG of a single-word value
+ clobbers the entire value. */
+ if (dest != SET_DEST (in)
+ && ! (GET_CODE (SET_DEST (in)) == SUBREG
+ || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
+ used = 1;
+ }
+
+ if (code == SET)
+ {
+ if (set)
+ used = refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ SET_SRC (in), 0);
+ else
+ used = refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ in, 0);
+ }
+
+ return set + used * 2;
+ }
+
+ if (refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ in, 0))
+ return 2;
+ return 0;
+}
+
+/* Return non-zero if OP can be written to without screwing up
+ GCC's model of what's going on. It is assumed that this operand
+ appears in the dest position of a SET insn in a conditional
+ branch's delay slot. AFTER is the label to start looking from. */
+int
+operand_clobbered_before_used_after (op, after)
+ rtx op;
+ rtx after;
+{
+ extern char call_used_regs[];
+
+ /* Just experimenting. */
+ if (GET_CODE (op) == CC0)
+ return 1;
+ if (GET_CODE (op) == REG)
+ {
+ rtx insn;
+
+ if (op == stack_pointer_rtx)
+ return 0;
+
+ /* Scan forward from the label, to see if the value of OP
+ is clobbered before the first use. */
+
+ for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == NOTE)
+ continue;
+ if (GET_CODE (insn) == INSN
+ || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ switch (reg_clobbered_p (op, PATTERN (insn)))
+ {
+ default:
+ return 0;
+ case 1:
+ return 1;
+ case 0:
+ break;
+ }
+ }
+ /* If we reach another label without clobbering OP,
+ then we cannot safely write it here. */
+ else if (GET_CODE (insn) == CODE_LABEL)
+ return 0;
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ if (condjump_p (insn))
+ return 0;
+ /* This is a jump insn which has already
+ been mangled. We can't tell what it does. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ return 0;
+ if (! JUMP_LABEL (insn))
+ return 0;
+ /* Keep following jumps. */
+ insn = JUMP_LABEL (insn);
+ }
+ }
+ return 1;
+ }
+
+ /* In both of these cases, the first insn executed
+ for this op will be a orh whatever%h,r0,r31,
+ which is tolerable. */
+ if (GET_CODE (op) == MEM)
+ return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
+
+ return 0;
+}
+
+/* Return non-zero if this pattern, as a source to a "SET",
+ is known to yield an instruction of unit size. */
+int
+single_insn_src_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ /* This is not always a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ return 1;
+
+ case SYMBOL_REF:
+ case CONST:
+ /* This is not a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ return 1;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return 1;
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != DFmode);
+ case NOT:
+ case ZERO_EXTEND:
+ return 1;
+
+ case PLUS:
+ case MINUS:
+ /* Detect cases that require multiple instructions. */
+ if (CONSTANT_P (XEXP (op, 1))
+ && !(GET_CODE (XEXP (op, 1)) == CONST_INT
+ && SMALL_INT (XEXP (op, 1))))
+ return 0;
+ case EQ:
+ case NE:
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ case LTU:
+ case GTU:
+ case LEU:
+ case GEU:
+ /* Not doing floating point, since they probably
+ take longer than the branch slot they might fill. */
+ return (mode != SFmode && mode != DFmode);
+
+ case AND:
+ if (GET_CODE (XEXP (op, 1)) == NOT)
+ {
+ rtx arg = XEXP (XEXP (op, 1), 0);
+ if (CONSTANT_P (arg)
+ && !(GET_CODE (arg) == CONST_INT
+ && (SMALL_INT (arg)
+ || INTVAL (arg) & 0xffff == 0)))
+ return 0;
+ }
+ case IOR:
+ case XOR:
+ /* Both small and round numbers take one instruction;
+ others take two. */
+ if (CONSTANT_P (XEXP (op, 1))
+ && !(GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (SMALL_INT (XEXP (op, 1))
+ || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
+ return 0;
+
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ return 1;
+
+ case SUBREG:
+ if (SUBREG_WORD (op) != 0)
+ return 0;
+ return single_insn_src_p (SUBREG_REG (op), mode);
+
+ /* Not doing floating point, since they probably
+ take longer than the branch slot they might fill. */
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case FLOAT:
+ case FIX:
+ case UNSIGNED_FLOAT:
+ case UNSIGNED_FIX:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/* Nonzero only if this *really* is a single insn operand. */
+int
+strict_single_insn_op_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ switch (GET_CODE (op))
+ {
+ case CC0:
+ return 1;
+
+ case CONST_INT:
+ if (SMALL_INT (op))
+ return 1;
+ /* We can put this set insn into delay slot, because this is one
+ insn; 'sethi'. */
+ if ((INTVAL (op) & 0x3ff) == 0)
+ return 1;
+ return 0;
+
+ case SYMBOL_REF:
+ return 0;
+
+ case REG:
+#if 0
+ /* This loses when moving an freg to a general reg. */
+ return HARD_REGNO_NREGS (REGNO (op), mode) == 1;
+#endif
+ return (mode != DFmode && mode != DImode);
+
+ case MEM:
+ if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
+ return (mode != DFmode && mode != DImode);
+ return 0;
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != DFmode);
+ case NOT:
+ case ZERO_EXTEND:
+ return 1;
+
+ case PLUS:
+ case MINUS:
+ /* Detect cases that require multiple instructions. */
+ if (CONSTANT_P (XEXP (op, 1))
+ && !(GET_CODE (XEXP (op, 1)) == CONST_INT
+ && SMALL_INT (XEXP (op, 1))))
+ return 0;
+ case EQ:
+ case NE:
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ case LTU:
+ case GTU:
+ case LEU:
+ case GEU:
+ return 1;
+
+ case AND:
+ if (GET_CODE (XEXP (op, 1)) == NOT)
+ {
+ rtx arg = XEXP (XEXP (op, 1), 0);
+ if (CONSTANT_P (arg)
+ && !(GET_CODE (arg) == CONST_INT
+ && (SMALL_INT (arg)
+ || INTVAL (arg) & 0xffff == 0)))
+ return 0;
+ }
+ case IOR:
+ case XOR:
+ /* Both small and round numbers take one instruction;
+ others take two. */
+ if (CONSTANT_P (XEXP (op, 1))
+ && !(GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (SMALL_INT (XEXP (op, 1))
+ || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
+ return 0;
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ return 1;
+
+ case SUBREG:
+ if (SUBREG_WORD (op) != 0)
+ return 0;
+ return strict_single_insn_op_p (SUBREG_REG (op), mode);
+
+ case SIGN_EXTEND:
+ if (GET_CODE (XEXP (op, 0)) == MEM
+ && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
+ return 1;
+ return 0;
+
+ /* Not doing floating point, since they probably
+ take longer than the branch slot they might fill. */
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case FLOAT:
+ case FIX:
+ case UNSIGNED_FLOAT:
+ case UNSIGNED_FIX:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return truth value of whether OP is a relational operator. */
+int
+relop (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case EQ:
+ case NE:
+ case GT:
+ case GE:
+ case LT:
+ case LE:
+ case GTU:
+ case GEU:
+ case LTU:
+ case LEU:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return truth value of whether OP can be used as an operands in a three
+ address add/subtract insn (such as add %o1,7,%l2) of mode MODE. */
+
+int
+arith_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
+}
+
+/* Return 1 if OP is a valid first operand for a logical insn of mode MODE. */
+
+int
+logic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
+}
+
+/* Return 1 if OP is a valid first operand for either a logical insn
+ or an add insn of mode MODE. */
+
+int
+compare_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
+}
+
+/* Return truth value of whether OP can be used as an operand
+ of a bte insn. */
+
+int
+bte_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT
+ && (unsigned) INTVAL (op) < 0x20));
+}
+
+/* Return 1 if OP is an indexed memory reference of mode MODE. */
+
+int
+indexed_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == MEM && GET_MODE (op) == mode
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_MODE (XEXP (op, 0)) == SImode
+ && register_operand (XEXP (XEXP (op, 0), 0), SImode)
+ && register_operand (XEXP (XEXP (op, 0), 1), SImode));
+}
+
+/* Return 1 if OP is a suitable source operand for a load insn
+ with mode MODE. */
+
+int
+load_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (memory_operand (op, mode) || indexed_operand (op, mode));
+}
+
+/* Return truth value of whether OP is a integer which fits the
+ range constraining immediate operands in add/subtract insns. */
+
+int
+small_int (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+}
+
+/* Return truth value of whether OP is a integer which fits the
+ range constraining immediate operands in logic insns. */
+
+int
+logic_int (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (operands[1]) != MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("orh ha%%%m0,r0,r31", operands);
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ return "st.l %r1,l%%%m0(r31)";
+ }
+ else
+ return "st.l %r1,%0";
+ else
+ abort ();
+#if 0
+ {
+ rtx xoperands[2];
+
+ cc_status.flags &= ~CC_F0_IS_0;
+ xoperands[0] = gen_rtx (REG, SFmode, 32);
+ xoperands[1] = operands[1];
+ output_asm_insn (singlemove_string (xoperands), xoperands);
+ xoperands[1] = xoperands[0];
+ xoperands[0] = operands[0];
+ output_asm_insn (singlemove_string (xoperands), xoperands);
+ return "";
+ }
+#endif
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("orh ha%%%m1,r0,r31", operands);
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return "ld.l l%%%m1(r31),%0";
+ }
+ return "ld.l %1,%0";
+ }
+ return "mov %1,%0";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+/* ??? Perhaps in some cases move double words
+ if there is a spare pair of floating regs. */
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If the first move would clobber the source of the second one,
+ do them in the other order.
+
+ RMS says "This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance."
+
+ but it happens on the sparc when loading parameter registers,
+ so I am going to define that circumstance, and make it work
+ as expected. */
+
+ if (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1]))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("adds 0x4,%0,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("adds 0x4,%0,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("adds -0x4,%0,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("adds -0x4,%0,%0", &addreg1);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+ else if (optype0 == REGOP && optype1 != REGOP
+ && reg_overlap_mentioned_p (operands[0], operands[1]))
+ {
+ /* Do the late half first. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+ /* Then clobber. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("adds 0x4,%0,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("adds 0x4,%0,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("adds -0x4,%0,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("adds -0x4,%0,%0", &addreg1);
+
+ return "";
+}
+
+static char *
+output_fp_move_double (operands)
+ rtx *operands;
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return "fmov.dd %1,%0";
+ if (GET_CODE (operands[1]) == REG)
+ {
+ output_asm_insn ("ixfr %1,%0", operands);
+ operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
+ return "ixfr %1,%0";
+ }
+ if (operands[1] == dconst0_rtx)
+ return "fmov.dd f0,%0";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("orh ha%%%m1,r0,r31", operands);
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return "fld.d l%%%m1(r31),%0";
+ }
+ return "fld.d %1,%0";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == REG)
+ {
+ output_asm_insn ("fxfr %1,%0", operands);
+ operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
+ return "fxfr %1,%0";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("orh ha%%%m0,r0,r31", operands);
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = XEXP (operands[0], 0);
+ return "fst.d %1,l%%%m0(r31)";
+ }
+ return "fst.d %1,%0";
+ }
+ else abort ();
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+/* Return a template for a load instruction with mode MODE and
+ arguments from the string ARGS.
+
+ This string is in static storage. */
+
+static char *
+load_opcode (mode, args, reg)
+ enum machine_mode mode;
+ char *args;
+ rtx reg;
+{
+ static char buf[30];
+ char *opcode;
+
+ switch (mode)
+ {
+ case QImode:
+ opcode = "ld.b";
+ break;
+
+ case HImode:
+ opcode = "ld.s";
+ break;
+
+ case SImode:
+ case SFmode:
+ if (FP_REG_P (reg))
+ opcode = "fld.l";
+ else
+ opcode = "ld.l";
+ break;
+
+ case DImode:
+ if (!FP_REG_P (reg))
+ abort ();
+ case DFmode:
+ opcode = "fld.d";
+ break;
+
+ default:
+ abort ();
+ }
+
+ sprintf (buf, "%s %s", opcode, args);
+ return buf;
+}
+
+/* Return a template for a store instruction with mode MODE and
+ arguments from the string ARGS.
+
+ This string is in static storage. */
+
+static char *
+store_opcode (mode, args, reg)
+ enum machine_mode mode;
+ char *args;
+ rtx reg;
+{
+ static char buf[30];
+ char *opcode;
+
+ switch (mode)
+ {
+ case QImode:
+ opcode = "st.b";
+ break;
+
+ case HImode:
+ opcode = "st.s";
+ break;
+
+ case SImode:
+ case SFmode:
+ if (FP_REG_P (reg))
+ opcode = "fst.l";
+ else
+ opcode = "st.l";
+ break;
+
+ case DImode:
+ if (!FP_REG_P (reg))
+ abort ();
+ case DFmode:
+ opcode = "fst.d";
+ break;
+
+ default:
+ abort ();
+ }
+
+ sprintf (buf, "%s %s", opcode, args);
+ return buf;
+}
+
+/* Output a store-in-memory whose operands are OPERANDS[0,1].
+ OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
+
+ This function returns a template for an insn.
+ This is in static storage.
+
+ It may also output some insns directly.
+ It may alter the values of operands[0] and operands[1]. */
+
+char *
+output_store (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx address = XEXP (operands[0], 0);
+ char *string;
+
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = address;
+
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && address == cc_prev_status.mdep))
+ {
+ output_asm_insn ("orh ha%%%m0,r0,r31", operands);
+ cc_prev_status.mdep = address;
+ }
+
+ /* Store zero in two parts when appropriate. */
+ if (mode == DFmode && operands[1] == dconst0_rtx)
+ return store_opcode (DFmode, "%r1,l%%%m0(r31)", operands[1]);
+
+ /* Code below isn't smart enough to move a doubleword in two parts,
+ so use output_move_double to do that in the cases that require it. */
+ if ((mode == DImode || mode == DFmode)
+ && ! FP_REG_P (operands[1]))
+ return output_move_double (operands);
+
+ return store_opcode (mode, "%r1,l%%%m0(r31)", operands[1]);
+}
+
+/* Output a load-from-memory whose operands are OPERANDS[0,1].
+ OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
+
+ This function returns a template for an insn.
+ This is in static storage.
+
+ It may also output some insns directly.
+ It may alter the values of operands[0] and operands[1]. */
+
+char *
+output_load (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx address = XEXP (operands[1], 0);
+
+ /* We don't bother trying to see if we know %hi(address).
+ This is because we are doing a load, and if we know the
+ %hi value, we probably also know that value in memory. */
+ cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
+ cc_status.mdep = address;
+
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && address == cc_prev_status.mdep
+ && cc_prev_status.mdep == cc_status.mdep))
+ {
+ output_asm_insn ("orh ha%%%m1,r0,r31", operands);
+ cc_prev_status.mdep = address;
+ }
+
+ /* Code below isn't smart enough to move a doubleword in two parts,
+ so use output_move_double to do that in the cases that require it. */
+ if ((mode == DImode || mode == DFmode)
+ && ! FP_REG_P (operands[0]))
+ return output_move_double (operands);
+
+ return load_opcode (mode, "l%%%m1(r31),%0", operands[0]);
+}
+
+/* Load the address specified by OPERANDS[3] into the register
+ specified by OPERANDS[0].
+
+ OPERANDS[3] may be the result of a sum, hence it could either be:
+
+ (1) CONST
+ (2) REG
+ (2) REG + CONST_INT
+ (3) REG + REG + CONST_INT
+ (4) REG + REG (special case of 3).
+
+ Note that (3) is not a legitimate address.
+ All cases are handled here. */
+
+void
+output_load_address (operands)
+ rtx *operands;
+{
+ rtx base, offset;
+
+ if (CONSTANT_P (operands[3]))
+ {
+ output_asm_insn ("mov %3,%0", operands);
+ return;
+ }
+
+ if (REG_P (operands[3]))
+ {
+ if (REGNO (operands[0]) != REGNO (operands[3]))
+ output_asm_insn ("mov %3,%0", operands);
+ return;
+ }
+
+ if (GET_CODE (operands[3]) != PLUS)
+ abort ();
+
+ base = XEXP (operands[3], 0);
+ offset = XEXP (operands[3], 1);
+
+ if (GET_CODE (base) == CONST_INT)
+ {
+ rtx tmp = base;
+ base = offset;
+ offset = tmp;
+ }
+
+ if (GET_CODE (offset) != CONST_INT)
+ {
+ /* Operand is (PLUS (REG) (REG)). */
+ base = operands[3];
+ offset = const0_rtx;
+ }
+
+ if (REG_P (base))
+ {
+ operands[6] = base;
+ operands[7] = offset;
+ if (SMALL_INT (offset))
+ output_asm_insn ("adds %7,%6,%0", operands);
+ else
+ output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
+ }
+ else if (GET_CODE (base) == PLUS)
+ {
+ operands[6] = XEXP (base, 0);
+ operands[7] = XEXP (base, 1);
+ operands[8] = offset;
+
+ if (SMALL_INT (offset))
+ output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
+ else
+ output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
+ }
+ else
+ abort ();
+}
+
+/* Output code to place a size count SIZE in register REG. */
+
+static void
+output_size_for_block_move (size, reg, align)
+ rtx size, reg, align;
+{
+ rtx xoperands[3];
+
+ xoperands[0] = reg;
+ xoperands[1] = size;
+ xoperands[2] = align;
+
+#if 1
+ cc_status.flags &= ~ CC_KNOW_HI_R31;
+ output_asm_insn ("mov %1,%0", xoperands);
+#else
+ if (GET_CODE (size) == REG)
+ output_asm_insn ("sub %2,%1,%0", xoperands);
+ else
+ {
+ xoperands[1]
+ = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
+ cc_status.flags &= ~ CC_KNOW_HI_R31;
+ output_asm_insn ("mov %1,%0", xoperands);
+ }
+#endif
+}
+
+/* Emit code to perform a block move.
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the source.
+ OPERANDS[2] is the size.
+ OPERANDS[3] is the known safe alignment.
+ OPERANDS[4..6] are pseudos we can safely clobber as temps. */
+
+char *
+output_block_move (operands)
+ rtx *operands;
+{
+ /* A vector for our computed operands. Note that load_output_address
+ makes use of (and can clobber) up to the 8th element of this vector. */
+ rtx xoperands[10];
+ rtx zoperands[10];
+ static int movstrsi_label = 0;
+ int i, j;
+ rtx temp1 = operands[4];
+ rtx alignrtx = operands[3];
+ int align = INTVAL (alignrtx);
+
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2] = temp1;
+
+ /* We can't move more than four bytes at a time
+ because we have only one register to move them through. */
+ if (align > 4)
+ {
+ align = 4;
+ alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
+ }
+
+ /* Since we clobber untold things, nix the condition codes. */
+ CC_STATUS_INIT;
+
+ /* Recognize special cases of block moves. These occur
+ when GNU C++ is forced to treat something as BLKmode
+ to keep it in memory, when its mode could be represented
+ with something smaller.
+
+ We cannot do this for global variables, since we don't know
+ what pages they don't cross. Sigh. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) <= 16
+ && ! CONSTANT_ADDRESS_P (operands[0])
+ && ! CONSTANT_ADDRESS_P (operands[1]))
+ {
+ int size = INTVAL (operands[2]);
+ rtx op0 = xoperands[0];
+ rtx op1 = xoperands[1];
+
+ cc_status.flags &= ~CC_KNOW_HI_R31;
+ if (align == 1)
+ {
+ if (memory_address_p (QImode, plus_constant (op0, size))
+ && memory_address_p (QImode, plus_constant (op1, size)))
+ {
+ for (i = size-1; i >= 0; i--)
+ {
+ xoperands[0] = plus_constant (op0, i);
+ xoperands[1] = plus_constant (op1, i);
+ output_asm_insn ("ld.b %a1,r31\n\tst.b r31,%a0",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ else if (align == 2)
+ {
+ if (memory_address_p (HImode, plus_constant (op0, size))
+ && memory_address_p (HImode, plus_constant (op1, size)))
+ {
+ for (i = (size>>1)-1; i >= 0; i--)
+ {
+ xoperands[0] = plus_constant (op0, i * 2);
+ xoperands[1] = plus_constant (op1, i * 2);
+ output_asm_insn ("ld.s %a1,r31\n\tst.s r31,%a0",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ else
+ {
+ if (memory_address_p (SImode, plus_constant (op0, size))
+ && memory_address_p (SImode, plus_constant (op1, size)))
+ {
+ for (i = (size>>2)-1; i >= 0; i--)
+ {
+ xoperands[0] = plus_constant (op0, i * 4);
+ xoperands[1] = plus_constant (op1, i * 4);
+ output_asm_insn ("ld.l %a1,r31\n\tst.l r31,%a0",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ }
+
+ /* This is the size of the transfer.
+ Either use the register which already contains the size,
+ or use a free register (used by no operands). */
+ output_size_for_block_move (operands[2], operands[4], alignrtx);
+
+#if 0
+ /* Also emit code to decrement the size value by ALIGN. */
+ zoperands[0] = operands[0];
+ zoperands[3] = plus_constant (operands[0], align);
+ output_load_address (zoperands);
+#endif
+
+ /* Generate number for unique label. */
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+
+ /* Copy the increment (negative) to a register for bla insn. */
+
+ xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - align);
+ xoperands[5] = operands[5];
+ output_asm_insn ("mov %4,%5", xoperands);
+
+ /* Make available a register which is a temporary. */
+
+ xoperands[6] = operands[6];
+
+ /* Now the actual loop.
+ In xoperands, elements 1 and 0 are the input and output vectors.
+ Element 2 is the loop index. Element 5 is the increment. */
+
+ if (align == 1)
+ {
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+
+ output_asm_insn ("adds %1,%2,%1", xoperands);
+ output_asm_insn ("adds %5,%2,%2\n.Lm%3:", xoperands);
+ output_asm_insn ("ld.b 0(%1),r31", xoperands);
+ output_asm_insn ("adds %5,%1,%1", xoperands);
+ output_asm_insn ("st.b r31,0(%6)", xoperands);
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %5,%6,%6", xoperands);
+ }
+ if (align == 2)
+ {
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+
+ output_asm_insn ("adds %1,%2,%1", xoperands);
+ output_asm_insn ("adds %5,%2,%2\n.Lm%3:", xoperands);
+ output_asm_insn ("ld.s 0(%1),r31", xoperands);
+ output_asm_insn ("adds %5,%1,%1", xoperands);
+ output_asm_insn ("st.s r31,0(%6)", xoperands);
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %5,%6,%6", xoperands);
+ }
+ if (align == 4)
+ {
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+
+ output_asm_insn ("adds %1,%2,%1", xoperands);
+ output_asm_insn ("adds %5,%2,%2\n.Lm%3:", xoperands);
+ output_asm_insn ("ld.l 0(%1),r31", xoperands);
+ output_asm_insn ("adds %5,%1,%1", xoperands);
+ output_asm_insn ("st.l r31,0(%6)", xoperands);
+ output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
+ output_asm_insn ("adds %5,%6,%6", xoperands);
+ }
+
+ return "";
+}
+
+/* Output a delayed branch insn with the delay insn in its
+ branch slot. The delayed branch insn template is in TEMPLATE,
+ with operands OPERANDS. The insn in its delay slot is INSN.
+
+ As a special case, since we know that all memory transfers are via
+ ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
+ reference around the branch as
+
+ orh ha%x,r0,r31
+ b ...
+ ld/st l%x(r31),...
+
+ As another special case, we handle loading (SYMBOL_REF ...) and
+ other large constants around branches as well:
+
+ orh h%x,r0,%0
+ b ...
+ or l%x,%0,%1
+
+ */
+
+char *
+output_delayed_branch (template, operands, insn)
+ char *template;
+ rtx *operands;
+ rtx insn;
+{
+ extern rtx recog_operand[];
+ rtx src = XVECEXP (PATTERN (insn), 0, 1);
+ rtx dest = XVECEXP (PATTERN (insn), 0, 0);
+
+ if (GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == CONST
+ || (GET_CODE (src) == CONST_INT
+ && !(SMALL_INT (src) || (INTVAL (src) & 0xffff) == 0)))
+ {
+ rtx xoperands[2];
+ xoperands[0] = dest;
+ xoperands[1] = src;
+
+ /* Output the `orh' insn. */
+ output_asm_insn ("orh h%%%1,r0,%0", xoperands);
+
+ /* Output the branch instruction next. */
+ output_asm_insn (template, operands);
+
+ /* Now output the `or' insn. */
+ output_asm_insn ("or l%%%1,%0,%0", xoperands);
+ }
+ else if ((GET_CODE (src) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (src, 0)))
+ || (GET_CODE (dest) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
+ {
+ rtx xoperands[2];
+ char *split_template;
+ xoperands[0] = dest;
+ xoperands[1] = src;
+
+ /* Output the `orh' insn. */
+ if (GET_CODE (src) == MEM)
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("orh ha%%%m1,r0,r31", xoperands);
+ split_template = load_opcode (GET_MODE (dest),
+ "l%%%m1(r31),%0", dest);
+ }
+ else
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
+ && (cc_prev_status.flags & CC_HI_R31_ADJ)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("orh ha%%%m0,r0,r31", xoperands);
+ split_template = store_opcode (GET_MODE (dest),
+ "%r1,l%%%m0(r31)", src);
+ }
+
+ /* Output the branch instruction next. */
+ output_asm_insn (template, operands);
+
+ /* Now output the load or store.
+ No need to do a CC_STATUS_INIT, because we are branching anyway. */
+ output_asm_insn (split_template, xoperands);
+ }
+ else
+ {
+ extern char *insn_template[];
+ extern char *(*insn_outfun[])();
+ extern int insn_n_operands[];
+ extern rtx alter_subreg();
+ int insn_code_number;
+ rtx pat = gen_rtx (SET, VOIDmode, dest, src);
+ rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
+ int i;
+
+ /* Output the branch instruction first. */
+ output_asm_insn (template, operands);
+
+ /* Now recognize the insn which we put in its delay slot.
+ We must do this after outputing the branch insn,
+ since operands may just be a pointer to `recog_operand'. */
+ insn_code_number = recog (pat, delay_insn);
+ if (insn_code_number == -1)
+ abort ();
+
+ for (i = 0; i < insn_n_operands[insn_code_number]; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ }
+
+ /* Now get the template for what this insn would
+ have been, without the branch. Its operands are
+ exactly the same as they would be, so we don't
+ need to do an insn_extract. */
+ template = insn_template[insn_code_number];
+ if (template == 0)
+ template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
+ output_asm_insn (template, recog_operand);
+ }
+ CC_STATUS_INIT;
+ return "";
+}
+
+/* Output a newly constructed insn DELAY_INSN. */
+char *
+output_delay_insn (delay_insn)
+ rtx delay_insn;
+{
+ char *template;
+ extern rtx recog_operand[];
+ extern char call_used_regs[];
+ extern char *insn_template[];
+ extern int insn_n_operands[];
+ extern char *(*insn_outfun[])();
+ extern rtx alter_subreg();
+ int insn_code_number;
+ extern int insn_n_operands[];
+ int i;
+
+ /* Now recognize the insn which we put in its delay slot.
+ We must do this after outputing the branch insn,
+ since operands may just be a pointer to `recog_operand'. */
+ insn_code_number = recog_memoized (delay_insn);
+ if (insn_code_number == -1)
+ abort ();
+
+ /* Extract the operands of this delay insn. */
+ INSN_CODE (delay_insn) = insn_code_number;
+ insn_extract (delay_insn);
+
+ /* It is possible that this insn has not been properly scaned by final
+ yet. If this insn's operands don't appear in the peephole's
+ actual operands, then they won't be fixed up by final, so we
+ make sure they get fixed up here. -- This is a kludge. */
+ for (i = 0; i < insn_n_operands[insn_code_number]; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ }
+
+#ifdef REGISTER_CONSTRAINTS
+ if (! constrain_operands (insn_code_number))
+ abort ();
+#endif
+
+ cc_prev_status = cc_status;
+
+ /* Update `cc_status' for this instruction.
+ The instruction's output routine may change it further.
+ If the output routine for a jump insn needs to depend
+ on the cc status, it should look at cc_prev_status. */
+
+ NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
+
+ /* Now get the template for what this insn would
+ have been, without the branch. */
+
+ template = insn_template[insn_code_number];
+ if (template == 0)
+ template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
+ output_asm_insn (template, recog_operand);
+ return "";
+}
diff --git a/gcc-1.40/config/out-m68k.c b/gcc-1.40/config/out-m68k.c
new file mode 100644
index 0000000..1f05125
--- /dev/null
+++ b/gcc-1.40/config/out-m68k.c
@@ -0,0 +1,560 @@
+/* Subroutines for insn-output.c for Motorola 68000 family.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Some output-actions in m68k.md need these. */
+#include <stdio.h>
+extern FILE *asm_out_file;
+
+/* Index into this array by (register number >> 3) to find the
+ smallest class which contains that register. */
+enum reg_class regno_reg_class[]
+ = { DATA_REGS, ADDR_REGS, FP_REGS,
+ LO_FPA_REGS, LO_FPA_REGS, FPA_REGS, FPA_REGS };
+
+static rtx find_addr_reg ();
+
+char *
+output_btst (operands, countop, dataop, insn, signpos)
+ rtx *operands;
+ rtx countop, dataop;
+ rtx insn;
+ int signpos;
+{
+ operands[0] = countop;
+ operands[1] = dataop;
+
+ if (GET_CODE (countop) == CONST_INT)
+ {
+ register int count = INTVAL (countop);
+ /* If COUNT is bigger than size of storage unit in use,
+ advance to the containing unit of same size. */
+ if (count > signpos)
+ {
+ int offset = (count & ~signpos) / 8;
+ count = count & signpos;
+ operands[1] = dataop = adj_offsettable_operand (dataop, offset);
+ }
+ if (count == signpos)
+ cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
+ else
+ cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
+
+ if (count == 31
+ && next_insns_test_no_inequality (insn))
+ return "tst%.l %1";
+ if (count == 15
+ && next_insns_test_no_inequality (insn))
+ return "tst%.w %1";
+ if (count == 7
+ && next_insns_test_no_inequality (insn))
+ return "tst%.b %1";
+
+ cc_status.flags = CC_NOT_NEGATIVE;
+ }
+ return "btst %0,%1";
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
+ return "fpmoves %1,%0";
+ if (operands[1] != const0_rtx)
+ return "move%.l %1,%0";
+ if (! ADDRESS_REG_P (operands[0]))
+ return "clr%.l %0";
+ return "sub%.l %0,%0";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ optype0 = POPOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ optype0 = PUSHOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
+ optype1 = POPOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ optype1 = PUSHOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If one operand is decrementing and one is incrementing
+ decrement the former register explicitly
+ and change that operand into ordinary indexing. */
+
+ if (optype0 == PUSHOP && optype1 == POPOP)
+ {
+ operands[0] = XEXP (XEXP (operands[0], 0), 0);
+ output_asm_insn ("subq%.l %#8,%0", operands);
+ operands[0] = gen_rtx (MEM, DImode, operands[0]);
+ optype0 = OFFSOP;
+ }
+ if (optype0 == POPOP && optype1 == PUSHOP)
+ {
+ operands[1] = XEXP (XEXP (operands[1], 0), 0);
+ output_asm_insn ("subq%.l %#8,%1", operands);
+ operands[1] = gen_rtx (MEM, DImode, operands[1]);
+ optype1 = OFFSOP;
+ }
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+#ifndef HOST_WORDS_BIG_ENDIAN
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+#else /* HOST_WORDS_BIG_ENDIAN */
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+#endif /* HOST_WORDS_BIG_ENDIAN */
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If insn is effectively movd N(sp),-(sp) then we will do the
+ high word first. We should use the adjusted operand 1 (which is N+4(sp))
+ for the low word as well, to compensate for the first decrement of sp. */
+ if (optype0 == PUSHOP
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
+ operands[1] = latehalf[1];
+
+ /* If one or both operands autodecrementing,
+ do the two words, high-numbered first. */
+
+ /* Likewise, the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == PUSHOP || optype1 == PUSHOP
+ || (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1])))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addql %#4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subql %#4,%0", &addreg1);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addql %#4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subql %#4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subql %#4,%0", &addreg1);
+
+ return "";
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+/* Test for -0.0. */
+
+int
+double_is_minus_zero (arg)
+ double arg;
+{
+ union { double d; int i[2];} u;
+
+ u.d = arg;
+ return (u.i[1] == 0 && u.i[0] == 0x80000000);
+}
+
+char *
+output_move_const_double (operands)
+ rtx *operands;
+{
+ if (TARGET_FPA && FPA_REG_P(operands[0]))
+ {
+ int code = standard_sun_fpa_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fpmove%%.d %%%%%d,%%0", code & 0x1ff);
+ return buf;
+ }
+ return "fpmove%.d %1,%0";
+ }
+ else
+ {
+ int code = standard_68881_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+ return buf;
+ }
+ return "fmove%.d %1,%0";
+ }
+}
+
+char *
+output_move_const_single (operands)
+ rtx *operands;
+{
+ if (TARGET_FPA)
+ {
+ int code = standard_sun_fpa_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fpmove%%.s %%%%%d,%%0", code & 0x1ff);
+ return buf;
+ }
+ return "fpmove%.s %1,%0";
+ }
+ else
+ {
+ int code = standard_68881_constant_p (operands[1]);
+
+ if (code != 0)
+ {
+ static char buf[40];
+
+ sprintf (buf, "fmovecr %%#0x%x,%%0", code & 0xff);
+ return buf;
+ }
+ return "fmove%.s %f1,%0";
+ }
+}
+
+/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
+ from the "fmovecr" instruction.
+ The value, anded with 0xff, gives the code to use in fmovecr
+ to get the desired constant. */
+
+int
+standard_68881_constant_p (x)
+ rtx x;
+{
+ union {double d; int i[2];} u;
+ register double d;
+
+#ifdef HOST_WORDS_BIG_ENDIAN
+ u.i[0] = CONST_DOUBLE_LOW (x);
+ u.i[1] = CONST_DOUBLE_HIGH (x);
+#else
+ u.i[0] = CONST_DOUBLE_HIGH (x);
+ u.i[1] = CONST_DOUBLE_LOW (x);
+#endif
+ d = u.d;
+
+ if (d == 0)
+ return 0x0f;
+ /* Note: there are various other constants available
+ but it is a nuisance to put in their values here. */
+ if (d == 1)
+ return 0x32;
+ if (d == 10)
+ return 0x33;
+ if (d == 100)
+ return 0x34;
+ if (d == 10000)
+ return 0x35;
+ if (d == 1e8)
+ return 0x36;
+ if (GET_MODE (x) == SFmode)
+ return 0;
+ if (d == 1e16)
+ return 0x37;
+ /* larger powers of ten in the constants ram are not used
+ because they are not equal to a `double' C constant. */
+ return 0;
+}
+
+/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get
+ from the Sun FPA's constant RAM.
+ The value returned, anded with 0x1ff, gives the code to use in fpmove
+ to get the desired constant. */
+#define S_E (2.718281745910644531)
+#define D_E (2.718281828459045091)
+#define S_PI (3.141592741012573242)
+#define D_PI (3.141592653589793116)
+#define S_SQRT2 (1.414213538169860840)
+#define D_SQRT2 (1.414213562373095145)
+#define S_LOG2ofE (1.442695021629333496)
+#define D_LOG2ofE (1.442695040888963387)
+#define S_LOG2of10 (3.321928024291992188)
+#define D_LOG2of10 (3.321928024887362182)
+#define S_LOGEof2 (0.6931471824645996094)
+#define D_LOGEof2 (0.6931471805599452862)
+#define S_LOGEof10 (2.302585124969482442)
+#define D_LOGEof10 (2.302585092994045901)
+#define S_LOG10of2 (0.3010300099849700928)
+#define D_LOG10of2 (0.3010299956639811980)
+#define S_LOG10ofE (0.4342944920063018799)
+#define D_LOG10ofE (0.4342944819032518167)
+
+int
+standard_sun_fpa_constant_p (x)
+ rtx x;
+{
+ union {double d; int i[2];} u;
+ register double d;
+ u.i[0] = CONST_DOUBLE_LOW (x);
+ u.i[1] = CONST_DOUBLE_HIGH (x);
+ d = u.d;
+
+ if (d == 0.0)
+ return 0x200; /* 0 once 0x1ff is anded with it */
+ if (d == 1.0)
+ return 0xe;
+ if (d == 0.5)
+ return 0xf;
+ if (d == -1.0)
+ return 0x10;
+ if (d == 2.0)
+ return 0x11;
+ if (d == 3.0)
+ return 0xB1;
+ if (d == 4.0)
+ return 0x12;
+ if (d == 8.0)
+ return 0x13;
+ if (d == 0.25)
+ return 0x15;
+ if (d == 0.125)
+ return 0x16;
+ if (d == 10.0)
+ return 0x17;
+ if (d == -(1.0/2.0))
+ return 0x2E;
+
+/*
+ * Stuff that looks different if it's single or double
+ */
+ if (GET_MODE(x) == SFmode)
+ {
+ if (d == S_E)
+ return 0x8;
+ if (d == (2*S_PI))
+ return 0x9;
+ if (d == S_PI)
+ return 0xA;
+ if (d == (S_PI / 2.0))
+ return 0xB;
+ if (d == S_SQRT2)
+ return 0xC;
+ if (d == (1.0 / S_SQRT2))
+ return 0xD;
+ /* Large powers of 10 in the constant
+ ram are not used because they are
+ not equal to a C double constant */
+ if (d == -(S_PI / 2.0))
+ return 0x27;
+ if (d == S_LOG2ofE)
+ return 0x28;
+ if (d == S_LOG2of10)
+ return 0x29;
+ if (d == S_LOGEof2)
+ return 0x2A;
+ if (d == S_LOGEof10)
+ return 0x2B;
+ if (d == S_LOG10of2)
+ return 0x2C;
+ if (d == S_LOG10ofE)
+ return 0x2D;
+ }
+ else
+ {
+ if (d == D_E)
+ return 0x8;
+ if (d == (2*D_PI))
+ return 0x9;
+ if (d == D_PI)
+ return 0xA;
+ if (d == (D_PI / 2.0))
+ return 0xB;
+ if (d == D_SQRT2)
+ return 0xC;
+ if (d == (1.0 / D_SQRT2))
+ return 0xD;
+ /* Large powers of 10 in the constant
+ ram are not used because they are
+ not equal to a C double constant */
+ if (d == -(D_PI / 2.0))
+ return 0x27;
+ if (d == D_LOG2ofE)
+ return 0x28;
+ if (d == D_LOG2of10)
+ return 0x29;
+ if (d == D_LOGEof2)
+ return 0x2A;
+ if (d == D_LOGEof10)
+ return 0x2B;
+ if (d == D_LOG10of2)
+ return 0x2C;
+ if (d == D_LOG10ofE)
+ return 0x2D;
+ }
+ return 0x0;
+}
+
+#undef S_E
+#undef D_E
+#undef S_PI
+#undef D_PI
+#undef S_SQRT2
+#undef D_SQRT2
+#undef S_LOG2ofE
+#undef D_LOG2ofE
+#undef S_LOG2of10
+#undef D_LOG2of10
+#undef S_LOGEof2
+#undef D_LOGEof2
+#undef S_LOGEof10
+#undef D_LOGEof10
+#undef S_LOG10of2
+#undef D_LOG10of2
+#undef S_LOG10ofE
+#undef D_LOG10ofE
diff --git a/gcc-1.40/config/out-m88k.c b/gcc-1.40/config/out-m88k.c
new file mode 100644
index 0000000..d02ac86
--- /dev/null
+++ b/gcc-1.40/config/out-m88k.c
@@ -0,0 +1,605 @@
+/* Subroutines for insn-output.c for Motorola 88000.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILE
+#include <stdio.h>
+#endif
+
+/* This is where the condition code register lives. */
+rtx cc0_reg_rtx;
+
+static rtx find_addr_reg ();
+
+#if 0
+char *
+output_compare (operands, opcode, exchange_opcode)
+ rtx *operands;
+ char *opcode;
+ char *exchange_opcode;
+{
+ static char buf[40];
+ rtx op1, op2;
+
+ if (GET_CODE (cc_prev_status.value2) == COMPARE)
+ {
+ op1 = XEXP (cc_prev_status.value2, 0);
+ op2 = XEXP (cc_prev_status.value2, 1);
+ }
+ else
+ {
+ op1 = cc_prev_status.value2;
+ op2 = const0_rtx;
+ }
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ operands[2] = op1;
+ operands[1] = op2;
+ opcode = exchange_opcode;
+ }
+ else
+ {
+ operands[1] = op1;
+ operands[2] = op2;
+ }
+ sprintf (buf, "cmp r25,%%1,%%2\n\tbcnd %s,r25,%%l0", opcode);
+ return buf;
+}
+
+char *
+output_fcompare (operands, opcode, exchange_opcode)
+ rtx *operands;
+ char *opcode;
+ char *exchange_opcode;
+{
+ static char buf[40];
+
+ rtx op1, op2;
+
+ if (GET_CODE (cc_prev_status.value2) == COMPARE)
+ {
+ op1 = XEXP (cc_prev_status.value2, 0);
+ op2 = XEXP (cc_prev_status.value2, 1);
+ }
+ else
+ {
+ op1 = cc_prev_status.value2;
+ op2 = const0_rtx;
+ }
+ if (GET_CODE (op1) == CONST_DOUBLE)
+ {
+ operands[2] = op1;
+ operands[1] = op2;
+ opcode = exchange_opcode;
+ }
+ else
+ {
+ operands[1] = op1;
+ operands[2] = op2;
+ }
+ sprintf (buf, "cmp r25,%%1,%%2\n\tbcnd %s,r25,%%l0", opcode);
+ return buf;
+}
+
+char *
+output_store (operands, opcode, exchange_opcode)
+ rtx *operands;
+ char *opcode;
+ char *exchange_opcode;
+{
+ static char buf[40];
+ rtx op1, op2;
+
+ if (GET_CODE (cc_prev_status.value2) == COMPARE)
+ {
+ op1 = XEXP (cc_prev_status.value2, 0);
+ op2 = XEXP (cc_prev_status.value2, 1);
+ }
+ else
+ {
+ op1 = cc_prev_status.value2;
+ op2 = const0_rtx;
+ }
+
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ operands[2] = op1;
+ operands[1] = op2;
+ opcode = exchange_opcode;
+ }
+ else
+ {
+ operands[1] = op1;
+ operands[2] = op2;
+ }
+
+ sprintf (buf, "cmp r25,%%1,%%2\n\textu %%0,r25,1<%s>", opcode);
+ return buf;
+}
+#endif
+
+/* Nonzero if OP is a valid second operand for an arithmetic insn. */
+
+int
+arith_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT
+ && (unsigned) INTVAL (op) < 0x10000));
+}
+
+int
+arith32_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
+}
+
+int
+int5_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x20);
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return "st %r1,%0";
+ if (GET_CODE (operands[1]) == MEM)
+ return "ld %0,%1";
+ return "or %0,r0,%1";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (operands[0]);
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (operands[1]);
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1]))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addu %0,%0,4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addu %0,%0,4", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subu %0,%0,4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subu %0,%0,4", &addreg0);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("addu %0,%0,4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addu %0,%0,4", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("subu %0,%0,4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subu %0,%0,4", &addreg1);
+
+ return "";
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ return 0;
+}
+
+/* Output an ascii string. */
+output_ascii (file, p, size)
+ FILE *file;
+ char *p;
+ int size;
+{
+ int i;
+
+ fprintf (file, "\tstring \"");
+
+ for (i = 0; i < size; i++)
+ {
+ register int c = p[i];
+ if (c == '\"' || c == '\\')
+ putc ('\\', file);
+ if (c >= ' ' && c < 0177)
+ putc (c, file);
+ else
+ {
+ fprintf (file, "\\%03o", c);
+ /* After an octal-escape, if a digit follows,
+ terminate one string constant and start another.
+ The Vax assembler fails to stop reading the escape
+ after three digits, so this is the only way we
+ can get it to parse the data properly. */
+ if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
+ fprintf (file, "\"\n\tstring \"");
+ }
+ }
+ fprintf (file, "\"\n");
+}
+
+void
+output_load_address (operands)
+ rtx *operands;
+{
+ rtx base, offset;
+
+ if (CONSTANT_P (operands[3]))
+ {
+ output_asm_insn ("lda %0,%3", operands);
+ return;
+ }
+
+ if (REG_P (operands[3]))
+ {
+ if (REGNO (operands[0]) != REGNO (operands[3]))
+ output_asm_insn ("or %0,r0,%3", operands);
+ return;
+ }
+
+ base = XEXP (operands[3], 0);
+ offset = XEXP (operands[3], 1);
+
+ if (GET_CODE (base) == CONST_INT)
+ {
+ rtx tmp = base;
+ base = offset;
+ offset = tmp;
+ }
+
+ if (GET_CODE (offset) != CONST_INT)
+ abort ();
+
+ operands[6] = base;
+ operands[7] = offset;
+
+ if (REG_P (base))
+ if (FITS_16_BITS (offset))
+ output_asm_insn ("addu %0,%6,%7", operands);
+ else if (INT_FITS_16_BITS (- INTVAL (offset)))
+ output_asm_insn ("subu %0,%6,%7", operands);
+ else
+ output_asm_insn ("or.h %0,r0,hi16(%7)\n\tor %0,%0,lo16(%7)\n\tadd %0,%6,%0", operands);
+ else
+ {
+ if (GET_CODE (base) == MULT)
+ if (GET_MODE (base) == QImode)
+ output_asm_insn ("lda.b %0,%6");
+ else if (GET_MODE (base) == HImode)
+ output_asm_insn ("lda.h %0,%6");
+ else if (GET_MODE (base) == SImode)
+ output_asm_insn ("lda %0,%6");
+ else
+ output_asm_insn ("lda.d %0,%6");
+ else
+ output_asm_insn ("lda %0,%6");
+
+ if (FITS_16_BITS (offset))
+ output_asm_insn ("addu %0,%7,%0", operands);
+ else if (INT_FITS_16_BITS (- INTVAL (offset)))
+ output_asm_insn ("subu %0,%7,%0", operands);
+ else
+ output_asm_insn ("or.h r25,r0,hi16(%7)\n\tor r25,r0,lo16(%7)\n\taddu %0,%0r25", operands);
+ }
+}
+
+char *
+output_block_move (operands)
+ rtx *operands;
+{
+ static int movstrsi_label = 0;
+ int align = 4;
+
+ rtx xoperands[9];
+ int available[3];
+ int i, j;
+
+ /* Since we clobber untold things, nix the condition codes. */
+ CC_STATUS_INIT;
+
+ /* Get past the MEMs. */
+ operands[0] = XEXP (operands[0], 0);
+ operands[1] = XEXP (operands[1], 0);
+
+ xoperands[0] = 0;
+ xoperands[1] = 0;
+ xoperands[2] = 0;
+
+ available[0] = 1;
+ available[1] = 1;
+ available[2] = 1;
+#if 1
+ /* Prepare to juggle registers if necessary. */
+ if (REG_P (operands[0]) && (unsigned) (REGNO (operands[0]) - 10) < 3)
+ {
+ xoperands[0] = operands[0];
+ available[REGNO (operands[0]) - 10] = 0;
+ }
+ if (REG_P (operands[1]) && (unsigned) (REGNO (operands[1]) - 10) < 3)
+ {
+ xoperands[1] = operands[1];
+ available[REGNO (operands[1]) - 10] = 0;
+ }
+ if (REG_P (operands[2]) && (unsigned) (REGNO (operands[2]) - 10) < 3)
+ {
+ xoperands[2] = operands[2];
+ available[REGNO (operands[2]) - 10] = 0;
+ }
+ for (i = 0; i < 3; i++)
+ {
+ if (xoperands[i])
+ continue;
+ if (available[0])
+ {
+ xoperands[i] = gen_rtx (REG, SImode, 10);
+ available[0] = 0;
+ continue;
+ }
+ if (available[1])
+ {
+ xoperands[i] = gen_rtx (REG, SImode, 11);
+ available[1] = 0;
+ continue;
+ }
+ xoperands[i] = gen_rtx (REG, SImode, 12);
+ available[2] = 0;
+ }
+#endif
+
+ /* First, figure out best alignment we may assume. */
+ if (REG_P (operands[2]))
+ {
+ xoperands[5] = operands[2];
+ output_asm_insn ("sub %5,%2,1", xoperands);
+ align = 1;
+ }
+ else
+ {
+ int i = INTVAL (operands[2]);
+
+ if (i & 1)
+ align = 1;
+ else if (i & 3)
+ {
+ align = 2;
+ i >>= 1;
+ }
+ else
+ i >>= 2;
+
+ /* predecrement count. */
+ i -= 1;
+ if (i < 0) abort ();
+
+ xoperands[5] = gen_rtx (CONST_INT, VOIDmode, i);
+
+ if (INT_FITS_16_BITS (i))
+ output_asm_insn ("addu %2,r0,%5", xoperands);
+ else if (INT_FITS_16_BITS (-i))
+ {
+ xoperands[5] = gen_rtx (CONST_INT, VOIDmode, -i);
+ output_asm_insn ("subu %2,r0,%5", xoperands);
+ }
+ else
+ output_asm_insn ("or.u %2,r0,hi16(%5)\n\tor %2,%2,lo16(%5)", xoperands);
+ }
+ /* Now, set up for pipelined operation: dest must contain
+ a pre-incremented address, because its index is pre-decremented. */
+
+ xoperands[3] = plus_constant (operands[0], align);
+ output_load_address (xoperands);
+
+ xoperands[4] = operands[1];
+ output_load_address (xoperands+1);
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+
+ if (align == 4)
+ output_asm_insn ("\n@Lm%3:\n\tld r25,%1[%2]\n\tsubu %2,%2,1\n\tbcnd.n ge0,%2,@Lm%3\n\tst r25,%0[%2]", xoperands);
+ else if (align == 2)
+ output_asm_insn ("\n@Lm%3:\n\tld.h r25,%1[%2]\n\tsubu %2,%2,1\n\tbcnd.n ge0,%2,@Lm%3\n\tst.h r25,%0[%2]", xoperands);
+ else
+ output_asm_insn ("\n@Lm%3:\n\tld.b r25,%1[%2]\n\tsubu %2,%2,1\n\tbcnd.n ge0,%2,@Lm%3\n\tst.b r25,%0[%2]", xoperands);
+ return "";
+}
+
+char *
+output_store_const_int (mode, operands)
+ enum machine_mode mode;
+ rtx *operands;
+{
+ int i = INTVAL (operands[1]);
+ if (INT_FITS_16_BITS (i))
+ return "addu %0,r0,%1";
+ if (INT_FITS_16_BITS (-i))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, -i);
+ return "subu %0,r0,%1";
+ }
+ if ((i & 0xffff) == 0)
+ return "or.u %0,r0,hi16(%1)";
+ /* Could check to see if number is a contiguous field
+ of 1's. Then we could use the SET instruction. */
+ if (mode == HImode)
+ {
+ warning ("truncating constant `%d' to fit in half-word", INTVAL (operands[1]));
+ return "or %0,r0,lo16(%1)";
+ }
+ if (mode == QImode)
+ {
+ warning ("truncating constant `%d' to fit in byte");
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, i & 0xff);
+ return "or %0,r0,%1";
+ }
+
+ return "or.u %0,r0,hi16(%1)\n\tor %0,%0,lo16(%1)";
+}
+
+/* This routine assumes that floating point numbers are represented
+ in a manner which is consistent between host and target machines. */
+char *
+output_store_const_float (mode, operands)
+ enum machine_mode mode;
+ rtx *operands;
+{
+ int i = INTVAL (operands[1]);
+ if (INT_FITS_16_BITS (i))
+ return "addu %0,r0,%1";
+ if (INT_FITS_16_BITS (-i))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, -i);
+ return "subu %0,r0,%1";
+ }
+ if ((i & 0xffff) == 0)
+ return "or.u %0,r0,hi16(%1)";
+ /* Could check to see if number is a contiguous field
+ of 1's. Then we could use the SET instruction. */
+ return "or.u %0,r0,hi16(%1)\n\tor %0,%0,lo16(%1)";
+}
diff --git a/gcc-1.40/config/out-mips.c b/gcc-1.40/config/out-mips.c
new file mode 100644
index 0000000..ab1dac0
--- /dev/null
+++ b/gcc-1.40/config/out-mips.c
@@ -0,0 +1,1086 @@
+/* Subroutines for insn-output.c for MIPS
+ Contributed by A. Lichnewsky, lich@inria.inria.fr.
+ Changes by Michael Meissner, meissner@osf.org.
+ Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include "tree.h"
+#include "flags.h"
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+extern void debug_rtx ();
+extern void abort_with_insn ();
+
+extern FILE *asm_out_file;
+extern tree current_function_decl;
+
+/* Global variables for machine-dependent things. */
+
+char *reg_numchar[] = REGISTER_NUMCHAR;
+
+/* Threshold for data being put into the small data/bss area, instead
+ of the normal data area (references to the small data/bss area take
+ 1 instruction, and use the global pointer, references to the normal
+ data area takes 2 instructions). */
+int mips_section_threshold = -1;
+
+/* Count the number of .file directives, so that .loc is up to date. */
+int num_source_filenames = 0;
+
+/* Count the number of words that are pushed to pass arguments. */
+int stack_args_pushed = 0;
+
+/* # bytes for args preallocated by function_prolog. */
+int stack_args_preallocated = 0;
+
+/* Count of the number of functions created so far, in order to make
+ unique labels for omitting the frame pointer. */
+int number_functions_processed = 0;
+
+/* Count the number of sdb related labels are generated (to find block
+ start and end boundaries). */
+int sdb_label_count = 0;
+
+/* Next label # for each statment for Silicon Graphics IRIS systems. */
+int sym_lineno = 0;
+
+/* Non-zero if inside of a function, because the stupid MIPS asm can't
+ handle .files inside of functions. */
+int inside_function = 0;
+
+/* String to be used for the unique name given to the difference between
+ the stack pointer and frame pointer when the frame pointer is to be
+ omitted. */
+char *sp_fp_difference = 0;
+
+/* Files to separate the text and the data output, so that all of the data
+ can be emitted before the text, which will mean that the assembler will
+ generate smaller code, based on the global pointer. */
+FILE *asm_out_data_file;
+FILE *asm_out_text_file;
+
+/* Linked list of all externals that are to be emitted when optimizing
+ for the global pointer if they haven't been declared by the end of
+ the program with an appropriate .comm or initialization. */
+
+struct extern_list {
+ struct extern_list *next; /* next external */
+ char *name; /* name of the external */
+ int size; /* size in bytes */
+} *extern_head = 0;
+
+/* Name of the current function. */
+char *current_function_name;
+
+/* Size of the frame allocated for this function. */
+int current_function_total_framesize;
+
+/* Number of bytes used to hold saved registers. */
+int current_function_saved_reg_size;
+
+/* Return truth value of whether OP can be used as an operands
+ where a register or 16 bit unsigned integer is needed. */
+
+int
+uns_arith_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op)));
+}
+
+/* Return truth value of whether OP can be used as an operands
+ where a 16 bit integer is needed */
+
+int
+arith_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
+}
+
+/* Return truth value of whether OP can be used as an operand in a two
+ address arithmetic insn (such as set 123456,%o4) of mode MODE. */
+
+int
+arith32_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
+}
+
+/* Return truth value of whether OP is a integer which fits in 16 bits */
+
+int
+small_int (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+}
+
+
+/* Argument support functions. */
+
+/* Initialize CUMULATIVE_ARGS for a function. */
+
+void
+init_cumulative_args (cum, fntype)
+ CUMULATIVE_ARGS cum; /* argument info to initialize */
+ tree fntype; /* tree ptr for function decl */
+{
+ tree param, next_param;
+
+ if (TARGET_DEBUGE_MODE)
+ {
+ fprintf (stderr, "\ninit_cumulative_args\n");
+ if (fntype != (tree)0)
+ {
+ putc ('\n', stderr);
+ debug_tree (fntype);
+ putc ('\n', stderr);
+ }
+ }
+
+ cum->gp_reg_found = 0;
+ cum->arg_number = 0;
+ cum->arg_words = 0;
+
+ /* Determine if this function has variable arguments. This is
+ indicated by the last argument being 'void_type_mode' if there
+ are no variable arguments. The standard MIPS calling sequence
+ passes all arguments in the general purpose registers in this
+ case. */
+
+ for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
+ param != (tree)0;
+ param = next_param)
+ {
+ next_param = TREE_CHAIN (param);
+ if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node)
+ cum->gp_reg_found = 1;
+ }
+
+ /* Determine if the function is returning a structure, if so,
+ advance by one argument. */
+
+ if (fntype
+ && (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE)
+ && TREE_TYPE (fntype) != 0)
+ {
+ tree ret_type = TREE_TYPE (fntype);
+ enum tree_code ret_code = TREE_CODE (ret_type);
+
+ if (ret_code == RECORD_TYPE || ret_code == UNION_TYPE)
+ {
+ cum->gp_reg_found = 1;
+ cum->arg_number = 1;
+ cum->arg_words = 1;
+ }
+ }
+}
+
+/* Advance the argument to the next argument position. */
+
+void
+function_arg_advance (cum, mode, type, named)
+ CUMULATIVE_ARGS cum; /* current arg information */
+ enum machine_mode mode; /* current arg mode */
+ tree type; /* type of the argument or 0 if lib support */
+{
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr,
+ "function_adv( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n",
+ cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
+ type, named);
+
+ cum->arg_number++;
+ switch (mode)
+ {
+ default:
+ error ("Illegal mode given to function_arg_advance");
+ break;
+
+ case VOIDmode:
+ break;
+
+ case BLKmode:
+ cum->gp_reg_found = 1;
+ cum->arg_words += (int_size_in_bytes (type) + 3) / 4;
+ break;
+
+ case SFmode:
+ cum->arg_words++;
+ break;
+
+ case DFmode:
+ cum->arg_words += 2;
+ break;
+
+ case DImode:
+ cum->gp_reg_found = 1;
+ cum->arg_words += 2;
+ break;
+
+ case QImode:
+ case HImode:
+ case SImode:
+ cum->gp_reg_found = 1;
+ cum->arg_words++;
+ break;
+ }
+}
+
+/* Return a RTL expression containing the register for the given mode,
+ or 0 if the argument is too be passed on the stack. */
+
+struct rtx_def *
+function_arg (cum, mode, type, named)
+ CUMULATIVE_ARGS cum; /* current arg information */
+ enum machine_mode mode; /* current arg mode */
+ tree type; /* type of the argument or 0 if lib support */
+ int named; /* != 0 for normal args, == 0 for ... args */
+{
+ int regbase = -1;
+ int bias = 0;
+
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr,
+ "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d ) = ",
+ cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
+ type, named);
+
+ switch (mode)
+ {
+ default:
+ error ("Illegal mode given to function_arg");
+ break;
+
+ case SFmode:
+ if (cum->gp_reg_found || cum->arg_number >= 2)
+ regbase = GP_ARG_FIRST;
+ else {
+ regbase = FP_ARG_FIRST;
+ if (cum->arg_words == 1) /* first arg was float */
+ bias = 1; /* use correct reg */
+ }
+
+ break;
+
+ case DFmode:
+ cum->arg_words += (cum->arg_words & 1);
+ regbase = (cum->gp_reg_found) ? GP_ARG_FIRST : FP_ARG_FIRST;
+ break;
+
+ case VOIDmode:
+ case BLKmode:
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ regbase = GP_ARG_FIRST;
+ break;
+ }
+
+ if (cum->arg_words >= MAX_ARGS_IN_REGISTERS)
+ {
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr, "<stack>\n");
+
+ return 0;
+ }
+
+ if (regbase == -1)
+ abort ();
+
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr, "%s\n", reg_numchar[ regbase + cum->arg_number + bias ]);
+
+ return gen_rtx (REG, mode, regbase + cum->arg_words + bias);
+}
+
+
+int
+function_arg_partial_nregs (cum, mode, type, named)
+ CUMULATIVE_ARGS cum; /* current arg information */
+ enum machine_mode mode; /* current arg mode */
+ tree type; /* type of the argument or 0 if lib support */
+ int named; /* != 0 for normal args, == 0 for ... args */
+{
+ if (mode == BLKmode && cum->arg_words < MAX_ARGS_IN_REGISTERS)
+ {
+ int words = (int_size_in_bytes (type) + 3) / 4;
+
+ if (words + cum->arg_words < MAX_ARGS_IN_REGISTERS)
+ return 0; /* structure fits in registers */
+
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr, "function_arg_partial_nregs = %d\n",
+ MAX_ARGS_IN_REGISTERS - cum->arg_words);
+
+ return MAX_ARGS_IN_REGISTERS - cum->arg_words;
+ }
+
+ else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS-1)
+ {
+ if (TARGET_DEBUGE_MODE)
+ fprintf (stderr, "function_arg_partial_nregs = 1\n");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Routines to merge the compare and branch operators into a single entity. */
+
+static rtx branch_cmp_op[2];
+static enum machine_mode branch_cmp_mode;
+
+/* Save the mode and operands on the current compare operator. */
+
+void
+compare_collect (mode, op0, op1)
+ enum machine_mode mode;
+ rtx op0;
+ rtx op1;
+{
+ if (TARGET_DEBUGD_MODE)
+ {
+ fprintf (stderr, "compare_collect mode = %s, operands::",
+ GET_MODE_NAME (mode));
+ debug_rtx (op0);
+ debug_rtx (op1);
+ }
+ branch_cmp_op[0] = op0;
+ branch_cmp_op[1] = op1;
+ branch_cmp_mode = mode;
+}
+
+/* Return the mode and operands saved with compare_collect for use
+ in a branch operator. */
+
+void
+compare_restore (operands, mode, insn)
+ rtx *operands;
+ enum machine_mode *mode;
+ rtx insn;
+{
+ if (!branch_cmp_op[0] || !branch_cmp_op[1])
+ abort_with_insn (insn, "Compare_restore did not follow compare_collect");
+
+ if (TARGET_DEBUGD_MODE)
+ {
+ fprintf (stderr,
+ "compare_restore returning mode = %s, operands:%X,%X:",
+ GET_MODE_NAME (branch_cmp_mode),
+ branch_cmp_op[0],
+ branch_cmp_op[1]);
+
+ debug_rtx (branch_cmp_op[0]);
+ debug_rtx (branch_cmp_op[1]);
+ }
+
+ operands[0] = branch_cmp_op[0];
+ operands[1] = branch_cmp_op[1];
+ *mode = branch_cmp_mode;
+
+ /* If the next insn is not a JUMP (after accounting for line numbers),
+ zero out the branch_cmp_array. Switch statements implemented as if's
+ tend to have multiple jumps. */
+ do
+ {
+ insn = NEXT_INSN (insn);
+ }
+ while (insn && GET_CODE (insn) == NOTE);
+
+ if (!insn || GET_CODE (insn) != JUMP_INSN)
+ {
+ branch_cmp_op[0] = NULL;
+ branch_cmp_op[1] = NULL;
+ branch_cmp_mode = VOIDmode;
+ }
+
+}
+
+/* Print the options used in the assembly file. */
+
+static struct {char *name; int value;} target_switches []
+ = TARGET_SWITCHES;
+
+void
+print_options (out)
+ FILE *out;
+{
+ int line_len;
+ int len;
+ int j;
+ char **p;
+ int mask = TARGET_DEFAULT;
+ extern char **save_argv;
+ extern char *version_string, *language_string;
+
+#if 0
+ /* Allow assembly language comparisons with -mdebug eliminating the
+ compiler version number and switch lists. */
+ if (!TARGET_DEBUG_MODE)
+ {
+ fprintf (out, "\n # %s %s", language_string, version_string);
+#ifdef TARGET_VERSION_INTERNAL
+ TARGET_VERSION_INTERNAL (out);
+#endif
+#ifdef __GNUC__
+ fprintf (out, " compiled by GNU C\n\n");
+#else
+ fprintf (out, " compiled by CC\n\n");
+#endif
+
+ fprintf (out, " # Cc1 defaults:");
+ line_len = 32767;
+ for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
+ if (target_switches[j].name[0] != '\0'
+ && target_switches[j].value > 0
+ && (target_switches[j].value & mask) == target_switches[j].value)
+ {
+ len = strlen (target_switches[j].name) + 1;
+ if (len + line_len > 79)
+ {
+ line_len = 2;
+ fputs ("\n #", out);
+ }
+ fprintf (out, " -m%s", target_switches[j].name);
+ line_len += len;
+ }
+
+ fprintf (out, "\n\n # Cc1 arguments (-G value = %d):",
+ mips_section_threshold);
+
+ line_len = 32767;
+ for (p = &save_argv[1]; *p != (char *)0; p++)
+ if (**p == '-')
+ {
+ len = strlen (*p) + 1;
+ if (len + line_len > 79)
+ {
+ line_len = 2;
+ fputs ("\n #", out);
+ }
+ fprintf (out, " %s", *p);
+ line_len += len;
+ }
+ fputs ("\n\n", out);
+ }
+
+#endif
+}
+
+
+
+/* Abort after printing out a specific insn. */
+
+void
+abort_with_insn (insn, reason)
+ rtx insn;
+ char *reason;
+{
+ error (reason);
+ debug_rtx (insn);
+ abort ();
+}
+
+/* Write a message to stderr (for use in macros expanded in files that do not
+ include stdio.h). */
+
+void
+trace (s, s1, s2)
+ char *s, *s1, *s2;
+{
+ fprintf (stderr, s, s1, s2);
+}
+
+
+/* Set up the threshold for data to go into the small data area, instead
+ of the normal data area, and detect any conflicts in the switches. */
+
+void
+overide_options ()
+{
+ register int i;
+
+ i = TARGET_GVALUE;
+ if (i >= 6)
+ i += 3;
+ mips_section_threshold = (i != 0) ? 1 << i : 0;
+}
+
+/* Compute a string to use as a temporary file name. */
+
+static FILE *
+make_temp_file ()
+{
+ char *temp_filename;
+ FILE *stream;
+ extern char *getenv ();
+ char *base = getenv ("TMPDIR");
+ int len;
+
+ if (base == (char *)0)
+ {
+#ifdef P_tmpdir
+ if (access (P_tmpdir, R_OK | W_OK) == 0)
+ base = P_tmpdir;
+ else
+#endif
+ if (access ("/usr/tmp", R_OK | W_OK) == 0)
+ base = "/usr/tmp/";
+ else
+ base = "/tmp/";
+ }
+
+ len = strlen (base);
+ temp_filename = (char *) alloca (len + sizeof("/ccXXXXXX"));
+ strcpy (temp_filename, base);
+ if (len > 0 && temp_filename[len-1] != '/')
+ temp_filename[len++] = '/';
+
+ strcpy (temp_filename + len, "ccXXXXXX");
+ mktemp (temp_filename);
+
+ stream = fopen (temp_filename, "w+");
+ if (!stream)
+ pfatal_with_name (temp_filename);
+
+ unlink (temp_filename);
+ return stream;
+}
+
+/* Output at beginning of assembler file.
+ If we are optimizing to use the global pointer, create a temporary
+ file to hold all of the text stuff, and write it out to the end.
+ This is needed because the MIPS assembler is evidently one pass,
+ and if it hasn't seen the relevant .comm/.lcomm/.extern/.sdata
+ declaration when the code is processed, it generates a two
+ instruction sequence. */
+
+void
+mips_asm_file_start (stream)
+ FILE *stream;
+{
+ if (TARGET_NAME_REGS)
+ fprintf (stream, "#include <regdef.h>\n");
+
+ ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);
+
+ print_options (stream);
+ data_section (); /* put gcc_compiled. in data, not text*/
+
+ if (TARGET_GP_OPT)
+ {
+ asm_out_data_file = stream;
+ asm_out_text_file = make_temp_file ();
+ }
+ else
+ asm_out_data_file = asm_out_text_file = stream;
+
+}
+
+/* If optimizing for the global pointer, keep track of all of
+ the externs, so that at the end of the file, we can emit
+ the appropriate .extern declaration for them, before writing
+ out the text section. We assume that all names passed to
+ us are in the permanent obstack, so that they will be valid
+ at the end of the compilation.
+
+ If we have -G 0, or the extern size is unknown, don't bother
+ emitting the .externs. */
+
+int
+mips_output_external (file, decl, name)
+ FILE *file;
+ tree decl;
+ char *name;
+{
+ extern char *permalloc ();
+ register struct extern_list *p;
+ int len;
+
+ if (TARGET_GP_OPT
+ && mips_section_threshold != 0
+ && ((TREE_CODE (decl)) != FUNCTION_DECL)
+ && ((len = int_size_in_bytes (TREE_TYPE (decl))) > 0))
+ {
+ p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
+ p->next = extern_head;
+ p->name = name;
+ p->size = len;
+ extern_head = p;
+ }
+ return 0;
+}
+
+/* If we are optimizing the global pointer, emit the text section now
+ and any small externs which did not have .comm, etc that are
+ needed. Also, give a warning if the data area is more than 32K and
+ -pic because 3 instructions are needed to reference the data
+ pointers. */
+
+int
+mips_asm_file_end (file)
+ FILE *file;
+{
+ char buffer[8192];
+ tree name_tree;
+ struct extern_list *p;
+ int len;
+ extern tree lookup_name ();
+
+ if (TARGET_GP_OPT)
+ {
+ if (extern_head)
+ fputs ("\n", file);
+
+ for (p = extern_head; p != 0; p = p->next)
+ {
+ name_tree = get_identifier (p->name);
+ if (!TREE_ADDRESSABLE (name_tree))
+ {
+ TREE_ADDRESSABLE (name_tree) = 1;
+ fprintf (file, "\t.extern\t%s, %d\n", p->name, p->size);
+ }
+ }
+
+ fprintf (file, "\n\t.text\n");
+ rewind (asm_out_text_file);
+ if (ferror (asm_out_text_file))
+ fatal_io_error ("write of text assembly file in mips_asm_file_end");
+
+ while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
+ if (fwrite (buffer, 1, len, file) != len)
+ pfatal_with_name ("write of final assembly file in mips_asm_file_end");
+
+ if (len < 0)
+ pfatal_with_name ("read of text assembly file in mips_asm_file_end");
+
+ if (fclose (asm_out_text_file) != 0)
+ pfatal_with_name ("close of tempfile in mips_asm_file_end");
+ }
+}
+
+/* Fix references to the frame pointer to be off of the stack pointer. */
+
+struct rtx_def *
+mips_fix_frame_pointer (oldaddr, depth)
+ rtx oldaddr;
+ int depth;
+{
+ rtx newaddr;
+ rtx sp_diff_rtx;
+ char temp[40];
+ int frame_offset = 0;
+ extern rtx eliminate_constant_term ();
+
+ newaddr = eliminate_constant_term (oldaddr, &frame_offset);
+ if (newaddr != frame_pointer_rtx)
+ return oldaddr;
+
+ if (sp_fp_difference == (char *)0)
+ {
+ sprintf (temp, "$Ls%d", number_functions_processed);
+ sp_fp_difference = IDENTIFIER_POINTER (get_identifier (temp));
+ }
+
+ sp_diff_rtx = gen_rtx (SYMBOL_REF, SImode, sp_fp_difference);
+ if (frame_offset + depth == 0)
+ newaddr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, sp_diff_rtx);
+ else
+ newaddr = gen_rtx (PLUS, Pmode,
+ stack_pointer_rtx,
+ gen_rtx (CONST, Pmode,
+ gen_rtx (PLUS, Pmode,
+ sp_diff_rtx,
+ gen_rtx (CONST_INT, VOIDmode,
+ frame_offset + depth))));
+
+ if (TARGET_DEBUGC_MODE)
+ {
+ fprintf (stderr,
+ "\n==================== FIX_FRAME, depth = %d, sp prealloc = %d, offset = %d\n",
+ depth, stack_args_preallocated, frame_offset);
+
+ fprintf (stderr, "old INSN:");
+ debug_rtx (oldaddr);
+
+ fprintf (stderr, "\nnew INSN:");
+ debug_rtx (newaddr);
+ }
+
+ return newaddr;
+}
+
+
+/* Set up the stack and frame (if desired) for the function. */
+
+void
+function_prologue (file, size)
+ FILE *file;
+ int size;
+{
+ extern char call_used_regs[];
+ extern char *reg_numchar[];
+ extern tree current_function_decl;
+ int regno;
+ int mask;
+ int fmask;
+ int push_loc;
+ int tsize;
+ int num_regs;
+ char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar;
+ char *base_str;
+ char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM];
+ char *fp_str = (!frame_pointer_needed)
+ ? sp_str
+ : reg_name_ptr[FRAME_POINTER_REGNUM];
+ tree fndecl = current_function_decl; /* current... is tooo long */
+ tree fntype = TREE_TYPE (fndecl);
+ tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
+ ? DECL_ARGUMENTS (fndecl)
+ : 0;
+ tree next_arg;
+ tree cur_arg;
+ char *arg_name = (char *)0;
+ CUMULATIVE_ARGS args_so_far;
+
+
+ inside_function = 1;
+
+
+ if (write_symbols != NO_DEBUG)
+ ASM_OUTPUT_SOURCE_LINE (file,
+ DECL_SOURCE_LINE (current_function_decl));
+
+ fprintf (file, "\t.ent\t%s\n%s:\n", current_function_name,
+ current_function_name);
+
+ fprintf (file, " #PROLOGUE\n");
+
+ /* Determine the last argument, and get it's name. */
+ for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg)
+ {
+ next_arg = TREE_CHAIN (cur_arg);
+ if (next_arg == (tree)0)
+ {
+ if (DECL_NAME (cur_arg))
+ arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
+
+ break;
+ }
+ }
+
+ /* If this function is a varargs function, store any registers that
+ would normally hold arguments ($4 - $7) on the stack. */
+ if ((TYPE_ARG_TYPES (fntype) != 0
+ && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))
+ || (arg_name
+ && (strcmp (arg_name, "__builtin_va_alist") == 0
+ || strcmp (arg_name, "va_alist") == 0)))
+ {
+ tree parm;
+
+ regno = 4;
+ INIT_CUMULATIVE_ARGS (args_so_far, fntype);
+
+ for (parm = fnargs; (parm && (regno <= 7)); parm = TREE_CHAIN (parm))
+ {
+ rtx entry_parm;
+ enum machine_mode passed_mode;
+ tree type;
+
+ type = DECL_ARG_TYPE (parm);
+ passed_mode = TYPE_MODE (type);
+ entry_parm = FUNCTION_ARG (args_so_far, passed_mode,
+ DECL_ARG_TYPE (parm), 1);
+
+ if (entry_parm)
+ {
+ int words;
+
+ /* passed in a register, so will get homed automatically */
+ if (GET_MODE (entry_parm) == BLKmode)
+ words = (int_size_in_bytes (type) + 3) / 4;
+ else
+ words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
+
+ regno = REGNO (entry_parm) + words - 1;
+ }
+ else
+ {
+ regno = 8;
+ break;
+ }
+
+ FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
+ DECL_ARG_TYPE (parm), 1);
+ }
+
+ switch (regno)
+ {
+ case 4:
+ fprintf(file, "\tsd\t%s,0(%s)\t#varargs: home regs 4-5\n",
+ reg_name_ptr[4], sp_str);
+
+ fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
+ reg_name_ptr[6], sp_str);
+ break;
+
+ case 5:
+ fprintf(file, "\tsw\t%s,4(%s)\t#varargs: home reg 5\n",
+ reg_name_ptr[5], sp_str);
+
+ fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
+ reg_name_ptr[6], sp_str);
+ break;
+
+ case 6:
+ fprintf(file, "\tsd\t%s,8(%s)\t#varargs: home regs 6-7\n",
+ reg_name_ptr[6], sp_str);
+ break;
+
+ case 7:
+ fprintf(file, "\tsw\t%s,12(%s)\t#varargs: home reg 7\n",
+ reg_name_ptr[7], sp_str);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ mask = 0;
+ fmask = 0;
+ num_regs = 0;
+ push_loc = stack_args_preallocated;
+ tsize = AL_ADJUST_ALIGN (size) + stack_args_preallocated;
+
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ if (MUST_SAVE_REGISTER (regno))
+ {
+ tsize += 4;
+ num_regs += 4;
+ mask |= 1 << (regno - GP_REG_FIRST);
+ }
+
+ tsize = AL_ADJUST_ALIGN (tsize);
+ num_regs = AL_ADJUST_ALIGN (num_regs);
+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ tsize += 8;
+ num_regs += 8;
+ fmask |= 1 << (regno - FP_REG_FIRST);
+ }
+
+ if (tsize)
+ tsize -= STARTING_FRAME_OFFSET;
+
+
+ if (!frame_pointer_needed && sp_fp_difference != (char *)0)
+ fprintf (file,"%s\t= %d\t\t\t#Difference between SP & FP\n\n",
+ sp_fp_difference, tsize);
+
+ current_function_total_framesize = tsize;
+ current_function_saved_reg_size = num_regs;
+ if (tsize > 0)
+ {
+ if (tsize <= 32767)
+ fprintf (file,
+ "\tsubu\t%s,%s,%d\t# temp= %d, regs= %d, args= %d, sfo= %d\n",
+ sp_str, sp_str, tsize, size, num_regs,
+ stack_args_preallocated, STARTING_FRAME_OFFSET);
+ else
+ fprintf (file,
+ "\tli\t%s,%d\n\tsubu\t%s,%s,%s\t# temp= %d, regs= %d, args= %d, sfo= %d\n",
+ reg_name_ptr[MIPS_TEMP1_REGNUM], tsize, sp_str, sp_str,
+ reg_name_ptr[MIPS_TEMP1_REGNUM], size, num_regs,
+ stack_args_preallocated, STARTING_FRAME_OFFSET);
+ }
+
+ fprintf (file, "\t.frame\t%s,%d,%s\n", fp_str,
+ (frame_pointer_needed) ? 0 : tsize,
+ reg_name_ptr[31]);
+
+ if (push_loc > 32767 && num_regs > 0)
+ {
+ if ((tsize - (push_loc + num_regs)) <= 32767)
+ {
+ base_str = reg_name_ptr[MIPS_TEMP1_REGNUM];
+ push_loc = tsize - push_loc;
+ }
+ else
+ {
+ base_str = reg_name_ptr[MIPS_TEMP2_REGNUM];
+ fprintf (file, "\tli\t%s,%d\n", base_str, push_loc);
+ push_loc = 0;
+ }
+ }
+ else
+ base_str = sp_str;
+
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ if ((mask & (1 << (regno - GP_REG_FIRST))) != 0)
+ {
+ fprintf (file, "\tsw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
+ base_str);
+ push_loc += 4;
+ }
+
+ fprintf (file, "\t.mask\t0x%08x,%d\n", mask, push_loc - tsize - 4);
+
+ push_loc = AL_ADJUST_ALIGN (push_loc);
+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
+ if ((fmask & (1 << (regno - FP_REG_FIRST))) != 0)
+ {
+ fprintf (file, "\ts.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
+ base_str);
+ push_loc += 8;
+ }
+
+ fprintf (file, "\t.fmask\t0x%08x,%d\n", fmask, push_loc - tsize - 4);
+
+ if (frame_pointer_needed)
+ {
+ if (tsize <= 32767)
+ fprintf (file, "\taddu\t%s,%s,%d\t# set up frame pointer\n", fp_str, sp_str, tsize);
+ else
+ fprintf (file, "\taddu\t%s,%s,%s\t# set up frame pointer\n", fp_str, sp_str,
+ reg_name_ptr[MIPS_TEMP1_REGNUM]);
+ }
+
+ fprintf (file," #END PROLOGUE\n");
+}
+
+
+/* Do any necessary cleanup after a function to restore stack, frame, and regs. */
+
+void
+function_epilogue (file, size)
+ FILE *file;
+ int size;
+{
+ extern FILE *asm_out_data_file, *asm_out_file;
+ extern char call_used_regs[];
+ extern char *reg_numchar[];
+ extern char *current_function_name;
+ extern int frame_pointer_needed;
+ int regno;
+ int push_loc = stack_args_preallocated;
+ int tsize = current_function_total_framesize;
+ int num_regs = current_function_saved_reg_size;
+ char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar;
+ char *sp_str = reg_name_ptr[STACK_POINTER_REGNUM];
+ char *t1_str = reg_name_ptr[MIPS_TEMP1_REGNUM];
+ char *base_str;
+
+
+ fprintf (file," #EPILOGUE\n");
+
+ if (tsize > 32767)
+ fprintf (file, "\tli\t%s,%d\n", t1_str, tsize);
+
+ if (frame_pointer_needed)
+ {
+ char *fp_str = reg_name_ptr[FRAME_POINTER_REGNUM];
+ if (tsize > 32767)
+ fprintf (file,"\tsubu\t%s,%s,%s\t# sp not trusted here\n",
+ sp_str, fp_str, t1_str);
+ else
+ fprintf (file,"\tsubu\t%s,%s,%d\t# sp not trusted here\n",
+ sp_str, fp_str, tsize);
+ }
+
+ if (push_loc > 32767 && num_regs > 0)
+ {
+ if ((tsize - (push_loc + num_regs)) <= 32767)
+ {
+ base_str = t1_str;
+ push_loc = tsize - push_loc;
+ }
+ else
+ {
+ base_str = reg_name_ptr[MIPS_TEMP2_REGNUM];
+ fprintf (file, "\tli\t%s,%d\n", base_str, push_loc);
+ push_loc = 0;
+ }
+ }
+ else
+ base_str = sp_str;
+
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ if (MUST_SAVE_REGISTER (regno))
+ {
+ fprintf (file,"\tlw\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
+ base_str);
+ push_loc += 4;
+ }
+
+ push_loc = AL_ADJUST_ALIGN (push_loc);
+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += 2)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ {
+ fprintf (file, "\tl.d\t%s,%d(%s)\n", reg_name_ptr[regno], push_loc,
+ base_str);
+ push_loc += 8;
+ }
+
+ if (tsize > 32767)
+ fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
+
+ else if (tsize > 0)
+ fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
+
+ fprintf (file,"\tj\t%s\n", reg_name_ptr[31]);
+ fprintf (file," #END EPILOGUE\n");
+ fprintf (file,"\t.end\t%s\n", current_function_name);
+
+ /* Reset state info for each function. */
+ stack_args_pushed = 0;
+ stack_args_preallocated = 0;
+ inside_function = 0;
+ sp_fp_difference = (char *)0;
+ number_functions_processed++;
+
+ /* Restore the output file if optimizing the GP (optimizing the GP causes
+ the text to be diverted to a tempfile, so that data decls come before
+ references to the data). */
+
+ if (TARGET_GP_OPT)
+ asm_out_file = asm_out_data_file;
+}
diff --git a/gcc-1.40/config/out-ns32k.c b/gcc-1.40/config/out-ns32k.c
new file mode 100644
index 0000000..e3df4fe
--- /dev/null
+++ b/gcc-1.40/config/out-ns32k.c
@@ -0,0 +1,575 @@
+/* Subroutines for assembler code output on the NS32000.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Some output-actions in ns32k.md need these. */
+#include <stdio.h>
+extern FILE *asm_out_file;
+
+#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) > 7 && REGNO (X) < 16)
+
+/* Generate the rtx that comes from an address expression in the md file */
+/* The expression to be build is BASE[INDEX:SCALE]. To recognize this,
+ scale must be converted from an exponent (from ASHIFT) to a
+ muliplier (for MULT). */
+rtx
+gen_indexed_expr (base, index, scale)
+ rtx base, index, scale;
+{
+ rtx addr;
+
+ /* This generates an illegal addressing mode, if BASE is
+ fp or sp. This is handled by PRINT_OPERAND_ADDRESS. */
+ if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
+ base = gen_rtx (MEM, SImode, base);
+ addr = gen_rtx (MULT, SImode, index,
+ gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (scale)));
+ addr = gen_rtx (PLUS, SImode, base, addr);
+ return addr;
+}
+
+/* Return 1 if OP is a valid constant int. These can be modeless
+ (void mode), so we do not mess with their modes.
+
+ The main use of this function is as a predicate in match_operand
+ expressions in the machine description. */
+
+int
+const_int (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT);
+}
+
+/* Return 1 if OP is a valid operand of mode MODE. This
+ predicate rejects operands which do not have a mode
+ (such as CONST_INT which are VOIDmode). */
+int
+reg_or_mem_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return (GET_MODE (op) == mode
+ && (GET_CODE (op) == REG
+ || GET_CODE (op) == SUBREG
+ || GET_CODE (op) == MEM));
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) <= 7
+ && INTVAL (operands[1]) >= -8)
+ return "movqd %1,%0";
+ return "movd %1,%0";
+}
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum anon1 { REGOP, OFFSOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ optype0 = POPOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_ADDRESS_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
+ optype1 = POPOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_ADDRESS_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If one or both operands autodecrementing,
+ do the two words, high-numbered first. */
+
+ if (optype0 == POPOP || optype1 == POPOP)
+ {
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+ return singlemove_string (operands);
+ }
+
+ /* Not autodecrementing. Do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ operands[0] = latehalf[0];
+ operands[1] = latehalf[1];
+ return singlemove_string (operands);
+}
+
+int
+check_reg (oper, reg)
+ rtx oper;
+ int reg;
+{
+ register int i;
+
+ if (oper == 0)
+ return 0;
+ switch (GET_CODE(oper))
+ {
+ case REG:
+ return (REGNO(oper) == reg) ? 1 : 0;
+ case MEM:
+ return check_reg(XEXP(oper, 0), reg);
+ case PLUS:
+ case MULT:
+ return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
+ }
+ return 0;
+}
+
+/* PRINT_OPERAND_ADDRESS is defined to call this function,
+ which is easier to debug than putting all the code in
+ a macro definition in tm-ns32k.h . */
+
+/* Nonzero if we have printed a base register.
+ If zero, on some systems, it means `(sb)' must be printed. */
+int paren_base_reg_printed = 0;
+
+print_operand_address (file, addr)
+ register FILE *file;
+ register rtx addr;
+{
+ register rtx reg1, reg2, breg, ireg;
+ rtx offset;
+ static char scales[] = { 'b', 'w', 'd', 0, 'q', };
+
+ retry:
+ switch (GET_CODE (addr))
+ {
+ case MEM:
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == REG)
+ if (REGNO (addr) == STACK_POINTER_REGNUM)
+ { fprintf (file, "tos"); break; }
+ else
+ { fprintf (file, "%s", reg_names[REGNO (addr)]); break; }
+ else if (CONSTANT_P (addr))
+ { output_addr_const (file, addr); break; }
+ else if (GET_CODE (addr) == MULT)
+ { fprintf (file, "@0"); ireg = addr; goto print_index; }
+ else if (GET_CODE (addr) == MEM)
+ {
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == PLUS)
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else
+ {
+ offset = const0_rtx;
+ }
+ output_addr_const (file, offset);
+ fprintf (file, "(%s)", reg_names[REGNO (addr)]);
+ break;
+ }
+
+ if (GET_CODE (addr) != PLUS)
+ abort ();
+
+ goto retry;
+
+ case REG:
+ if (REGNO (addr) == STACK_POINTER_REGNUM)
+ fprintf (file, "tos");
+ else
+ fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
+ break;
+
+ case PRE_DEC:
+ case POST_INC:
+ fprintf (file, "tos");
+ break;
+
+ case MULT:
+ fprintf (file, "@0");
+ ireg = addr; /* [rX:Y] */
+ goto print_index;
+ break;
+
+ case PLUS:
+ reg1 = 0; reg2 = 0;
+ ireg = 0; breg = 0;
+ offset = const0_rtx;
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) != PLUS) ;
+ else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ /* The case for memory is somewhat tricky: to get
+ a MEM here, the only RTX formats that could
+ get here are either (modulo commutativity)
+ (PLUS (PLUS (REG *MEM)) CONST) -or-
+ (PLUS (PLUS (CONST REG/MULT)) *MEM)
+ We take advantage of that knowledge here. */
+ else if (GET_CODE (XEXP (addr, 0)) == MEM
+ || GET_CODE (XEXP (addr, 1)) == MEM)
+ {
+ rtx temp;
+
+ if (GET_CODE (XEXP (addr, 0)) == MEM)
+ {
+ temp = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else
+ {
+ temp = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+
+ if (GET_CODE (temp) == REG)
+ {
+ reg1 = temp;
+ }
+ else
+ {
+ if (GET_CODE (temp) != PLUS)
+ abort ();
+
+ if (GET_CODE (XEXP (temp, 0)) == MULT)
+ {
+ reg1 = XEXP (temp, 0);
+ offset = XEXP (temp, 1);
+ }
+ if (GET_CODE (XEXP (temp, 1)) == MULT)
+ {
+ reg1 = XEXP (temp, 1);
+ offset = XEXP (temp, 0);
+ }
+ else
+ abort ();
+ }
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == REG
+ || GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ rtx temp;
+
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ temp = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else
+ {
+ temp = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+
+ if (GET_CODE (addr) == REG)
+ {
+ if (REGNO (temp) >= FRAME_POINTER_REGNUM)
+ { reg1 = addr; addr = temp; }
+ else
+ { reg1 = temp; }
+ }
+ else if (CONSTANT_P (addr))
+ {
+ if (GET_CODE (offset) == CONST_INT
+ && INTVAL (offset))
+ offset = plus_constant (addr, INTVAL (offset));
+ addr = temp;
+ }
+ else if (GET_CODE (addr) != PLUS)
+ abort ();
+ else
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else abort ();
+
+ if (GET_CODE (addr) == REG)
+ {
+ if (REGNO (temp) >= FRAME_POINTER_REGNUM)
+ { reg1 = addr; addr = temp; }
+ else
+ { reg1 = temp; }
+ }
+ else
+ reg1 = temp;
+ }
+ }
+
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }
+ if (addr != 0)
+ {
+ if (CONSTANT_P (addr) && reg1)
+ {
+ /* OFFSET comes second, to prevent outputting
+ operands of the form INT+SYMBOL+INT.
+ The Genix assembler dies on them. */
+ output_addr_const (file, addr);
+ if (offset != const0_rtx)
+ {
+ putc ('+', file);
+ output_addr_const (file, offset);
+ }
+ ireg = reg1;
+ goto print_index;
+ }
+ else if (GET_CODE (addr) != MEM)
+ abort ();
+
+ output_addr_const (file, offset);
+#ifndef SEQUENT_ADDRESS_BUG
+ putc ('(', file);
+ paren_base_reg_printed = 0;
+ output_address (addr);
+#ifdef SEQUENT_BASE_REGS
+ if (!paren_base_reg_printed)
+ fprintf (file, "(sb)");
+#endif
+ putc (')', file);
+#else /* SEQUENT_ADDRESS_BUG */
+ if ((GET_CODE (offset) == SYMBOL_REF
+ || GET_CODE (offset) == CONST)
+ && GET_CODE (addr) == REG)
+ {
+ if (reg1) abort ();
+ fprintf (file, "[%s:b]", reg_names[REGNO (addr)]);
+ }
+ else
+ {
+ putc ('(', file);
+ paren_base_reg_printed = 0;
+ output_address (addr);
+#ifdef SEQUENT_BASE_REGS
+ if (!paren_base_reg_printed)
+ fprintf (file, "(sb)");
+#endif
+ putc (')', file);
+ }
+#endif /* SEQUENT_ADDRESS_BUG */
+ ireg = reg1;
+ goto print_index;
+ }
+ else addr = offset;
+ if (reg1 && GET_CODE (reg1) == MULT)
+ { breg = reg2; ireg = reg1; }
+ else if (reg2 && GET_CODE (reg2) == MULT)
+ { breg = reg1; ireg = reg2; }
+ else if (reg2 || GET_CODE (addr) == MEM)
+ { breg = reg2; ireg = reg1; }
+ else
+ { breg = reg1; ireg = reg2; }
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)
+ {
+ int scale;
+ if (GET_CODE (ireg) == MULT)
+ {
+ scale = INTVAL (XEXP (ireg, 1)) >> 1;
+ ireg = XEXP (ireg, 0);
+ }
+ else scale = 0;
+ output_asm_label (addr);
+ fprintf (file, "[%s:%c]",
+ reg_names[REGNO (ireg)], scales[scale]);
+ break;
+ }
+ if (ireg && breg && offset == const0_rtx)
+ fprintf (file, "0(%s)", reg_names[REGNO (breg)]);
+ else
+ {
+ if (addr != 0)
+ {
+ if (ireg != 0 && breg == 0
+ && GET_CODE (offset) == CONST_INT) putc('@', file);
+ output_addr_const (file, offset);
+ }
+ if (breg != 0)
+ {
+ if (GET_CODE (breg) != REG) abort ();
+#ifndef SEQUENT_ADDRESS_BUG
+ fprintf (file, "(%s)", reg_names[REGNO (breg)]);
+ paren_base_reg_printed = -1;
+#else
+ if (GET_CODE (offset) == SYMBOL_REF || GET_CODE (offset) == CONST)
+ {
+ if (ireg) abort ();
+ fprintf (file, "[%s:b]", reg_names[REGNO (breg)]);
+ }
+ else
+ {
+ fprintf (file, "(%s)", reg_names[REGNO (breg)]);
+ paren_base_reg_printed = -1;
+ }
+#endif
+ }
+ }
+ print_index:
+ if (ireg != 0)
+ {
+ int scale;
+ if (GET_CODE (ireg) == MULT)
+ {
+ scale = INTVAL (XEXP (ireg, 1)) >> 1;
+ ireg = XEXP (ireg, 0);
+ }
+ else scale = 0;
+ if (GET_CODE (ireg) != REG) abort ();
+ fprintf (file, "[%s:%c]",
+ reg_names[REGNO (ireg)],
+ scales[scale]);
+ }
+ break;
+ default:
+ output_addr_const (file, addr);
+ }
+}
+
+/* National 32032 shifting is so bad that we can get
+ better performance in many common cases by using other
+ techniques. */
+char *
+output_shift_insn (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 3)
+ if (GET_CODE (operands[0]) == REG)
+ {
+ if (GET_CODE (operands[1]) == REG)
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return "addd %0,%0";
+ else if (INTVAL (operands[2]) == 2)
+ return "addd %0,%0\n\taddd %0,%0";
+ }
+ if (operands[2] == const1_rtx)
+ return "movd %1,%0\n\taddd %0,%0";
+
+ operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
+ return "addr %a1,%0";
+ }
+ if (operands[2] == const1_rtx)
+ return "movd %1,%0\n\taddd %0,%0";
+ }
+ else if (GET_CODE (operands[1]) == REG)
+ {
+ operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
+ return "addr %a1,%0";
+ }
+ else if (INTVAL (operands[2]) == 1
+ && GET_CODE (operands[1]) == MEM
+ && rtx_equal_p (operands [0], operands[1]))
+ {
+ rtx temp = XEXP (operands[1], 0);
+
+ if (GET_CODE (temp) == REG
+ || (GET_CODE (temp) == PLUS
+ && GET_CODE (XEXP (temp, 0)) == REG
+ && GET_CODE (XEXP (temp, 1)) == CONST_INT))
+ return "addd %0,%0";
+ }
+ else return "ashd %2,%0";
+ return "ashd %2,%0";
+}
diff --git a/gcc-1.40/config/out-pyr.c b/gcc-1.40/config/out-pyr.c
new file mode 100644
index 0000000..c6e85a8
--- /dev/null
+++ b/gcc-1.40/config/out-pyr.c
@@ -0,0 +1,849 @@
+/* Subroutines for insn-output.c for Pyramid 90 Series.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Some output-actions in pyr.md need these. */
+#include <stdio.h>
+
+extern FILE *asm_out_file;
+#include "tree.h"
+
+/*
+ * Do FUNCTION_ARG.
+ * This cannot be defined as a macro on pyramids, because Pyramid Technology's
+ * C compiler dies on (several equivalent definitions of) this macro.
+ * The only way around this cc bug was to make this a function.
+ * While it would be possible to use a macro version for gcc, it seems
+ * more reliable to have a single version of the code.
+ */
+void *
+pyr_function_arg(cum, mode, type, named)
+ CUMULATIVE_ARGS cum;
+ enum machine_mode mode;
+ tree type;
+{
+ return (void *)(FUNCTION_ARG_HELPER (cum, mode,type,named));
+}
+
+/* Do the hard part of PARAM_SAFE_FOR_REG_P.
+ * This cannot be defined as a macro on pyramids, because Pyramid Technology's
+ * C compiler dies on (several equivalent definitions of) this macro.
+ * The only way around this cc bug was to make this a function.
+ */
+int
+inner_param_safe_helper (type)
+ tree type;
+{
+ return (INNER_PARAM_SAFE_HELPER(type));
+}
+
+
+/* Return 1 if OP is a non-indexed operand of mode MODE.
+ This is either a register reference, a memory reference,
+ or a constant. In the case of a memory reference, the address
+ is checked to make sure it isn't indexed.
+
+ Register and memory references must have mode MODE in order to be valid,
+ but some constants have no machine mode and are valid for any mode.
+
+ If MODE is VOIDmode, OP is checked for validity for whatever mode
+ it has.
+
+ The main use of this function is as a predicate in match_operand
+ expressions in the machine description.
+
+ It is useful to compare this with general_operand(). They should
+ be identical except for one line.
+
+ This function seems necessary because of the non-orthogonality of
+ Pyramid insns.
+ For any 2-operand insn, and any combination of operand modes,
+ if indexing is valid for the isn's second operand, it is invalid
+ for the first operand to be indexed. */
+
+extern int volatile_ok;
+
+int
+nonindexed_operand(op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ register RTX_CODE code = GET_CODE (op);
+ int mode_altering_drug = 0;
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (CONSTANT_P (op))
+ return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
+ && LEGITIMATE_CONSTANT_P (op));
+
+ /* Except for certain constants with VOIDmode, already checked for,
+ OP's mode must match MODE if MODE specifies a mode. */
+
+ if (GET_MODE (op) != mode)
+ return 0;
+
+ while (code == SUBREG)
+ {
+ op = SUBREG_REG (op);
+ code = GET_CODE (op);
+#if 0
+ /* No longer needed, since (SUBREG (MEM...))
+ will load the MEM into a reload reg in the MEM's own mode. */
+ mode_altering_drug = 1;
+#endif
+ }
+ if (code == REG)
+ return 1;
+ if (code == CONST_DOUBLE)
+ return LEGITIMATE_CONSTANT_P (op);
+ if (code == MEM)
+ {
+ register rtx y = XEXP (op, 0);
+ if (! volatile_ok && MEM_VOLATILE_P (op))
+ return 0;
+ GO_IF_NONINDEXED_ADDRESS (y, win);
+ }
+ return 0;
+
+ win:
+ if (mode_altering_drug)
+ return ! mode_dependent_address_p (XEXP (op, 0));
+ return 1;
+}
+
+/* Return non-zero if the rtx OP has an immediate component. An
+ immediate component or additive term equal to zero is rejected
+ due to assembler problems. */
+
+int
+has_direct_base (op)
+ rtx op;
+{
+ if ((CONSTANT_ADDRESS_P (op)
+ && op != const0_rtx)
+ || (GET_CODE (op) == PLUS
+ && ((CONSTANT_ADDRESS_P (XEXP (op, 1))
+ && XEXP (op, 1) != const0_rtx)
+ || (CONSTANT_ADDRESS_P (XEXP (op, 0))
+ && XEXP (op, 0) != const0_rtx))))
+ return 1;
+
+ return 0;
+}
+
+int
+has_index (op)
+ rtx op;
+{
+ if (GET_CODE (op) == PLUS
+ && (GET_CODE (XEXP (op, 0)) == MULT
+ || (GET_CODE (XEXP (op, 1)) == MULT)))
+ return 1;
+ else
+ return 0;
+}
+
+int swap_operands;
+
+/* weird_memory_memory -- return 1 if OP1 and OP2 can be compared (or
+ exchanged with xchw) with one instruction. If the operands need to
+ be swapped, set the global variable SWAP_OPERANDS. This function
+ silently assumes that both OP0 and OP1 are valid memory references.
+ */
+
+int
+weird_memory_memory (op0, op1)
+ rtx op0, op1;
+{
+ int ret;
+ int c;
+ RTX_CODE code0, code1;
+
+ op0 = XEXP (op0, 0);
+ op1 = XEXP (op1, 0);
+ code0 = GET_CODE (op0);
+ code1 = GET_CODE (op1);
+
+ swap_operands = 0;
+
+ if (code1 == REG || code1 == SUBREG)
+ {
+ return 1;
+ }
+ if (code0 == REG || code0 == SUBREG)
+ {
+ swap_operands = 1;
+ return 1;
+ }
+ if (has_direct_base (op0) && has_direct_base (op1))
+ {
+ if (has_index (op1))
+ {
+ if (has_index (op0))
+ return 0;
+ swap_operands = 1;
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
+int
+signed_comparison (x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ return ! TRULY_UNSIGNED_COMPARE_P (GET_CODE (x));
+}
+
+extern rtx force_reg ();
+rtx test_op0, test_op1;
+enum machine_mode test_mode;
+
+/* Sign-extend or zero-extend constant X from FROM_MODE to TO_MODE. */
+
+rtx
+extend_const (x, extop, from_mode, to_mode)
+ rtx x;
+ RTX_CODE extop;
+ enum machine_mode from_mode, to_mode;
+{
+ int val;
+ int negative;
+ if (from_mode == to_mode)
+ return x;
+ if (GET_CODE (x) != CONST_INT)
+ abort ();
+ val = INTVAL (x);
+ negative = val & (1 << (GET_MODE_BITSIZE (from_mode) - 1));
+ if (GET_MODE_BITSIZE (from_mode) == HOST_BITS_PER_INT)
+ abort ();
+ if (negative && extop == SIGN_EXTEND)
+ val = val | ((-1) << (GET_MODE_BITSIZE (from_mode)));
+ else
+ val = val & ~((-1) << (GET_MODE_BITSIZE (from_mode)));
+ if (GET_MODE_BITSIZE (to_mode) == HOST_BITS_PER_INT)
+ return gen_rtx (CONST_INT, VOIDmode, val);
+ return gen_rtx (CONST_INT, VOIDmode,
+ val & ~((-1) << (GET_MODE_BITSIZE (to_mode))));
+}
+
+rtx
+ensure_extended (op, extop, from_mode)
+ rtx op;
+ RTX_CODE extop;
+ enum machine_mode from_mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return extend_const (op, extop, from_mode, SImode);
+ else
+ return force_reg (SImode, gen_rtx (extop, SImode, op));
+}
+
+/* Emit rtl for a branch, as well as any delayed (integer) compare insns.
+ The compare insn to perform is determined by the global variables
+ test_op0 and test_op1. */
+
+void
+extend_and_branch (extop)
+ RTX_CODE extop;
+{
+ rtx op0, op1;
+ RTX_CODE code0, code1;
+
+ op0 = test_op0, op1 = test_op1;
+ if (op0 == 0)
+ return;
+
+ code0 = GET_CODE (op0);
+ if (op1 != 0)
+ code1 = GET_CODE (op1);
+ test_op0 = test_op1 = 0;
+
+ if (op1 == 0)
+ {
+ op0 = ensure_extended (op0, extop, test_mode);
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx, op0));
+ }
+ else
+ {
+ if (CONSTANT_P (op0) && CONSTANT_P (op1))
+ {
+ op0 = ensure_extended (op0, extop, test_mode);
+ op1 = ensure_extended (op1, extop, test_mode);
+ }
+ else if (extop == ZERO_EXTEND && test_mode == HImode)
+ {
+ /* Pyramids have no unsigned "cmphi" instructions. We need to
+ zero extend unsigned halfwords into temporary registers. */
+ op0 = ensure_extended (op0, extop, test_mode);
+ op1 = ensure_extended (op1, extop, test_mode);
+ }
+ else if (CONSTANT_P (op0))
+ {
+ op0 = ensure_extended (op0, extop, test_mode);
+ op1 = ensure_extended (op1, extop, test_mode);
+ }
+ else if (CONSTANT_P (op1))
+ {
+ op1 = ensure_extended (op1, extop, test_mode);
+ op0 = ensure_extended (op0, extop, test_mode);
+ }
+ else if ((code0 == REG || code0 == SUBREG)
+ && (code1 == REG || code1 == SUBREG))
+ {
+ /* I could do this case without extension, by using the virtual
+ register address (but that would lose for global regs). */
+ op0 = ensure_extended (op0, extop, test_mode);
+ op1 = ensure_extended (op1, extop, test_mode);
+ }
+ else if (code0 == MEM && code1 == MEM)
+ {
+ /* Load into a reg if the address combination can't be handled
+ directly. */
+ if (! weird_memory_memory (op0, op1))
+ op0 = force_reg (test_mode, op0);
+ }
+
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, VOIDmode, op0, op1)));
+ }
+}
+
+/* Return non-zero if the two single-word moves with operands[0]
+ and operands[1] for the first single-word move, and operands[2]
+ and operands[3] for the second single-word move, is possible to
+ combine to a double word move.
+
+ The criterion is whether the operands are in consecutive memory cells,
+ registers, etc. */
+
+int
+movdi_possible (operands)
+ rtx operands[];
+{
+ int cnst_diff0, cnst_diff1;
+ RTX_CODE code0 = GET_CODE (operands[0]);
+ RTX_CODE code1 = GET_CODE (operands[1]);
+
+ /* Don't dare to combine (possibly overlapping) memory -> memory moves. */
+ /* It would be possible to detect the cases where we dare, by using
+ constant_diff (operands[0], operands[1])!!! */
+ if (code0 == MEM && code1 == MEM)
+ return 0;
+
+ cnst_diff0 = consecutive_operands (operands[0], operands[2]);
+ if (cnst_diff0 == 0)
+ return 0;
+
+ cnst_diff1 = consecutive_operands (operands[1], operands[3]);
+ if (cnst_diff1 == 0)
+ return 0;
+
+ if (cnst_diff0 & cnst_diff1)
+ {
+ /* The source and destination operands are consecutive. */
+
+ /* If the first move writes into the source of the second move,
+ we cannot combine. */
+ if ((code0 == REG
+ && reg_overlap_mentioned_p (operands[0], operands[3]))
+ || (code0 == SUBREG
+ && subreg_overlap_mentioned_p (operands[0], operands[3])))
+ return 0;
+
+ if (cnst_diff0 & 1)
+ /* operands[0],[1] has higher addresses than operands[2],[3]. */
+ swap_operands = 0;
+ else
+ /* operands[0],[1] has lower addresses than operands[2],[3]. */
+ swap_operands = 1;
+ return 1;
+ }
+ return 0;
+}
+
+/* Like reg_overlap_mentioned_p, but accepts a subreg rtx instead
+ of a reg. */
+
+int
+subreg_overlap_mentioned_p (subreg, x)
+ rtx subreg, x;
+{
+ rtx reg = SUBREG_REG (subreg);
+ int regno = REGNO (reg) + SUBREG_WORD (subreg);
+ int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (subreg));
+ return refers_to_regno_p (regno, endregno, x, 0);
+}
+
+/* Return 1 if OP0 is a consecutive operand to OP1, 2 if OP1 is a
+ consecutive operand to OP0.
+
+ This function is used to determine if addresses are consecutive,
+ and therefore possible to combine to fewer instructions. */
+
+int
+consecutive_operands (op0, op1)
+ rtx op0, op1;
+{
+ RTX_CODE code0, code1;
+ int cnst_diff;
+ int regno_off0, regno_off1;
+
+ code0 = GET_CODE (op0);
+ code1 = GET_CODE (op1);
+
+ regno_off0 = 0;
+ if (code0 == SUBREG)
+ {
+ if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))) <= UNITS_PER_WORD)
+ return 0;
+ regno_off0 = SUBREG_WORD (op0);
+ op0 = SUBREG_REG (op0);
+ code0 = REG;
+ }
+
+ regno_off1 = 0;
+ if (code1 == SUBREG)
+ {
+ if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))) <= UNITS_PER_WORD)
+ return 0;
+ regno_off1 = SUBREG_WORD (op1);
+ op1 = SUBREG_REG (op1);
+ code1 = REG;
+ }
+
+ if (code0 != code1)
+ return 0;
+
+ switch (code0)
+ {
+ case CONST_INT:
+ /* Cannot permit any symbolic constants, even if the consecutive
+ operand is 0, since a movl really performs sign extension. */
+ if (code1 != CONST_INT)
+ return 0;
+ if ((INTVAL (op0) == 0 && INTVAL (op1) == 0)
+ || (INTVAL (op0) == -1 && INTVAL (op1) == -1))
+ return 3;
+ if ((INTVAL (op0) == 0 && INTVAL (op1) > 0)
+ || (INTVAL (op0) == -1 && INTVAL (op1) < 0))
+ return 2;
+ if ((INTVAL (op1) == 0 && INTVAL (op0) > 0)
+ || (INTVAL (op1) == -1 && INTVAL (op0) < 0))
+ return 1;
+ break;
+
+ case REG:
+ regno_off0 = REGNO (op0) + regno_off0;
+ regno_off1 = REGNO (op1) + regno_off1;
+
+ cnst_diff = regno_off0 - regno_off1;
+ if (cnst_diff == 1)
+ {
+ /* movl with the highest numbered parameter (local) register as
+ source or destination, doesn't wrap to the lowest numbered local
+ (temporary) register. */
+
+ if (regno_off0 % 16 != 0)
+ return 1;
+ else
+ return 0;
+ }
+ else if (cnst_diff == -1)
+ {
+ if (regno_off1 % 16 != 0)
+ return 2;
+ else
+ return 0;
+ }
+ break;
+
+ case MEM:
+ op0 = XEXP (op0, 0);
+ op1 = XEXP (op1, 0);
+ if (GET_CODE (op0) == CONST)
+ op0 = XEXP (op0, 0);
+ if (GET_CODE (op1) == CONST)
+ op1 = XEXP (op1, 0);
+
+ cnst_diff = constant_diff (op0, op1);
+ if (cnst_diff)
+ {
+ if (cnst_diff == 4)
+ return 1;
+ else if (cnst_diff == -4)
+ return 2;
+ }
+ break;
+ }
+ return 0;
+}
+
+/* Return the constant difference of the rtx expressions OP0 and OP1,
+ or 0 if they don't have a constant difference.
+
+ This function is used to determine if addresses are consecutive,
+ and therefore possible to combine to fewer instructions. */
+
+int
+constant_diff (op0, op1)
+ rtx op0, op1;
+{
+ RTX_CODE code0, code1;
+ int cnst_diff;
+
+ code0 = GET_CODE (op0);
+ code1 = GET_CODE (op1);
+
+ if (code0 != code1)
+ {
+ if (code0 == PLUS)
+ {
+ if (GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && rtx_equal_p (op1, XEXP (op0, 0)))
+ return INTVAL (XEXP (op0, 1));
+ }
+ else if (code1 == PLUS)
+ {
+ if (GET_CODE (XEXP (op1, 1)) == CONST_INT
+ && rtx_equal_p (op0, XEXP (op1, 0)))
+ return -INTVAL (XEXP (op1, 1));
+ }
+ return 0;
+ }
+
+ if (code0 == CONST_INT)
+ return INTVAL (op0) - INTVAL (op1);
+
+ if (code0 == PLUS)
+ {
+ cnst_diff = constant_diff (XEXP (op0, 0), XEXP (op1, 0));
+ if (cnst_diff)
+ return (rtx_equal_p (XEXP (op0, 1), XEXP (op1, 1)))
+ ? cnst_diff : 0;
+ cnst_diff = constant_diff (XEXP (op0, 1), XEXP (op1, 1));
+ if (cnst_diff)
+ return (rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0)))
+ ? cnst_diff : 0;
+ }
+
+ return 0;
+}
+
+int
+already_sign_extended (insn, from_mode, op)
+ rtx insn;
+ enum machine_mode from_mode;
+ rtx op;
+{
+ rtx xinsn, xdest, xsrc;
+
+ for (;;)
+ {
+ insn = PREV_INSN (insn);
+ if (insn == 0)
+ return 0;
+ if (GET_CODE (insn) == NOTE || GET_CODE (insn) == JUMP_INSN)
+ continue;
+ if (GET_CODE (insn) == CALL_INSN && ! call_used_regs[REGNO (op)])
+ continue;
+ if (GET_CODE (insn) != INSN)
+ return 0;
+ xinsn = PATTERN (insn);
+
+ if (GET_CODE (xinsn) != SET)
+ return 0;
+
+ xdest = SET_DEST (xinsn);
+ xsrc = SET_SRC (xinsn);
+
+ if (GET_CODE (xdest) == SUBREG)
+ abort ();
+
+ if ( ! REG_P (xdest))
+ continue;
+
+ if (REGNO (op) == REGNO (xdest)
+ && ((GET_CODE (xsrc) == SIGN_EXTEND
+ && GET_MODE (XEXP (xsrc, 0)) == from_mode)
+ || (GET_CODE (xsrc) == MEM
+ && GET_MODE (xsrc) == from_mode)))
+ return 1;
+
+ /* The register is modified by another operation. */
+ if (reg_overlap_mentioned_p (xdest, op))
+ return 0;
+ }
+}
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT)
+ {
+ /* In an integer, the low-order word is in CONST_DOUBLE_LOW. */
+ rtx const_op = operands[1];
+ if ((CONST_DOUBLE_HIGH (const_op) == 0
+ && CONST_DOUBLE_LOW (const_op) >= 0)
+ || (CONST_DOUBLE_HIGH (const_op) == -1
+ && CONST_DOUBLE_LOW (const_op) < 0))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (const_op));
+ return "movl %1,%0";
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (const_op));
+ output_asm_insn ("movw %1,%0", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (const_op));
+ return "movw %1,%0";
+ }
+ else
+ {
+ /* In a real, the low-address word is in CONST_DOUBLE_LOW. */
+ rtx const_op = operands[1];
+ if ((CONST_DOUBLE_LOW (const_op) == 0
+ && CONST_DOUBLE_HIGH (const_op) >= 0)
+ || (CONST_DOUBLE_LOW (const_op) == -1
+ && CONST_DOUBLE_HIGH (const_op) < 0))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (const_op));
+ return "movl %1,%0";
+ }
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (const_op));
+ output_asm_insn ("movw %1,%0", operands);
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (const_op));
+ return "movw %1,%0";
+ }
+ }
+
+ return "movl %1,%0";
+}
+
+/* Output a shift insns, after having reduced integer arguments to
+ avoid as warnings. */
+
+char *
+output_shift (pattern, op2, mod)
+ char *pattern;
+ rtx op2;
+ int mod;
+{
+ if (GET_CODE (op2) == CONST_INT)
+ {
+ int cnt = INTVAL (op2) % mod;
+ if (cnt == 0)
+ {
+ cc_status = cc_prev_status;
+ return "";
+ }
+ op2 = gen_rtx (CONST_INT, VOIDmode, cnt);
+ }
+ return pattern;
+}
+
+/* Return non-zero if the code of this rtx pattern is a relop. */
+
+int
+relop (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case EQ:
+ case NE:
+ case LT:
+ case LE:
+ case GE:
+ case GT:
+ case LTU:
+ case LEU:
+ case GEU:
+ case GTU:
+ return 1;
+ }
+ return 0;
+}
+
+void
+notice_update_cc (EXP, INSN)
+ rtx EXP, INSN;
+{
+ switch (GET_CODE (EXP))
+ {
+ case SET:
+ switch (GET_CODE (SET_DEST (EXP)))
+ {
+ case CC0:
+ cc_status.mdep = 0;
+ cc_status.flags = 0;
+ cc_status.value1 = 0;
+ cc_status.value2 = SET_SRC (EXP);
+ break;
+
+ case PC:
+ break;
+
+ case REG:
+ switch (GET_CODE (SET_SRC (EXP)))
+ {
+ case CALL:
+ goto call;
+ case MEM:
+ if (GET_MODE (SET_SRC (EXP)) == QImode
+ || GET_MODE (SET_SRC (EXP)) == HImode)
+ {
+ cc_status.mdep = 0;
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (EXP);
+ cc_status.value2 = SET_SRC (EXP);
+ break;
+ }
+ /* else: Fall through. */
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ case CONST_DOUBLE:
+ case REG:
+ if (cc_status.value1
+ && reg_overlap_mentioned_p (SET_DEST (EXP),
+ cc_status.value1))
+ cc_status.value1 = 0;
+ if (cc_status.value2
+ && reg_overlap_mentioned_p (SET_DEST (EXP),
+ cc_status.value2))
+ cc_status.value2 = 0;
+ break;
+
+ case UDIV:
+ case UMOD:
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (EXP);
+ cc_status.value2 = SET_SRC (EXP);
+ break;
+ default:
+ cc_status.mdep = 0;
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (EXP);
+ cc_status.value2 = SET_SRC (EXP);
+ break;
+ }
+ break;
+
+ case MEM:
+ switch (GET_CODE (SET_SRC (EXP)))
+ {
+ case REG:
+ if (GET_MODE (SET_SRC (EXP)) == QImode
+ || GET_MODE (SET_SRC (EXP)) == HImode)
+ {
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (EXP);
+ cc_status.value2 = SET_SRC (EXP);
+ cc_status.mdep = 0;
+ break;
+ }
+ /* else: Fall through. */
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ case CONST_DOUBLE:
+ case MEM:
+ /* Need to forget cc_status about memory positions each
+ time a memory store is made, even if the memory store
+ insns in question doesn't modify the condition codes. */
+ if (cc_status.value1 &&
+ GET_CODE (cc_status.value1) == MEM)
+ cc_status.value1 = 0;
+ if (cc_status.value2 &&
+ GET_CODE (cc_status.value2) == MEM)
+ cc_status.value2 = 0;
+ break;
+ case SIGN_EXTEND:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case FLOAT:
+ case FIX:
+ cc_status.flags = CC_NO_OVERFLOW;
+ cc_status.value1 = SET_DEST (EXP);
+ cc_status.value2 = SET_SRC (EXP);
+ cc_status.mdep = 0;
+ break;
+
+ default:
+ abort ();
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ break;
+
+ case CALL:
+ call:
+ CC_STATUS_INIT;
+ break;
+ /* Do calls preserve the condition codes? (At least forget
+ cc_status expressions if they refer to registers
+ not preserved across calls. Also forget expressions
+ about memory contents.) */
+ if (cc_status.value1
+ && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
+ cc_status.value1, 0)
+ || GET_CODE (cc_status.value1) == MEM))
+ cc_status.value1 = 0;
+ if (cc_status.value2
+ && (refers_to_regno_p (PYR_TREG (0), PYR_TREG (15),
+ cc_status.value2, 0)
+ || GET_CODE (cc_status.value2) == MEM))
+ cc_status.value2 = 0;
+ break;
+
+ default:
+ CC_STATUS_INIT;
+ }
+}
+
+void
+forget_cc_if_dependent (op)
+ rtx op;
+{
+ cc_status = cc_prev_status;
+ if (cc_status.value1 && reg_overlap_mentioned_p (op, cc_status.value1))
+ cc_status.value1 = 0;
+ if (cc_status.value2 && reg_overlap_mentioned_p (op, cc_status.value2))
+ cc_status.value2 = 0;
+}
diff --git a/gcc-1.40/config/out-sparc.c b/gcc-1.40/config/out-sparc.c
new file mode 100644
index 0000000..d180b1f
--- /dev/null
+++ b/gcc-1.40/config/out-sparc.c
@@ -0,0 +1,2092 @@
+/* Subroutines for insn-output.c for Sun SPARC.
+ Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Global variables for machine-dependend things. */
+
+/* This should go away if we pass floats to regs via
+ the stack instead of the frame, and if we learn how
+ to renumber all the registers when we don't do a save (hard!). */
+extern int frame_pointer_needed;
+
+static rtx find_addr_reg ();
+
+rtx next_real_insn_no_labels ();
+
+/* Return non-zero only if OP is a register of mode MODE,
+ or const0_rtx. */
+int
+reg_or_0_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (op == const0_rtx || register_operand (op, mode));
+}
+
+/* Return non-zero if INSN is a conditional insn with a predicate
+ valid after an addcc or subcc instruction. */
+
+int
+ignore_overflow_conditional_p (insn)
+ rtx insn;
+{
+ rtx x = SET_SRC (PATTERN (insn));
+ RTX_CODE code;
+ if (GET_CODE (x) == IF_THEN_ELSE)
+ x = XEXP (x, 0);
+ code = GET_CODE (x);
+ return code == EQ || code == NE || code == GE || code == LT;
+}
+
+/* Return non-zero if this pattern, can be evaluated safely, even if it
+ was not asked for. */
+int
+safe_insn_src_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* Just experimenting. */
+
+ /* No floating point src is safe if it contains an arithmetic
+ operation, since that operation may trap. */
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ return 1;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return CONSTANT_ADDRESS_P (XEXP (op, 0));
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != SFmode && mode != DFmode);
+ case NOT:
+ return 1;
+
+ case COMPARE:
+ case MINUS:
+ case PLUS:
+ return (mode != SFmode && mode != DFmode);
+ case AND:
+ case IOR:
+ case XOR:
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
+ || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
+ return 0;
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return 1 if REG is clobbered in IN.
+ Return 0 if REG is used in IN (other than being clobbered).
+ Return 2 if REG does not appear in IN. */
+
+static int
+reg_clobbered_p (reg, in)
+ rtx reg;
+ rtx in;
+{
+ register char *fmt;
+ register int i, result = 0;
+
+ register enum rtx_code code;
+
+ if (in == 0)
+ return 2;
+
+ code = GET_CODE (in);
+
+ switch (code)
+ {
+ /* Let these fail out quickly. */
+ case CONST_INT:
+ case SYMBOL_REF:
+ case CONST:
+ return 2;
+
+ case SUBREG:
+ if (SUBREG_WORD (in) != 0)
+ in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+ else
+ in = SUBREG_REG (in);
+
+ case REG:
+ if (in == reg
+ || refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ in, 0))
+ return 0;
+ return 2;
+
+ case SET:
+ if (SET_SRC (in) == reg
+ || refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ SET_SRC (in), 0))
+ return 0;
+
+ if (SET_DEST (in) == reg)
+ return 1;
+
+ if (refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ SET_DEST (in), 0))
+ if (GET_CODE (SET_DEST (in)) == REG
+ || GET_CODE (SET_DEST (in)) == SUBREG)
+ return 1;
+ else
+ return 0;
+ return 2;
+
+ case USE:
+ if (XEXP (in, 0) == reg
+ || refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ XEXP (in, 0), 0))
+ return 0;
+ return 2;
+
+ case CLOBBER:
+ if (XEXP (in, 0) == reg)
+ return 1;
+ /* If the CLOBBER expression is a SUBREG, accept that as a
+ clobber. But if it is some expression based on this register,
+ that is like a USE as far as this register is concerned,
+ so we won't take it. */
+ if (refers_to_regno_p (REGNO (reg),
+ REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
+ XEXP (in, 0), 0))
+ if (GET_CODE (XEXP (in, 0)) == REG
+ || GET_CODE (XEXP (in, 0)) == SUBREG)
+ return 1;
+ else
+ return 0;
+ return 2;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+
+ result = 2;
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+ for (j = XVECLEN (in, i) - 1; j >= 0; j--)
+ switch (reg_clobbered_p (reg, XVECEXP (in, i, j)))
+ {
+ case 0:
+ return 0;
+ case 2:
+ continue;
+ case 1:
+ result = 1;
+ break;
+ }
+ }
+ else if (fmt[i] == 'e')
+ switch (reg_clobbered_p (reg, XEXP (in, i)))
+ {
+ case 0:
+ return 0;
+ case 2:
+ continue;
+ case 1:
+ result = 1;
+ break;
+ }
+ }
+ return result;
+}
+
+/* Return non-zero if OP can be written to without screwing up
+ GCC's model of what's going on. It is assumed that this operand
+ appears in the dest position of a SET insn in a conditional
+ branch's delay slot. AFTER is the label to start looking from. */
+int
+operand_clobbered_before_used_after (op, after)
+ rtx op;
+ rtx after;
+{
+ extern char call_used_regs[];
+
+ /* Just experimenting. */
+ if (GET_CODE (op) == CC0)
+ return 1;
+ if (GET_CODE (op) == REG)
+ {
+ rtx insn;
+
+ if (op == stack_pointer_rtx)
+ return 0;
+
+ for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == NOTE)
+ continue;
+ if (GET_CODE (insn) == INSN
+ || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ switch (reg_clobbered_p (op, PATTERN (insn)))
+ {
+ case 0:
+ return 0;
+ case 2:
+ break;
+ case 1:
+ return 1;
+ }
+ if (dead_or_set_p (insn, op))
+ return 1;
+ }
+ else if (GET_CODE (insn) == CODE_LABEL)
+ return 0;
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ if (condjump_p (insn))
+ return 0;
+ /* This is a jump insn which has already
+ been mangled. We can't tell what it does. */
+ if (GET_CODE (PATTERN (insn)) == PARALLEL)
+ return 0;
+ if (! JUMP_LABEL (insn))
+ return 0;
+ /* Keep following jumps. */
+ insn = JUMP_LABEL (insn);
+ }
+ }
+ return 1;
+ }
+
+ /* In both of these cases, the first insn executed
+ for this op will be a sethi %hi(whatever),%g1,
+ which is tolerable. */
+ if (GET_CODE (op) == MEM)
+ return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
+
+ return 0;
+}
+
+/* Return non-zero if this pattern, as a source to a "SET",
+ is known to yield an instruction of unit size. */
+int
+single_insn_src_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+#if 1
+ /* This is not always a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ return 1;
+#else
+ if (SMALL_INT (op))
+ return 1;
+ /* We can put this set insn into delay slot, because this is one
+ insn; 'sethi'. */
+ if ((INTVAL (op) & 0x3ff) == 0)
+ return 1;
+
+ /* This is not a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ return 1;
+#endif
+
+#if 1
+ case SYMBOL_REF:
+ /* This is not a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ return 1;
+#else
+ return 0;
+#endif
+
+ case REG:
+ return 1;
+
+ case MEM:
+#if 0
+ /* This is not a single insn src, technically,
+ but output_delayed_branch knows how to deal with it. */
+ if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
+ return 0;
+#endif
+ return 1;
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != DFmode);
+ case NOT:
+ return 1;
+
+ case COMPARE:
+ case MINUS:
+ /* If the target is cc0, then these insns will take
+ two insns (one being a nop). */
+ return (mode != SFmode && mode != DFmode);
+ case PLUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
+ || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
+ return 0;
+ return 1;
+
+ case SUBREG:
+ if (SUBREG_WORD (op) != 0)
+ return 0;
+ return single_insn_src_p (SUBREG_REG (op), mode);
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ /* Lazy... could check for more cases. */
+ if (GET_CODE (XEXP (op, 0)) == MEM
+ && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
+ return 1;
+ return 0;
+
+ /* Not doing floating point, since they probably
+ take longer than the branch slot they might fill. */
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case FLOAT:
+ case FIX:
+ case UNSIGNED_FLOAT:
+ case UNSIGNED_FIX:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/* This extra test must be done to verify that a move insn
+ really is just one assembler insn. */
+
+int
+single_insn_extra_test (dest, src)
+ rtx dest, src;
+{
+ /* Moves between FP regs and CPU regs are two insns. */
+ return (!(GET_CODE (src) == REG
+ && GET_CODE (dest) == REG
+ && (FP_REG_P (src) != FP_REG_P (dest))));
+}
+
+/* Nonzero only if this *really* is a single insn operand. */
+int
+strict_single_insn_op_p (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ switch (GET_CODE (op))
+ {
+ case CC0:
+ return 1;
+
+ case CONST_INT:
+ if (SMALL_INT (op))
+ return 1;
+ /* We can put this set insn into delay slot, because this is one
+ insn; 'sethi'. */
+ if ((INTVAL (op) & 0x3ff) == 0)
+ return 1;
+ return 0;
+
+ case SYMBOL_REF:
+ return 0;
+
+ case REG:
+ return (mode != DFmode && mode != DImode);
+
+ case MEM:
+ if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
+ return (mode != DFmode && mode != DImode);
+ return 0;
+
+ /* We never need to negate or complement constants. */
+ case NEG:
+ return (mode != DFmode);
+ case NOT:
+ return 1;
+
+ case COMPARE:
+ case MINUS:
+ /* If the target is cc0, then these insns will take
+ two insns (one being a nop). */
+ return (mode != SFmode && mode != DFmode);
+ case PLUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case LSHIFT:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
+ || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
+ return 0;
+ return 1;
+
+ case SUBREG:
+ if (SUBREG_WORD (op) != 0)
+ return 0;
+ return strict_single_insn_op_p (SUBREG_REG (op), mode);
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ if (GET_CODE (XEXP (op, 0)) == MEM
+ && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
+ return 1;
+ return 0;
+
+ /* Not doing floating point, since they probably
+ take longer than the branch slot they might fill. */
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case FLOAT:
+ case FIX:
+ case UNSIGNED_FLOAT:
+ case UNSIGNED_FIX:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return truth value of whether OP is a relational operator. */
+int
+relop (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case EQ:
+ case NE:
+ case GT:
+ case GE:
+ case LT:
+ case LE:
+ case GTU:
+ case GEU:
+ case LTU:
+ case LEU:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return truth value of wheterh OP is EQ or NE. */
+int
+eq_or_neq (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
+}
+
+/* Return truth value of whether OP can be used as an operands in a three
+ address arithmetic insn (such as add %o1,7,%l2) of mode MODE. */
+
+int
+arith_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
+}
+
+/* Return truth value of whether OP can be used as an operand in a two
+ address arithmetic insn (such as set 123456,%o4) of mode MODE. */
+
+int
+arith32_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
+}
+
+/* Return truth value of whether OP is a integer which fits the
+ range constraining immediate operands in three-address insns. */
+
+int
+small_int (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (operands[1]) != MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ return "st %1,[%%lo(%m0)+%%g1]";
+ }
+ else
+ return "st %r1,%0";
+ else
+ {
+ rtx xoperands[2];
+
+ cc_status.flags &= ~CC_F0_IS_0;
+ xoperands[0] = gen_rtx (REG, SFmode, 32);
+ xoperands[1] = operands[1];
+ output_asm_insn (singlemove_string (xoperands), xoperands);
+ xoperands[1] = xoperands[0];
+ xoperands[0] = operands[0];
+ output_asm_insn (singlemove_string (xoperands), xoperands);
+ return "";
+ }
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return "ld [%%lo(%m1)+%%g1],%0";
+ }
+ return "ld %1,%0";
+ }
+ return "mov %1,%0";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If the first move would clobber the source of the second one,
+ do them in the other order.
+
+ RMS says "This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance."
+
+ but it happens on the sparc when loading parameter registers,
+ so I am going to define that circumstance, and make it work
+ as expected. */
+
+ /* Easy case: try moving both words at once. */
+ /* First check for moving between an even/odd register pair
+ and a memory location. */
+ if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
+ && (REGNO (operands[0]) & 1) == 0)
+ || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
+ && (REGNO (operands[1]) & 1) == 0))
+ {
+ rtx op1, op2;
+ rtx base = 0, offset = const0_rtx;
+
+ /* OP1 gets the register pair, and OP2 gets the memory address. */
+ if (optype0 == REGOP)
+ op1 = operands[0], op2 = XEXP (operands[1], 0);
+ else
+ op1 = operands[1], op2 = XEXP (operands[0], 0);
+
+ /* Now see if we can trust the address to be 8-byte aligned. */
+ /* Trust global variables. */
+ if (CONSTANT_ADDRESS_P (op2))
+ {
+ operands[0] = op1;
+ operands[1] = op2;
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == op2))
+ output_asm_insn ("sethi %%hi(%1),%%g1", operands);
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = op2;
+ if (op1 == operands[0])
+ return "ldd [%%lo(%1)+%%g1],%0";
+ else
+ return "std [%%lo(%1)+%%g1],%0";
+ }
+
+ if (GET_CODE (op2) == PLUS)
+ {
+ if (GET_CODE (XEXP (op2, 0)) == REG)
+ base = XEXP (op2, 0), offset = XEXP (op2, 1);
+ else if (GET_CODE (XEXP (op2, 1)) == REG)
+ base = XEXP (op2, 1), offset = XEXP (op2, 0);
+ }
+
+ /* Trust round enough offsets from the stack or frame pointer. */
+ if (base
+ && (REGNO (base) == FRAME_POINTER_REGNUM
+ || REGNO (base) == STACK_POINTER_REGNUM))
+ {
+ if (GET_CODE (offset) == CONST_INT
+ && (INTVAL (offset) & 0x7) == 0)
+ {
+ if (op1 == operands[0])
+ return "ldd %1,%0";
+ else
+ return "std %1,%0";
+ }
+ }
+ else
+ {
+ /* We know structs not on the stack are properly aligned.
+ Since a double asks for 8-byte alignment,
+ we know it must have got that if it is in a struct.
+ But a DImode need not be 8-byte aligned, because it could be a
+ struct containing two ints or pointers. */
+
+ /* Sun fucks us here. We cannot trust references
+ to doubles via varying addresses. It might be on the stack
+ even if we don't know that it is; and then it might not be
+ double-word aligned. */
+#if 0
+ if (GET_CODE (operands[1]) == MEM && GET_MODE (operands[1]) == DFmode
+ && MEM_IN_STRUCT_P (operands[1]))
+ return "ldd %1,%0";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_MODE (operands[0]) == DFmode
+ && MEM_IN_STRUCT_P (operands[0]))
+ return "std %1,%0";
+#endif
+ }
+ }
+
+ if (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1]))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("add %0,0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,0x4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("add %0,-0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,-0x4,%0", &addreg0);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+ else if (optype0 == REGOP && optype1 != REGOP
+ && reg_overlap_mentioned_p (operands[0], operands[1]))
+ {
+ /* Do the late half first. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+ /* Then clobber. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("add %0,0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,0x4,%0", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("add %0,-0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,-0x4,%0", &addreg1);
+
+ return "";
+}
+
+static char *
+output_fp_move_double (operands)
+ rtx *operands;
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ {
+ output_asm_insn ("fmovs %1,%0", operands);
+ operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
+ return "fmovs %1,%0";
+ }
+ if (GET_CODE (operands[1]) == REG)
+ {
+ if ((REGNO (operands[1]) & 1) == 0)
+ return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
+ else
+ {
+ rtx xoperands[3];
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
+ return "";
+ }
+ }
+ /* Use ldd if known to be aligned. */
+ if (GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && (((XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
+ || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
+ && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0)
+#if 0 /* An array in a structure that is a parm need not be aligned! */
+ /* Arrays are known to be aligned,
+ and reg+reg addresses are used (on this machine)
+ only for array accesses. */
+ || (REG_P (XEXP (XEXP (operands[1], 0), 0))
+ && REG_P (XEXP (XEXP (operands[1], 0), 1)))
+#endif
+ ))
+ return "ldd %1,%0";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return "ldd [%%lo(%m1)+%%g1],%0";
+ }
+ /* Otherwise use two ld insns. */
+ {
+ rtx xoperands[2];
+ output_asm_insn ("ld %1,%0", operands);
+ xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
+ REGNO (operands[0]) + 1);
+ if (GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && offsettable_address_p (1, GET_MODE (operands[1]),
+ XEXP (operands[1], 0)))
+ {
+ xoperands[1] = adj_offsettable_operand (operands[1], 4);
+ output_asm_insn ("ld %1,%0", xoperands);
+ }
+ else if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
+ {
+ rtx memref = operands[1];
+ rtx inc_reg = XEXP (XEXP (operands[1], 0), 0);
+ if (inc_reg == frame_pointer_rtx
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == REG
+ && XEXP (XEXP (operands[1], 0), 1) != frame_pointer_rtx)
+ inc_reg = XEXP (XEXP (operands[1], 0), 1);
+ if (inc_reg == frame_pointer_rtx)
+ {
+ output_asm_insn ("mov %%fp,%%g1", xoperands);
+ inc_reg = gen_rtx (REG, SImode, 1);
+ memref = gen_rtx (GET_CODE (operands[1]),
+ GET_MODE (operands[1]),
+ gen_rtx (PLUS, GET_MODE (XEXP (operands[1], 0)),
+ inc_reg,
+ XEXP (XEXP (operands[1], 0), 1)));
+ }
+ xoperands[1] = inc_reg;
+ output_asm_insn ("add 4,%1,%1", xoperands);
+ xoperands[1] = memref;
+ output_asm_insn ("ld %1,%0", xoperands);
+ xoperands[1] = inc_reg;
+ output_asm_insn ("add -4,%1,%1", xoperands);
+ }
+ else
+ {
+ xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
+ plus_constant (XEXP (operands[1], 0), 4));
+ output_asm_insn ("ld %1,%0", xoperands);
+ }
+ return "";
+ }
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == REG)
+ {
+ if ((REGNO (operands[0]) & 1) == 0)
+ return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
+ else
+ {
+ rtx xoperands[3];
+ xoperands[2] = operands[1];
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ xoperands[0] = operands[0];
+ output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
+ return "";
+ }
+ }
+ /* Use std if we can be sure it is well-aligned. */
+ if (GET_CODE (XEXP (operands[0], 0)) == PLUS
+ && (((XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
+ || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
+ && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
+ && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) == 0)
+#if 0 /* An array in a structure that is a parm need not be aligned! */
+ /* Arrays are known to be aligned,
+ and reg+reg addresses are used (on this machine)
+ only for array accesses. */
+ || (REG_P (XEXP (XEXP (operands[0], 0), 0))
+ && REG_P (XEXP (XEXP (operands[0], 0), 1)))
+#endif
+ ))
+ return "std %1,%0";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ return "std %1,[%%lo(%m0)+%%g1]";
+ }
+ /* Otherwise use two st insns. */
+ {
+ rtx xoperands[2];
+ output_asm_insn ("st %r1,%0", operands);
+ xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
+ REGNO (operands[1]) + 1);
+ if (GET_CODE (XEXP (operands[0], 0)) == PLUS
+ && offsettable_address_p (1, GET_MODE (operands[0]),
+ XEXP (operands[0], 0)))
+ {
+ xoperands[0] = adj_offsettable_operand (operands[0], 4);
+ output_asm_insn ("st %r1,%0", xoperands);
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PLUS)
+ {
+ rtx memref = operands[0];
+ rtx inc_reg = XEXP (XEXP (operands[0], 0), 0);
+ if (inc_reg == frame_pointer_rtx
+ && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG
+ && XEXP (XEXP (operands[0], 0), 1) != frame_pointer_rtx)
+ inc_reg = XEXP (XEXP (operands[0], 0), 1);
+ if (inc_reg == frame_pointer_rtx)
+ {
+ output_asm_insn ("mov %%fp,%%g1", xoperands);
+ inc_reg = gen_rtx (REG, SImode, 1);
+ memref = gen_rtx (GET_CODE (operands[0]),
+ GET_MODE (operands[0]),
+ gen_rtx (PLUS, GET_MODE (XEXP (operands[0], 0)),
+ inc_reg,
+ XEXP (XEXP (operands[0], 0), 1)));
+ }
+ xoperands[0] = inc_reg;
+ output_asm_insn ("add 4,%0,%0", xoperands);
+ xoperands[0] = memref;
+ output_asm_insn ("st %r1,%0", xoperands);
+ xoperands[0] = inc_reg;
+ output_asm_insn ("add -4,%0,%0", xoperands);
+ }
+ else
+ {
+ xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
+ plus_constant (XEXP (operands[0], 0), 4));
+ output_asm_insn ("st %r1,%0", xoperands);
+ }
+ return "";
+ }
+ }
+ else abort ();
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG
+ && !(GET_CODE (XEXP (addr, 1)) == REG
+ && XEXP (addr, 0) == frame_pointer_rtx))
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+void
+output_sized_memop (opname, mode)
+ char *opname;
+ enum machine_mode mode;
+{
+ extern struct _iobuf *asm_out_file;
+
+ static char *ld_size_suffix[] = { "ub", "uh", "", "?", "d" };
+ static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
+ char *modename
+ = (opname[0] == 'l' ? ld_size_suffix : st_size_suffix)[GET_MODE_SIZE (mode) >> 1];
+
+ fprintf (asm_out_file, "\t%s%s", opname, modename);
+}
+
+/* Output a store-in-memory whose operands are OPERANDS[0,1].
+ OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero. */
+
+char *
+output_store (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx address = XEXP (operands[0], 0);
+
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = address;
+
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && address == cc_prev_status.mdep))
+ {
+ output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
+ cc_prev_status.mdep = address;
+ }
+
+ /* Store zero in two parts when appropriate. */
+ if (mode == DFmode && operands[1] == dconst0_rtx)
+ {
+ /* We can't cross a page boundary here because the
+ SYMBOL_REF must be double word aligned, and for this
+ to be the case, SYMBOL_REF+4 cannot cross. */
+ output_sized_memop ("st", SImode);
+ output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands);
+ output_sized_memop ("st", SImode);
+ return "%r1,[%%g1+%%lo(%m0)+4]";
+ }
+
+ /* Code below isn't smart enough to move a doubleword in two parts,
+ so use output_move_double to do that in the cases that require it. */
+ if ((mode == DImode || mode == DFmode)
+ && (GET_CODE (operands[1]) == REG
+ && (REGNO (operands[1]) & 1)))
+ return output_move_double (operands);
+
+ output_sized_memop ("st", mode);
+ return "%r1,[%%g1+%%lo(%m0)]";
+}
+
+/* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1].
+ OPERANDS[0] is a reg, and OPERANDS[1] is a mem. */
+
+char *
+output_load_fixed (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx address = XEXP (operands[1], 0);
+
+ /* We don't bother trying to see if we know %hi(address).
+ This is because we are doing a load, and if we know the
+ %hi value, we probably also know that value in memory. */
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = address;
+
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && address == cc_prev_status.mdep
+ && cc_prev_status.mdep == cc_status.mdep))
+ {
+ output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
+ cc_prev_status.mdep = address;
+ }
+
+ /* Code below isn't smart enough to do a doubleword in two parts.
+ So handle that case the slow way. */
+ if (mode == DImode
+ && GET_CODE (operands[0]) == REG /* Moving to nonaligned reg pair */
+ && (REGNO (operands[0]) & 1))
+ return output_move_double (operands);
+
+ output_sized_memop ("ld", mode);
+ if (GET_CODE (operands[0]) == REG)
+ return "[%%g1+%%lo(%m1)],%0";
+ abort ();
+}
+
+/* Output a floating-point load-from-memory whose operands are OPERANDS[0,1].
+ OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
+ We also handle the case where OPERANDS[0] is a mem. */
+
+char *
+output_load_floating (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx address = XEXP (operands[1], 0);
+
+ /* We don't bother trying to see if we know %hi(address).
+ This is because we are doing a load, and if we know the
+ %hi value, we probably also know that value in memory. */
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = address;
+
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && address == cc_prev_status.mdep
+ && cc_prev_status.mdep == cc_status.mdep))
+ {
+ output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
+ cc_prev_status.mdep = address;
+ }
+
+ if (mode == DFmode)
+ {
+ if (REG_P (operands[0]))
+ {
+ if (REGNO (operands[0]) & 1)
+ return output_move_double (operands);
+ else
+ return "ldd [%%g1+%%lo(%m1)],%0";
+ }
+ cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0);
+ output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands);
+ operands[1] = gen_rtx (REG, DFmode, 32);
+ return output_fp_move_double (operands);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ cc_status.flags &= ~CC_F1_IS_0;
+ output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands);
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ cc_status.mdep = XEXP (operands[0], 0);
+ return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]";
+ }
+ else
+ return "st %%f1,%0";
+ }
+ return "ld [%%g1+%%lo(%m1)],%0";
+}
+
+/* Load the address specified by OPERANDS[3] into the register
+ specified by OPERANDS[0].
+
+ OPERANDS[3] may be the result of a sum, hence it could either be:
+
+ (1) CONST
+ (2) REG
+ (2) REG + CONST_INT
+ (3) REG + REG + CONST_INT
+ (4) REG + REG (special case of 3).
+
+ Note that (3) is not a legitimate address.
+ All cases are handled here. */
+
+void
+output_load_address (operands)
+ rtx *operands;
+{
+ rtx base, offset;
+
+ if (CONSTANT_P (operands[3]))
+ {
+ output_asm_insn ("set %3,%0", operands);
+ return;
+ }
+
+ if (REG_P (operands[3]))
+ {
+ if (REGNO (operands[0]) != REGNO (operands[3]))
+ output_asm_insn ("mov %3,%0", operands);
+ return;
+ }
+
+ if (GET_CODE (operands[3]) != PLUS)
+ abort ();
+
+ base = XEXP (operands[3], 0);
+ offset = XEXP (operands[3], 1);
+
+ if (GET_CODE (base) == CONST_INT)
+ {
+ rtx tmp = base;
+ base = offset;
+ offset = tmp;
+ }
+
+ if (GET_CODE (offset) != CONST_INT)
+ {
+ /* Operand is (PLUS (REG) (REG)). */
+ base = operands[3];
+ offset = const0_rtx;
+ }
+
+ if (REG_P (base))
+ {
+ operands[6] = base;
+ operands[7] = offset;
+ if (SMALL_INT (offset))
+ output_asm_insn ("add %6,%7,%0", operands);
+ else
+ output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
+ }
+ else if (GET_CODE (base) == PLUS)
+ {
+ operands[6] = XEXP (base, 0);
+ operands[7] = XEXP (base, 1);
+ operands[8] = offset;
+
+ if (SMALL_INT (offset))
+ output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
+ else
+ output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
+ }
+ else
+ abort ();
+}
+
+/* Output code to place a size count SIZE in register REG.
+ ALIGN is the size of the unit of transfer.
+
+ Because block moves are pipelined, we don't include the
+ first element in the transfer of SIZE to REG. */
+
+static void
+output_size_for_block_move (size, reg, align)
+ rtx size, reg;
+ rtx align;
+{
+ rtx xoperands[3];
+
+ xoperands[0] = reg;
+ xoperands[1] = size;
+ xoperands[2] = align;
+ if (GET_CODE (size) == REG)
+ output_asm_insn ("sub %1,%2,%0", xoperands);
+ else
+ {
+ xoperands[1]
+ = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
+ cc_status.flags &= ~ CC_KNOW_HI_G1;
+ output_asm_insn ("set %1,%0", xoperands);
+ }
+}
+
+/* Emit code to perform a block move.
+
+ OPERANDS[0] is the destination.
+ OPERANDS[1] is the source.
+ OPERANDS[2] is the size.
+ OPERANDS[3] is the alignment safe to use.
+ OPERANDS[4] is a register we can safely clobber as a temp. */
+
+char *
+output_block_move (operands)
+ rtx *operands;
+{
+ /* A vector for our computed operands. Note that load_output_address
+ makes use of (and can clobber) up to the 8th element of this vector. */
+ rtx xoperands[10];
+ rtx zoperands[10];
+ static int movstrsi_label = 0;
+ int i, j;
+ rtx temp1 = operands[4];
+ rtx alignrtx = operands[3];
+ int align = INTVAL (alignrtx);
+
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2] = temp1;
+
+ /* We can't move more than four bytes at a time
+ because we have only one register to move them through. */
+ if (align > 4)
+ {
+ align = 4;
+ alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
+ }
+
+ /* Since we clobber untold things, nix the condition codes. */
+ CC_STATUS_INIT;
+
+ /* Recognize special cases of block moves. These occur
+ when GNU C++ is forced to treat something as BLKmode
+ to keep it in memory, when its mode could be represented
+ with something smaller.
+
+ We cannot do this for global variables, since we don't know
+ what pages they don't cross. Sigh. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) <= 16
+ && ! CONSTANT_ADDRESS_P (operands[0])
+ && ! CONSTANT_ADDRESS_P (operands[1]))
+ {
+ int size = INTVAL (operands[2]);
+
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ if (align == 1)
+ {
+ if (memory_address_p (QImode, plus_constant (xoperands[0], size))
+ && memory_address_p (QImode, plus_constant (xoperands[1], size)))
+ {
+ /* We will store different integers into this particular RTX. */
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
+ for (i = size-1; i >= 0; i--)
+ {
+ INTVAL (xoperands[2]) = i;
+ output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ else if (align == 2)
+ {
+ if (memory_address_p (HImode, plus_constant (xoperands[0], size))
+ && memory_address_p (HImode, plus_constant (xoperands[1], size)))
+ {
+ /* We will store different integers into this particular RTX. */
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
+ for (i = (size>>1)-1; i >= 0; i--)
+ {
+ INTVAL (xoperands[2]) = i<<1;
+ output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ else
+ {
+ if (memory_address_p (SImode, plus_constant (xoperands[0], size))
+ && memory_address_p (SImode, plus_constant (xoperands[1], size)))
+ {
+ /* We will store different integers into this particular RTX. */
+ xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
+ for (i = (size>>2)-1; i >= 0; i--)
+ {
+ INTVAL (xoperands[2]) = i<<2;
+ output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
+ xoperands);
+ }
+ return "";
+ }
+ }
+ }
+
+ /* This is the size of the transfer.
+ Either use the register which already contains the size,
+ or use a free register (used by no operands).
+ Also emit code to decrement the size value by ALIGN. */
+ output_size_for_block_move (operands[2], temp1, alignrtx);
+
+ zoperands[0] = operands[0];
+ zoperands[3] = plus_constant (operands[0], align);
+ output_load_address (zoperands);
+
+ xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
+ xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
+
+#ifdef NO_UNDERSCORES
+ if (align == 1)
+ output_asm_insn ("\n.Lm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
+ else if (align == 2)
+ output_asm_insn ("\n.Lm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
+ else
+ output_asm_insn ("\n.Lm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tst %%g1,[%0+%2]", xoperands);
+#else
+ if (align == 1)
+ output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
+ else if (align == 2)
+ output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
+ else
+ output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]", xoperands);
+#endif
+ return "";
+}
+
+/* What the sparc lacks in hardware, make up for in software.
+ Compute a fairly good sequence of shift and add insns
+ to make a multiply happen. */
+
+#define ABS(x) ((x) < 0 ? -(x) : x)
+
+char *
+output_mul_by_constant (insn, operands, unsignedp)
+ rtx insn;
+ rtx *operands;
+ int unsignedp;
+{
+ int c; /* Size of constant */
+ int shifts[BITS_PER_WORD]; /* Table of shifts */
+ unsigned int p, log; /* A power of two, and its log */
+ int d1, d2; /* Differences of c and p */
+ int first = 1; /* True if dst has unknown data in it */
+ int i;
+
+ CC_STATUS_INIT;
+
+ c = INTVAL (operands[2]);
+ if (c == 0)
+ {
+ /* Does happen, at least when not optimizing. */
+ if (GET_CODE (operands[0]) == MEM)
+ return "st %%g0,%0";
+ return "mov %%g0,%0";
+ }
+
+ output_asm_insn ("! start open coded multiply");
+
+ /* Clear out the table of shifts. */
+ for (i = 0; i < BITS_PER_WORD; ++i)
+ shifts[i] = 0;
+
+ while (c)
+ {
+ /* Find the power of two nearest ABS(c) */
+ p = 1, log = 0;
+ do
+ {
+ d1 = ABS(c) - p;
+ p *= 2;
+ ++log;
+ }
+ while (p < ABS(c));
+ d2 = p - ABS(c);
+
+ /* Make an appropriate entry in shifts for p. */
+ if (d2 < d1)
+ {
+ shifts[log] = c < 0 ? -1 : 1;
+ c = c < 0 ? d2 : -d2;
+ }
+ else
+ {
+ shifts[log - 1] = c < 0 ? -1 : 1;
+ c = c < 0 ? -d1 : d1;
+ }
+ }
+
+ /* Take care of the first insn in sequence.
+ We know we have at least one. */
+
+ /* A value of -1 in shifts says to subtract that power of two, and a value
+ of 1 says to add that power of two. */
+ for (i = 0; ; i++)
+ if (shifts[i])
+ {
+ if (i)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
+ output_asm_insn ("sll %1,%2,%%g1", operands);
+ }
+ else output_asm_insn ("mov %1,%%g1", operands);
+
+ log = i;
+ if (shifts[i] < 0)
+ output_asm_insn ("sub %%g0,%%g1,%0", operands);
+ else
+ output_asm_insn ("mov %%g1,%0", operands);
+ break;
+ }
+
+ /* A value of -1 in shifts says to subtract that power of two, and a value
+ of 1 says to add that power of two--continued. */
+ for (i += 1; i < BITS_PER_WORD; ++i)
+ if (shifts[i])
+ {
+ if (i - log > 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
+ output_asm_insn ("sll %%g1,%2,%%g1", operands);
+ }
+ else
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
+ output_asm_insn ("sra %%g1,%2,%%g1", operands);
+ }
+ log = i;
+ if (shifts[i] < 0)
+ output_asm_insn ("sub %0,%%g1,%0", operands);
+ else
+ output_asm_insn ("add %0,%%g1,%0", operands);
+ }
+
+ output_asm_insn ("! end open coded multiply");
+
+ return "";
+}
+
+char *
+output_mul_insn (operands, unsignedp)
+ rtx *operands;
+ int unsignedp;
+{
+ int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
+ int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
+
+ CC_STATUS_INIT;
+
+ if (lucky1)
+ {
+ if (lucky2)
+ {
+ if (REGNO (operands[1]) == REGNO (operands[2]))
+ {
+ if (REGNO (operands[1]) == 8)
+ output_asm_insn ("mov %%o0,%%o1");
+ else
+ output_asm_insn ("mov %%o1,%%o0");
+ }
+ output_asm_insn ("call .mul,2\n\tnop", operands);
+ }
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (REG, SImode,
+ 8 ^ (REGNO (operands[1]) == 8));
+ xoperands[1] = operands[2];
+ output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
+ }
+ }
+ else if (lucky2)
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (REG, SImode,
+ 8 ^ (REGNO (operands[2]) == 8));
+ xoperands[1] = operands[1];
+ output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
+ }
+ else
+ {
+ output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
+ operands);
+ }
+
+ if (REGNO (operands[0]) == 8)
+ return "";
+ return "mov %%o0,%0";
+}
+
+/* Make floating point register f0 contain 0.
+ SIZE is the number of registers (including f0)
+ which should contain 0. */
+
+void
+make_f0_contain_0 (size)
+ int size;
+{
+ if (size == 1)
+ {
+ if ((cc_status.flags & (CC_F0_IS_0)) == 0)
+ output_asm_insn ("ld [%%fp-16],%%f0", 0);
+ cc_status.flags |= CC_F0_IS_0;
+ }
+ else if (size == 2)
+ {
+ if ((cc_status.flags & CC_F0_IS_0) == 0)
+ output_asm_insn ("ld [%%fp-16],%%f0", 0);
+ if ((cc_status.flags & (CC_F1_IS_0)) == 0)
+ output_asm_insn ("ld [%%fp-12],%%f1", 0);
+ cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;
+ }
+}
+
+/* Since condition codes don't have logical links, we need to keep
+ their setting and use together for set-cc insns. */
+void
+gen_scc_insn (code, mode, operands)
+ enum rtx_code code;
+ enum machine_mode mode;
+ rtx *operands;
+{
+ extern rtx sequence_stack;
+ rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);
+ rtx last_pat;
+
+ /* Skip back over the CLOBBERs that may precede this insn. */
+ while (last_insn && GET_CODE (last_insn) == INSN
+ && GET_CODE (PATTERN (last_insn)) == CLOBBER)
+ last_insn = PREV_INSN (last_insn);
+ /* We should have found the preceding compare. */
+ if (last_insn == 0 || GET_CODE (last_insn) != INSN)
+ abort ();
+ last_pat = PATTERN (last_insn);
+ if (GET_CODE (last_pat) != SET
+ || GET_CODE (SET_DEST (last_pat)) != CC0)
+ abort ();
+
+ /* Turn off that previous insn, now that we have got the data out of it. */
+ PUT_CODE (last_insn, NOTE);
+ NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;
+
+ /* Emit one replacement insn to compare operands and store result. */
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));
+}
+
+/* Output reasonable peephole for set-on-condition-code insns.
+ Note that these insns assume a particular way of defining
+ labels. Therefore, *both* tm-sparc.h and this function must
+ be changed if a new syntax is needed. */
+
+char *
+output_scc_insn (code, operand)
+ enum rtx_code code;
+ rtx operand;
+{
+ rtx xoperands[2];
+ rtx label = gen_label_rtx ();
+ int cc_in_fccr = cc_status.flags & CC_IN_FCCR;
+ int antisymmetric = 0;
+
+ xoperands[0] = operand;
+ xoperands[1] = label;
+
+ switch (code)
+ {
+ case NE:
+ if (cc_in_fccr)
+ output_asm_insn ("fbne,a %l0", &label);
+ else
+ output_asm_insn ("bne,a %l0", &label);
+ break;
+ case EQ:
+ if (cc_in_fccr)
+ output_asm_insn ("fbe,a %l0", &label);
+ else
+ output_asm_insn ("be,a %l0", &label);
+ break;
+ case GE:
+ if (cc_in_fccr)
+ output_asm_insn ("fbge,a %l0", &label);
+ else
+ output_asm_insn ("bge,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case GT:
+ if (cc_in_fccr)
+ output_asm_insn ("fbg,a %l0", &label);
+ else
+ output_asm_insn ("bg,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case LE:
+ if (cc_in_fccr)
+ output_asm_insn ("fble,a %l0", &label);
+ else
+ output_asm_insn ("ble,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case LT:
+ if (cc_in_fccr)
+ output_asm_insn ("fbl,a %l0", &label);
+ else
+ output_asm_insn ("bl,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case GEU:
+ if (cc_in_fccr)
+ abort ();
+ else
+ output_asm_insn ("bgeu,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case GTU:
+ if (cc_in_fccr)
+ abort ();
+ else
+ output_asm_insn ("bgu,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case LEU:
+ if (cc_in_fccr)
+ abort ();
+ else
+ output_asm_insn ("bleu,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ case LTU:
+ if (cc_in_fccr)
+ abort ();
+ else
+ output_asm_insn ("blu,a %l0", &label);
+ antisymmetric = 1;
+ break;
+ default:
+ abort ();
+ }
+
+ if (antisymmetric
+ && (cc_status.flags & CC_REVERSED))
+ output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);
+ else
+ output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);
+ cc_status.flags &= ~CC_IN_FCCR;
+
+ return "";
+}
+
+/* Output a delayed branch insn with the delay insn in its
+ branch slot. The delayed branch insn template is in TEMPLATE,
+ with operands OPERANDS. The insn in its delay slot is INSN.
+
+ As a special case, since we know that all memory transfers are via
+ ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
+ reference around the branch as
+
+ sethi %hi(x),%%g1
+ b ...
+ ld/st [%g1+%lo(x)],...
+
+ As another special case, we handle loading (SYMBOL_REF ...) and
+ other large constants around branches as well:
+
+ sethi %hi(x),%0
+ b ...
+ or %0,%lo(x),%1
+
+ */
+
+char *
+output_delayed_branch (template, operands, insn)
+ char *template;
+ rtx *operands;
+ rtx insn;
+{
+ extern rtx recog_operand[];
+ rtx src = XVECEXP (PATTERN (insn), 0, 1);
+ rtx dest = XVECEXP (PATTERN (insn), 0, 0);
+
+ if (GET_CODE (src) == SYMBOL_REF
+ || (GET_CODE (src) == CONST_INT
+ && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))
+ {
+ rtx xoperands[2];
+ xoperands[0] = dest;
+ xoperands[1] = src;
+
+ /* Output the `sethi' insn. */
+ output_asm_insn ("sethi %%hi(%1),%0", xoperands);
+
+ /* Output the branch instruction next. */
+ output_asm_insn (template, operands);
+
+ /* Now output the `or' insn. */
+ output_asm_insn ("or %0,%%lo(%1),%0", xoperands);
+ }
+ else if ((GET_CODE (src) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (src, 0)))
+ || (GET_CODE (dest) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
+ {
+ rtx xoperands[2];
+ char *split_template;
+ xoperands[0] = dest;
+ xoperands[1] = src;
+
+ /* Output the `sethi' insn. */
+ if (GET_CODE (src) == MEM)
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[1], 0)))
+ output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);
+ split_template = "ld [%%g1+%%lo(%m1)],%0";
+ }
+ else
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && cc_prev_status.mdep == XEXP (operands[0], 0)))
+ output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);
+ split_template = "st %r1,[%%g1+%%lo(%m0)]";
+ }
+
+ /* Output the branch instruction next. */
+ output_asm_insn (template, operands);
+
+ /* Now output the load or store.
+ No need to do a CC_STATUS_INIT, because we are branching anyway. */
+ output_asm_insn (split_template, xoperands);
+ }
+ else
+ {
+ extern char *insn_template[];
+ extern char *(*insn_outfun[])();
+ int insn_code_number;
+ rtx pat = gen_rtx (SET, VOIDmode, dest, src);
+ rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
+ int i;
+ extern rtx alter_subreg();
+ extern int insn_n_operands[];
+
+ /* Output the branch instruction first. */
+ output_asm_insn (template, operands);
+
+ /* Now recognize the insn which we put in its delay slot.
+ We must do this after outputing the branch insn,
+ since operands may just be a pointer to `recog_operand'. */
+ insn_code_number = recog (pat, delay_insn);
+ if (insn_code_number == -1)
+ abort ();
+
+ for (i = 0; i < insn_n_operands[insn_code_number]; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ }
+
+ /* Now get the template for what this insn would
+ have been, without the branch. Its operands are
+ exactly the same as they would be, so we don't
+ need to do an insn_extract. */
+ template = insn_template[insn_code_number];
+ if (template == 0)
+ template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
+ output_asm_insn (template, recog_operand);
+ }
+ CC_STATUS_INIT;
+ return "";
+}
+
+/* Output a newly constructed insn DELAY_INSN. */
+char *
+output_delay_insn (delay_insn)
+ rtx delay_insn;
+{
+ char *template;
+ extern rtx recog_operand[];
+ extern char call_used_regs[];
+ extern char *insn_template[];
+ extern int insn_n_operands[];
+ extern char *(*insn_outfun[])();
+ extern rtx alter_subreg();
+ int insn_code_number;
+ extern int insn_n_operands[];
+ int i;
+
+ /* Now recognize the insn which we put in its delay slot.
+ We must do this after outputing the branch insn,
+ since operands may just be a pointer to `recog_operand'. */
+ insn_code_number = recog_memoized (delay_insn);
+ if (insn_code_number == -1)
+ abort ();
+
+ /* Extract the operands of this delay insn. */
+ INSN_CODE (delay_insn) = insn_code_number;
+ insn_extract (delay_insn);
+
+ /* It is possible that this insn has not been properly scaned by final
+ yet. If this insn's operands don't appear in the peephole's
+ actual operands, then they won't be fixed up by final, so we
+ make sure they get fixed up here. -- This is a kludge. */
+ for (i = 0; i < insn_n_operands[insn_code_number]; i++)
+ {
+ if (GET_CODE (recog_operand[i]) == SUBREG)
+ recog_operand[i] = alter_subreg (recog_operand[i]);
+ }
+
+#ifdef REGISTER_CONSTRAINTS
+ if (! constrain_operands (insn_code_number))
+ abort ();
+#endif
+
+ cc_prev_status = cc_status;
+
+ /* Update `cc_status' for this instruction.
+ The instruction's output routine may change it further.
+ If the output routine for a jump insn needs to depend
+ on the cc status, it should look at cc_prev_status. */
+
+ NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
+
+ /* Now get the template for what this insn would
+ have been, without the branch. */
+
+ template = insn_template[insn_code_number];
+ if (template == 0)
+ template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
+ output_asm_insn (template, recog_operand);
+ return "";
+}
+
+/* Output the insn HEAD, keeping OPERANDS protected (wherever they are).
+ HEAD comes from the target of some branch, so before we output it,
+ we delete it from the target, lest we execute it twice. The caller
+ of this function promises that such code motion is permissable. */
+char *
+output_eager_then_insn (head, operands)
+ rtx head;
+ rtx *operands;
+{
+ extern rtx alter_subreg ();
+ extern int insn_n_operands[];
+ extern rtx recog_operand[];
+ rtx xoperands[MAX_RECOG_OPERANDS];
+ int insn_code_number, i, nbytes;
+ rtx nhead;
+
+ /* Micro-hack: run peephole on head if it looks like a good idea.
+ Right now there's only one such case worth doing...
+
+ This could be made smarter if the peephole for ``2-insn combine''
+ were also made smarter. */
+ if (GET_CODE (PATTERN (head)) == SET
+ && REG_P (SET_SRC (PATTERN (head)))
+ && REG_P (SET_DEST (PATTERN (head)))
+ && (nhead = next_real_insn_no_labels (head))
+ && GET_CODE (nhead) == INSN
+ && GET_CODE (PATTERN (nhead)) == SET
+ && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0
+ && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))
+ || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))
+ /* Something's wrong if this does not fly. */
+ if (! peephole (head))
+ abort ();
+
+ /* Save our contents of `operands', since output_delay_insn sets them. */
+ insn_code_number = recog_memoized (head);
+ nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);
+ bcopy (operands, xoperands, nbytes);
+
+ /* Output the delay insn, and prevent duplication later. */
+ delete_insn (head);
+ output_delay_insn (head);
+
+ /* Restore this insn's operands. */
+ bcopy (xoperands, operands, nbytes);
+}
+
+/* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
+ or 0, if there is none. Also return 0 if we cross a label. */
+
+rtx
+next_real_insn_no_labels (label)
+ rtx label;
+{
+ register rtx insn = NEXT_INSN (label);
+ register RTX_CODE code;
+
+ while (insn)
+ {
+ code = GET_CODE (insn);
+ if (code == INSN)
+ {
+ if (GET_CODE (PATTERN (insn)) != CLOBBER
+ && GET_CODE (PATTERN (insn)) != USE)
+ return insn;
+ }
+ if (code == CALL_INSN || code == JUMP_INSN)
+ return insn;
+ if (code == CODE_LABEL)
+ return 0;
+ insn = NEXT_INSN (insn);
+ }
+
+ return 0;
+}
+
+int
+operands_satisfy_eager_branch_peephole (operands, conditional)
+ rtx *operands;
+ int conditional;
+{
+ rtx label;
+
+ if (conditional)
+ {
+ if (GET_CODE (operands[0]) != IF_THEN_ELSE)
+ return 0;
+
+ if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)
+ label = XEXP (XEXP (operands[0], 1), 0);
+ else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)
+ label = XEXP (XEXP (operands[0], 2), 0);
+ else return 0;
+ }
+ else
+ {
+ label = operands[0];
+ }
+
+ if (LABEL_NUSES (label) == 1)
+ {
+ rtx prev = PREV_INSN (label);
+ while (prev && GET_CODE (prev) == NOTE)
+ prev = PREV_INSN (prev);
+ if (prev == 0
+ || GET_CODE (prev) == BARRIER)
+ {
+ rtx head = next_real_insn_no_labels (label);
+
+ if (head
+ && ! INSN_DELETED_P (head)
+ && GET_CODE (head) == INSN
+ && GET_CODE (PATTERN (head)) == SET
+ && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
+ GET_MODE (SET_DEST (PATTERN (head))))
+ && strict_single_insn_op_p (SET_DEST (PATTERN (head)),
+ GET_MODE (SET_DEST (PATTERN (head))))
+ /* Moves between FP regs and CPU regs are two insns. */
+ && !(GET_CODE (SET_SRC (PATTERN (head))) == REG
+ && GET_CODE (SET_DEST (PATTERN (head))) == REG
+ && (FP_REG_P (SET_SRC (PATTERN (head)))
+ != FP_REG_P (SET_DEST (PATTERN (head))))))
+ {
+ if (conditional == 2)
+ return (GET_CODE (operands[1]) != PC
+ && safe_insn_src_p (operands[2], VOIDmode)
+ && strict_single_insn_op_p (operands[2], VOIDmode)
+ && operand_clobbered_before_used_after (operands[1], label));
+ return 1;
+ }
+ }
+ }
+
+ if (conditional == 1
+ && GET_CODE (operands[1]) != PC
+ && safe_insn_src_p (operands[2], VOIDmode)
+ && strict_single_insn_op_p (operands[2], VOIDmode)
+ && operand_clobbered_before_used_after (operands[1], label))
+ return 1;
+
+ return 0;
+}
+
diff --git a/gcc-1.40/config/out-spur.c b/gcc-1.40/config/out-spur.c
new file mode 100644
index 0000000..0e5c5a8
--- /dev/null
+++ b/gcc-1.40/config/out-spur.c
@@ -0,0 +1,316 @@
+/* Subroutines for insn-output.c for SPUR. Adapted from routines for
+ the Motorola 68000 family.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+static rtx find_addr_reg ();
+
+char *
+output_compare (operands, opcode, exchange_opcode,
+ neg_opcode, neg_exchange_opcode)
+ rtx *operands;
+ char *opcode;
+ char *exchange_opcode;
+ char *neg_opcode;
+ char *neg_exchange_opcode;
+{
+ static char buf[100];
+ operands[2] = operands[0];
+ if (GET_CODE (cc_prev_status.value1) == CONST_INT)
+ {
+ operands[1] = cc_prev_status.value1;
+ operands[0] = cc_prev_status.value2;
+ opcode = exchange_opcode, neg_opcode = neg_exchange_opcode;
+ }
+ else
+ {
+ operands[0] = cc_prev_status.value1;
+ operands[1] = cc_prev_status.value2;
+ }
+ if (TARGET_LONG_JUMPS)
+ sprintf (buf,
+ "cmp_br_delayed %s,%%0,%%1,1f\n\tnop\n\tjump %%l2\n\tnop\n1:",
+ neg_opcode);
+ else
+ sprintf (buf, "cmp_br_delayed %s,%%0,%%1,%%l2\n\tnop", opcode);
+ return buf;
+}
+
+/* Return the best assembler insn template
+ for moving operands[1] into operands[0] as a fullword. */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return "st_32 %r1,%0";
+ if (GET_CODE (operands[1]) == MEM)
+ return "ld_32 %0,%1\n\tnop";
+ if (GET_CODE (operands[1]) == REG)
+ return "add_nt %0,%1,$0";
+ return "add_nt %0,r0,%1";
+}
+
+/* Output assembler code to perform a doubleword move insn
+ with operands OPERANDS. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx addreg0 = 0, addreg1 = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if (CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ optype1 = CNSTOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else
+ optype1 = RNDOP;
+
+ /* Check for the cases that the operand constraints are not
+ supposed to allow to happen. Abort if we get one,
+ because generating code for these cases is painful. */
+
+ if (optype0 == RNDOP || optype1 == RNDOP)
+ abort ();
+
+ /* If an operand is an unoffsettable memory ref, find a register
+ we can increment temporarily to make it refer to the second word. */
+
+ if (optype0 == MEMOP)
+ addreg0 = find_addr_reg (XEXP (operands[0], 0));
+
+ if (optype1 == MEMOP)
+ addreg1 = find_addr_reg (XEXP (operands[1], 0));
+
+ /* Ok, we can do one word at a time.
+ Normally we do the low-numbered word first,
+ but if either operand is autodecrementing then we
+ do the high-numbered word first.
+
+ In either case, set up in LATEHALF the operands to use
+ for the high-numbered word and in some cases alter the
+ operands in OPERANDS to be suitable for the low-numbered word. */
+
+ if (optype0 == REGOP)
+ latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (optype0 == OFFSOP)
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ else
+ latehalf[0] = operands[0];
+
+ if (optype1 == REGOP)
+ latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ else if (optype1 == OFFSOP)
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ else if (optype1 == CNSTOP)
+ {
+ if (CONSTANT_P (operands[1]))
+ latehalf[1] = const0_rtx;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ }
+ else
+ latehalf[1] = operands[1];
+
+ /* If the first move would clobber the source of the second one,
+ do them in the other order. This happens only for registers;
+ such overlap can't happen in memory unless the user explicitly
+ sets it up, and that is an undefined circumstance. */
+
+ if (optype0 == REGOP && optype1 == REGOP
+ && REGNO (operands[0]) == REGNO (latehalf[1]))
+ {
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("add_nt %0,%0,$4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add_nt %0,%0,$4", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("add_nt %0,%0,$-4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add_nt %0,%0,$-4", &addreg0);
+
+ /* Do low-numbered word. */
+ return singlemove_string (operands);
+ }
+
+ /* Normal case: do the two words, low-numbered first. */
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ /* Make any unoffsettable addresses point at high-numbered word. */
+ if (addreg0)
+ output_asm_insn ("add_nt %0,%0,$4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add_nt %0,%0,$4", &addreg1);
+
+ /* Do that word. */
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("add_nt %0,%0,$-4", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add_nt %0,%0,$-4", &addreg1);
+
+ return "";
+}
+
+static char *
+output_fp_move_double (operands)
+ rtx *operands;
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return "fmov %0,%1";
+ if (GET_CODE (operands[1]) == REG)
+ {
+ rtx xoperands[2];
+ int offset = - get_frame_size () - 8;
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4);
+ output_asm_insn ("st_32 %1,r25,%0", xoperands);
+ xoperands[1] = operands[1];
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+ output_asm_insn ("st_32 %1,r25,%0", xoperands);
+ xoperands[1] = operands[0];
+ output_asm_insn ("ld_dbl %1,r25,%0\n\tnop", xoperands);
+ return "";
+ }
+ return "ld_dbl %0,%1\n\tnop";
+ }
+ else if (FP_REG_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == REG)
+ {
+ rtx xoperands[2];
+ int offset = - get_frame_size () - 8;
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+ xoperands[1] = operands[1];
+ output_asm_insn ("st_dbl %1,r25,%0", xoperands);
+ xoperands[1] = operands[0];
+ output_asm_insn ("ld_32 %1,r25,%0\n\tnop", xoperands);
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4);
+ output_asm_insn ("ld_32 %1,r25,%0\n\tnop", xoperands);
+ return "";
+ }
+ return "st_dbl %1,%0";
+ }
+}
+
+/* Return a REG that occurs in ADDR with coefficient 1.
+ ADDR can be effectively incremented by incrementing REG. */
+
+static rtx
+find_addr_reg (addr)
+ rtx addr;
+{
+ while (GET_CODE (addr) == PLUS)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ addr = XEXP (addr, 0);
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 0)))
+ addr = XEXP (addr, 1);
+ else if (CONSTANT_P (XEXP (addr, 1)))
+ addr = XEXP (addr, 0);
+ else
+ abort ();
+ }
+ if (GET_CODE (addr) == REG)
+ return addr;
+ abort ();
+}
+
+/* Generate code to add a large integer constant to register, reg, storing
+ * the result in a register, target. Offset must be 27-bit signed quantity */
+
+static char *
+output_add_large_offset (target, reg, offset)
+ rtx target, reg;
+ int offset;
+{
+ rtx operands[3];
+ int high, n, i;
+ operands[0] = target, operands[1] = reg;
+
+ for (high = offset, n = 0;
+ (unsigned) (high + 0x2000) >= 0x4000;
+ high >>= 1, n += 1)
+ ;
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, high);
+ output_asm_insn ("add_nt r2,r0,%2", operands);
+ i = n;
+ while (i >= 3)
+ output_asm_insn ("sll r2,r2,$3", operands), i -= 3;
+ if (i == 2)
+ output_asm_insn ("sll r2,r2,$2", operands);
+ else if (i == 1)
+ output_asm_insn ("sll r2,r2,$1", operands);
+ output_asm_insn ("add_nt %0,r2,%1", operands);
+ if (offset - (high << n) != 0)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, offset - (high << n));
+ output_asm_insn ("add_nt %0,%0,%2", operands);
+ }
+ return "";
+}
+
+/* Additional TESTFN for matching. Like immediate_operand, but matches big
+ * constants */
+
+int
+big_immediate_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == CONST_INT);
+}
diff --git a/gcc-1.40/config/out-tahoe.c b/gcc-1.40/config/out-tahoe.c
new file mode 100644
index 0000000..47f9591
--- /dev/null
+++ b/gcc-1.40/config/out-tahoe.c
@@ -0,0 +1,550 @@
+/* Subroutines for insn-output.c for Tahoe.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * File: output-tahoe.c
+ *
+ * This port made at the University of Buffalo by Devon Bowen,
+ * Dale Wiles and Kevin Zachmann.
+ *
+ * Mail bugs reports or fixes to: gcc@cs.buffalo.edu
+ */
+
+
+/* most of the print_operand_address function was taken from the vax */
+/* since the modes are basically the same. I had to add a special case, */
+/* though, for symbol references with offsets. */
+
+#include <stdio.h>
+
+print_operand_address (file, addr)
+ FILE *file;
+ register rtx addr;
+{
+ register rtx reg1, reg2, breg, ireg;
+ rtx offset;
+ static char *reg_name[] = REGISTER_NAMES;
+
+ retry:
+ switch (GET_CODE (addr))
+ {
+ case MEM:
+ fprintf (file, "*");
+ addr = XEXP (addr, 0);
+ goto retry;
+
+ case REG:
+ fprintf (file, "(%s)", reg_name [REGNO (addr)]);
+ break;
+
+ case PRE_DEC:
+ fprintf (file, "-(%s)", reg_name [REGNO (XEXP (addr, 0))]);
+ break;
+
+ case POST_INC:
+ fprintf (file, "(%s)+", reg_name [REGNO (XEXP (addr, 0))]);
+ break;
+
+ case PLUS:
+ reg1 = 0; reg2 = 0;
+ ireg = 0; breg = 0;
+ offset = 0;
+
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ output_addr_const (file, addr);
+
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
+ && GET_CODE (XEXP (addr, 0)) == CONST_INT)
+ output_addr_const (file, addr);
+
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
+ || GET_CODE (XEXP (addr, 0)) == MEM)
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
+ || GET_CODE (XEXP (addr, 1)) == MEM)
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) != PLUS)
+ ;
+ else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ {
+ if (reg1 == 0)
+ reg1 = addr;
+ else
+ reg2 = addr;
+ addr = 0;
+ }
+ if (offset != 0)
+ {
+ if (addr != 0) abort ();
+ addr = offset;
+ }
+ if (reg1 != 0 && GET_CODE (reg1) == MULT)
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else if (reg2 != 0 && GET_CODE (reg2) == MULT)
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+ else if (reg2 != 0 || GET_CODE (addr) == MEM)
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+ if (addr != 0)
+ output_address (offset);
+ if (breg != 0)
+ {
+ if (GET_CODE (breg) != REG)
+ abort ();
+ fprintf (file, "(%s)", reg_name[REGNO (breg)]);
+ }
+ if (ireg != 0)
+ {
+ if (GET_CODE (ireg) == MULT)
+ ireg = XEXP (ireg, 0);
+ if (GET_CODE (ireg) != REG)
+ abort ();
+ fprintf (file, "[%s]", reg_name[REGNO (ireg)]);
+ }
+ break;
+
+ default:
+ output_addr_const (file, addr);
+ }
+}
+
+
+/* Do a quick check and find out what the best way to do the */
+/* mini-move is. Could be a push or a move..... */
+
+static char *
+singlemove_string (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0],0)) == PRE_DEC)
+ return "pushl %1";
+ return "movl %1,%0";
+}
+
+
+/* given the rtx for an address, return true if the given */
+/* register number is used in the address somewhere. */
+
+int
+regisused (addr,regnum)
+ rtx addr;
+ int regnum;
+{
+ if (GET_CODE (addr) == REG)
+ {
+ if (REGNO (addr) == regnum)
+ return (1);
+ else
+ return (0);
+ }
+
+ if (GET_CODE (addr) == MEM)
+ return regisused (XEXP (addr,0),regnum);
+
+ if (GET_CODE (addr) == MULT || GET_CODE (addr) == PLUS)
+ return (regisused (XEXP (addr,0),regnum)
+ || regisused (XEXP (addr,1),regnum));
+
+ return 0;
+}
+
+
+/* Given some rtx, traverse it and return the register used in a */
+/* index. If no index is found, return 0. */
+
+rtx
+index_reg (addr)
+ rtx addr;
+{
+ rtx temp;
+
+ if (GET_CODE (addr) == MEM)
+ return index_reg (XEXP (addr,0));
+
+ if (GET_CODE (addr) == MULT)
+ {
+ if (GET_CODE (XEXP (addr,0)) == REG)
+ return XEXP (addr,0);
+ else
+ return XEXP (addr,1);
+ }
+
+ if (GET_CODE (addr) == PLUS)
+ {
+ if (temp = index_reg (XEXP (addr,0)))
+ return temp;
+ else
+ return index_reg (XEXP (addr,1));
+ }
+
+ return 0;
+}
+
+
+/* simulate the move double by generating two movl's. You have */
+/* to be careful about mixing modes here. A future improvement */
+/* would be to allow immediate doubles. */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, INDOP, CNSTOP, RNDOP } optype0, optype1;
+ rtx latehalf[2];
+ rtx shftreg0 = 0, shftreg1 = 0;
+ rtx temp0 = 0, temp1 = 0;
+ rtx addreg0 = 0, addreg1 = 0;
+ int dohighfirst = 0;
+
+ /* First classify both operands. */
+
+ if (REG_P (operands[0]))
+ optype0 = REGOP;
+ else if ((GET_CODE (operands[0])==MEM) && (shftreg0=index_reg (operands[0])))
+ optype0 = INDOP;
+ else if (offsettable_memref_p (operands[0]))
+ optype0 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ {
+ optype0 = PUSHOP;
+ dohighfirst++;
+ }
+ else if (GET_CODE (operands[0]) == MEM)
+ optype0 = MEMOP;
+ else
+ optype0 = RNDOP;
+
+ if (REG_P (operands[1]))
+ optype1 = REGOP;
+ else if ((GET_CODE (operands[1])==MEM) && (shftreg1=index_reg (operands[1])))
+ optype1 = INDOP;
+ else if (offsettable_memref_p (operands[1]))
+ optype1 = OFFSOP;
+ else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
+ optype1 = POPOP;
+ else if (GET_CODE (operands[1]) == MEM)
+ optype1 = MEMOP;
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE || CONSTANT_P (operands[1]))
+ optype1 = CNSTOP;
+ else
+ optype1 = RNDOP;
+
+ /* set up for the high byte move for operand zero */
+
+ switch (optype0)
+ {
+
+ /* if it's a register, just use the next highest in the */
+ /* high address move. */
+
+ case REGOP:
+ latehalf[0] = gen_rtx (REG,SImode,REGNO (operands[0])+1);
+ break;
+
+ /* for an offsettable address, use the gcc function to */
+ /* modify the operand to get an offset of 4 higher for */
+ /* the second move. */
+
+ case OFFSOP:
+ latehalf[0] = adj_offsettable_operand (operands[0], 4);
+ break;
+
+ /* if the operand is MEMOP type, it must be a pointer */
+ /* to a pointer. So just remember to increase the mem */
+ /* location and use the same operand. */
+
+ case MEMOP:
+ latehalf[0] = operands[0];
+ addreg0 = XEXP (operands[0],0);
+ break;
+
+ /* if we're dealing with a push instruction, just leave */
+ /* the operand alone since it auto-increments. */
+
+ case PUSHOP:
+ latehalf[0] = operands[0];
+ break;
+
+ /* YUCK! Indexed addressing!! If the address is considered */
+ /* offsettable, go use the offset in the high part. Otherwise */
+ /* find what exactly is being added to the mutiplication. If */
+ /* it's a mem reference, increment that with the high part */
+ /* being unchanged to cause the shift. If it's a reg, do the */
+ /* same. If you can't identify it, abort. Remember that the */
+ /* shift register was already set during identification. */
+
+ case INDOP:
+ if (offsettable_memref_p (operands[0]))
+ {
+ latehalf[0] = adj_offsettable_operand (operands[0],4);
+ break;
+ }
+
+ latehalf[0] = operands[0];
+
+ temp0 = XEXP (XEXP (operands[0],0),0);
+ if (GET_CODE (temp0) == MULT)
+ {
+ temp1 = temp0;
+ temp0 = XEXP (XEXP (operands[0],0),1);
+ }
+ else
+ {
+ temp1 = XEXP (XEXP (operands[0],0),1);
+ if (GET_CODE (temp1) != MULT)
+ abort ();
+ }
+
+ if (GET_CODE (temp0) == MEM)
+ addreg0 = temp0;
+ else if (GET_CODE (temp0) == REG)
+ addreg0 = temp0;
+ else
+ abort ();
+
+ break;
+
+ /* if we don't know the operand type, print a friendly */
+ /* little error message... 8-) */
+
+ case RNDOP:
+ default:
+ abort ();
+ }
+
+ /* do the same setup for operand one */
+
+ switch (optype1)
+ {
+
+ case REGOP:
+ latehalf[1] = gen_rtx (REG,SImode,REGNO (operands[1])+1);
+ break;
+
+ case OFFSOP:
+ latehalf[1] = adj_offsettable_operand (operands[1], 4);
+ break;
+
+ case MEMOP:
+ latehalf[1] = operands[1];
+ addreg1 = XEXP (operands[1],0);
+ break;
+
+ case POPOP:
+ latehalf[1] = operands[1];
+ break;
+
+ case INDOP:
+ if (offsettable_memref_p (operands[1]))
+ {
+ latehalf[1] = adj_offsettable_operand (operands[1],4);
+ break;
+ }
+
+ latehalf[1] = operands[1];
+
+ temp0 = XEXP (XEXP (operands[1],0),0);
+ if (GET_CODE (temp0) == MULT)
+ {
+ temp1 = temp0;
+ temp0 = XEXP (XEXP (operands[1],0),1);
+ }
+ else
+ {
+ temp1 = XEXP (XEXP (operands[1],0),1);
+ if (GET_CODE (temp1) != MULT)
+ abort ();
+ }
+
+ if (GET_CODE (temp0) == MEM)
+ addreg1 = temp0;
+ else if (GET_CODE (temp0) == REG)
+ addreg1 = temp0;
+ else
+ abort ();
+
+ break;
+
+ case CNSTOP:
+ /* Since this machine is big-endian,
+ the late half must be the low-order word for an integer,
+ or the latter word for a float. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ }
+ else
+ {
+ latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[1]));
+ }
+ }
+ else
+ {
+ latehalf[1] = operands[1];
+ operands[1] = const0_rtx;
+ }
+ break;
+
+ case RNDOP:
+ default:
+ abort ();
+ }
+
+
+ /* double the register used for shifting in both of the operands */
+ /* but make sure the same register isn't doubled twice! */
+
+ if (shftreg0 && shftreg1 && rtx_equal_p (shftreg0, shftreg1))
+ output_asm_insn ("addl2 %0,%0", &shftreg0);
+ else
+ {
+ if (shftreg0)
+ output_asm_insn ("addl2 %0,%0", &shftreg0);
+ if (shftreg1)
+ output_asm_insn ("addl2 %0,%0", &shftreg1);
+ }
+
+ /* if the destination is a register and that register is needed in */
+ /* the source addressing mode, swap the order of the moves since we */
+ /* don't want this destroyed til last. If both regs are used, not */
+ /* much we can do, so abort. If these becomes a problem, maybe we */
+ /* can do it on the stack? */
+
+ if (GET_CODE (operands[0])==REG && regisused (operands[1],REGNO (operands[0])))
+ if (regisused (latehalf[1],REGNO (latehalf[0])))
+ 8;
+ else
+ dohighfirst++;
+
+ /* if we're pushing, do the high address part first. */
+
+ if (dohighfirst)
+ {
+
+ if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
+ output_asm_insn ("addl2 $4,%0", &addreg0);
+ else
+ {
+ if (addreg0)
+ output_asm_insn ("addl2 $4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addl2 $4,%0", &addreg1);
+ }
+
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
+ output_asm_insn ("subl2 $4,%0", &addreg0);
+ else
+ {
+ if (addreg0)
+ output_asm_insn ("subl2 $4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subl2 $4,%0", &addreg1);
+ }
+
+ return singlemove_string (operands);
+ }
+
+ output_asm_insn (singlemove_string (operands), operands);
+
+ if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
+ output_asm_insn ("addl2 $4,%0", &addreg0);
+ else
+ {
+ if (addreg0)
+ output_asm_insn ("addl2 $4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("addl2 $4,%0", &addreg1);
+ }
+
+ output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ if (addreg0 && addreg1 && (rtx_equal_p (addreg0,addreg1)))
+ output_asm_insn ("subl2 $4,%0", &addreg0);
+ else
+ {
+ if (addreg0)
+ output_asm_insn ("subl2 $4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("subl2 $4,%0", &addreg1);
+ }
+
+ if (shftreg0 && shftreg1 && (rtx_equal_p (shftreg0,shftreg1)))
+ output_asm_insn ("shar $1,%0,%0", &shftreg0);
+ else
+ {
+ if (shftreg0)
+ output_asm_insn ("shar $1,%0,%0", &shftreg0);
+ if (shftreg1)
+ output_asm_insn ("shar $1,%0,%0", &shftreg1);
+ }
+
+ return "";
+}
diff --git a/gcc-1.40/config/out-vax.c b/gcc-1.40/config/out-vax.c
new file mode 100644
index 0000000..a17590b
--- /dev/null
+++ b/gcc-1.40/config/out-vax.c
@@ -0,0 +1,152 @@
+/* Subroutines for insn-output.c for Vax.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+/* This function allows any constant operand, even on VMS where some
+ constants are not normally legitimate. */
+
+int
+supergeneral_operand (x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ return (CONSTANT_P (x) || general_operand (x, mode));
+}
+
+print_operand_address (file, addr)
+ FILE *file;
+ register rtx addr;
+{
+ register rtx reg1, reg2, breg, ireg;
+ rtx offset;
+
+ retry:
+ switch (GET_CODE (addr))
+ {
+ case MEM:
+ fprintf (file, "*");
+ addr = XEXP (addr, 0);
+ goto retry;
+
+ case REG:
+ fprintf (file, "(%s)", reg_names[REGNO (addr)]);
+ break;
+
+ case PRE_DEC:
+ fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
+ break;
+
+ case POST_INC:
+ fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
+ break;
+
+ case PLUS:
+ reg1 = 0; reg2 = 0;
+ ireg = 0; breg = 0;
+ offset = 0;
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
+ || GET_CODE (XEXP (addr, 0)) == MEM)
+ {
+ offset = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
+ || GET_CODE (XEXP (addr, 1)) == MEM)
+ {
+ offset = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) != PLUS)
+ ;
+ else if (GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == MULT)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ else if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ reg1 = XEXP (addr, 0);
+ addr = XEXP (addr, 1);
+ }
+ else if (GET_CODE (XEXP (addr, 1)) == REG)
+ {
+ reg1 = XEXP (addr, 1);
+ addr = XEXP (addr, 0);
+ }
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
+ {
+ if (reg1 == 0)
+ reg1 = addr;
+ else
+ reg2 = addr;
+ addr = 0;
+ }
+ if (offset != 0)
+ {
+ if (addr != 0) abort ();
+ addr = offset;
+ }
+ if (reg1 != 0 && GET_CODE (reg1) == MULT)
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else if (reg2 != 0 && GET_CODE (reg2) == MULT)
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+ else if (reg2 != 0 || GET_CODE (addr) == MEM)
+ {
+ breg = reg2;
+ ireg = reg1;
+ }
+ else
+ {
+ breg = reg1;
+ ireg = reg2;
+ }
+ if (addr != 0)
+ output_address (addr);
+ if (breg != 0)
+ {
+ if (GET_CODE (breg) != REG)
+ abort ();
+ fprintf (file, "(%s)", reg_names[REGNO (breg)]);
+ }
+ if (ireg != 0)
+ {
+ if (GET_CODE (ireg) == MULT)
+ ireg = XEXP (ireg, 0);
+ if (GET_CODE (ireg) != REG)
+ abort ();
+ fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
+ }
+ break;
+
+ default:
+ output_addr_const (file, addr);
+ }
+}
diff --git a/gcc-1.40/config/pyr.md b/gcc-1.40/config/pyr.md
new file mode 100644
index 0000000..e8b09d0
--- /dev/null
+++ b/gcc-1.40/config/pyr.md
@@ -0,0 +1,1377 @@
+;; Machine description for Pyramid 90 Series for GNU C compiler
+;; Copyright (C) 1989 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+;; Instruction patterns. When multiple patterns apply,
+;; the first one in the file is chosen.
+;;
+;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
+;;
+;; cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;; updates for most instructions.
+
+;; * Try using define_insn instead of some peepholes in more places.
+;; * Set REG_NOTES:REG_EQUIV for cvt[bh]w loads. This would make the
+;; backward scan in sign_extend needless.
+;; * Match (pc) (label_ref) case in peephole patterns.
+;; * Should optimize
+;; "cmpX op1,op2; b{eq,ne} LY; ucmpX op1.op2; b{lt,le,gt,ge} LZ"
+;; to
+;; "ucmpX op1,op2; b{eq,ne} LY; b{lt,le,gt,ge} LZ"
+;; by pre-scanning insn and running notice_update_cc for them.
+;; * Is it necessary to do copy_rtx in the test and compare patterns?
+;; * Fix true frame pointer omission.
+;; * Make the jump tables contain branches, not addresses! This would
+;; save us one instruction.
+;; * Could the compilcated scheme for compares be simplyfied, if we had
+;; no named cmpqi or cmphi patterns, and instead anonymous patterns for
+;; the less-than-word compare cases pyr can handle???
+;; * The jump insn seems to accept more than just IR addressing. Would
+;; we win by telling GCC? Or can we use movw into the global reg which
+;; is a synonym for pc?
+;; * More DImode patterns.
+;; * Scan backwards in "zero_extendhisi2", "zero_extendqisi2" to find out
+;; if the extension can be omitted.
+;; * "divmodsi" with Pyramid "ediv" insn. Is it possible in rtl??
+;; * Would "rcsp tmpreg; u?cmp[bh] op1_regdispl(tmpreg),op2" win in
+;; comparison with the two extensions and single test generated now?
+;; The rcsp insn could be expanded, and moved out of loops by the
+;; optimizer, making 1 (64 bit) insn of 3 (32 bit) insns in loops.
+;; The rcsp insn could be followed by an add insn, making non-displacement
+;; IR addressing sufficient.
+
+;______________________________________________________________________
+;
+; Test and Compare Patterns.
+;______________________________________________________________________
+
+; The argument for the rather complicated test and compare expansion
+; scheme, is the irregular pyramid instructions for these operations.
+; 1) Pyramid has different signed and unsigned compares. 2) HImode
+; and QImode integers are memory-memory and immediate-memory only. 3)
+; Unsigned HImode compares doesn't exist. 4) Only certain
+; combinations of addresses are allowed for memory-memory compares.
+; Whenever necessary, in order to fulfill these addressing
+; constraints, the compare operands are swapped.
+
+(define_expand "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" ""))]
+ "" "operands[0] = force_reg (SImode, operands[0]);")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "memory_operand" "m")))]
+ "weird_memory_memory (operands[0], operands[1])"
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+ RTX_CODE br_code;
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+ br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
+
+ weird_memory_memory (operands[0], operands[1]);
+
+ if (swap_operands)
+ {
+ cc_status.flags = CC_REVERSED;
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpw %0,%1\";
+ }
+ return \"cmpw %0,%1\";
+ }
+
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpw %1,%0\";
+ }
+ return \"cmpw %1,%0\";
+}")
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "r,g")
+ (match_operand:SI 1 "general_operand" "g,r")))]
+ ""
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+ RTX_CODE br_code;
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+ br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
+
+ if (which_alternative != 0)
+ {
+ cc_status.flags = CC_REVERSED;
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpw %0,%1\";
+ }
+ return \"cmpw %0,%1\";
+ }
+
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpw %1,%0\";
+ }
+ return \"cmpw %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "r"))]
+ ""
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+ RTX_CODE br_code;
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+ br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
+
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpw $0,%0\";
+ }
+ return \"mtstw %0,%0\";
+}")
+
+(define_expand "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" "")))]
+ ""
+ "
+{
+ extern rtx test_op0, test_op1; extern enum machine_mode test_mode;
+ test_op0 = copy_rtx (operands[0]);
+ test_op1 = copy_rtx (operands[1]);
+ test_mode = HImode;
+ DONE;
+}")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "nonimmediate_operand" "rm"))]
+ ""
+ "*
+{
+ cc_status.flags = CC_NO_OVERFLOW;
+ return \"cvthw %0,lr15\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:HI 0 "memory_operand" "m")
+ (match_operand:HI 1 "memory_operand" "m")))]
+ "weird_memory_memory (operands[0], operands[1])"
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+
+ weird_memory_memory (operands[0], operands[1]);
+
+ if (swap_operands)
+ {
+ cc_status.flags = CC_REVERSED;
+ return \"cmph %0,%1\";
+ }
+
+ return \"cmph %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "r,m")
+ (match_operand:HI 1 "nonimmediate_operand" "m,r")))]
+ "(GET_CODE (operands[0]) != GET_CODE (operands[1]))"
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+
+ if (which_alternative != 0)
+ {
+ cc_status.flags = CC_REVERSED;
+ return \"cmph %0,%1\";
+ }
+
+ return \"cmph %1,%0\";
+}")
+
+(define_expand "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" "")))]
+ ""
+ "
+{
+ extern rtx test_op0, test_op1; extern enum machine_mode test_mode;
+ test_op0 = copy_rtx (operands[0]);
+ test_op1 = copy_rtx (operands[1]);
+ test_mode = QImode;
+ DONE;
+}")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "nonimmediate_operand" "rm"))]
+ ""
+ "*
+{
+ cc_status.flags = CC_NO_OVERFLOW;
+ return \"cvtbw %0,lr15\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:QI 0 "memory_operand" "m")
+ (match_operand:QI 1 "memory_operand" "m")))]
+ "weird_memory_memory (operands[0], operands[1])"
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+ RTX_CODE br_code;
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+ br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
+
+ weird_memory_memory (operands[0], operands[1]);
+
+ if (swap_operands)
+ {
+ cc_status.flags = CC_REVERSED;
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpb %0,%1\";
+ }
+ return \"cmpb %0,%1\";
+ }
+
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpb %1,%0\";
+ }
+ return \"cmpb %1,%0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "r,m")
+ (match_operand:QI 1 "nonimmediate_operand" "m,r")))]
+ "(GET_CODE (operands[0]) != GET_CODE (operands[1]))"
+ "*
+{
+ rtx br_insn = NEXT_INSN (insn);
+ RTX_CODE br_code;
+
+ if (GET_CODE (br_insn) != JUMP_INSN)
+ abort();
+ br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
+
+ if (which_alternative != 0)
+ {
+ cc_status.flags = CC_REVERSED;
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpb %0,%1\";
+ }
+ return \"cmpb %0,%1\";
+ }
+
+ if (TRULY_UNSIGNED_COMPARE_P (br_code))
+ {
+ cc_status.mdep = CC_VALID_FOR_UNSIGNED;
+ return \"ucmpb %1,%0\";
+ }
+ return \"cmpb %1,%0\";
+}")
+
+(define_expand "bgt"
+ [(set (pc) (if_then_else (gt (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "blt"
+ [(set (pc) (if_then_else (lt (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "bge"
+ [(set (pc) (if_then_else (ge (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "ble"
+ [(set (pc) (if_then_else (le (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "beq"
+ [(set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "bne"
+ [(set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (SIGN_EXTEND);")
+
+(define_expand "bgtu"
+ [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (ZERO_EXTEND);")
+
+(define_expand "bltu"
+ [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (ZERO_EXTEND);")
+
+(define_expand "bgeu"
+ [(set (pc) (if_then_else (geu (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (ZERO_EXTEND);")
+
+(define_expand "bleu"
+ [(set (pc) (if_then_else (leu (cc0) (const_int 0))
+ (label_ref (match_operand 0 "" "")) (pc)))]
+ "" "extend_and_branch (ZERO_EXTEND);")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "r")
+ (match_operand:DF 1 "register_operand" "r")))]
+ ""
+ "cmpd %1,%0")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "register_operand" "r")
+ (match_operand:SF 1 "register_operand" "r")))]
+ ""
+ "cmpf %1,%0")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "register_operand" "r"))]
+ ""
+ "mtstd %0,%0")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "r"))]
+ ""
+ "mtstf %0,%0")
+
+;______________________________________________________________________
+;
+; Fixed-point Arithmetic.
+;______________________________________________________________________
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,!r")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0,r")
+ (match_operand:SI 2 "general_operand" "g,rJ")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ return \"addw %2,%0\";
+ else
+ {
+ forget_cc_if_dependent (operands[0]);
+ return REG_P (operands[2])
+ ? \"mova (%2)[%1*1],%0\" : \"mova %a2[%1*1],%0\";
+ }
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,g")
+ (match_operand:SI 2 "general_operand" "g,0")))]
+ ""
+ "* return (which_alternative == 0) ? \"subw %2,%0\" : \"rsubw %1,%0\";")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "mulw %2,%0")
+
+(define_insn "umulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "umulw %2,%0")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (div:SI (match_operand:SI 1 "general_operand" "0,g")
+ (match_operand:SI 2 "general_operand" "g,0")))]
+ ""
+ "* return (which_alternative == 0) ? \"divw %2,%0\" : \"rdivw %1,%0\";")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "udivw %2,%0")
+
+(define_insn "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mod:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "modw %2,%0")
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "umodw %2,%0")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "mnegw %1,%0")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "mcomw %1,%0")
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (abs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "mabsw %1,%0")
+
+;______________________________________________________________________
+;
+; Floating-point Arithmetic.
+;______________________________________________________________________
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "addd %2,%0")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "addf %2,%0")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (minus:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "subd %2,%0")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (minus:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "subf %2,%0")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "muld %2,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "mulf %2,%0")
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (div:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "r")))]
+ ""
+ "divd %2,%0")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (div:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "register_operand" "r")))]
+ ""
+ "divf %2,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (neg:DF (match_operand:DF 1 "register_operand" "r")))]
+ ""
+ "mnegd %1,%0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (neg:SF (match_operand:SF 1 "register_operand" "r")))]
+ ""
+ "mnegf %1,%0")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=r")
+ (abs:DF (match_operand:DF 1 "register_operand" "r")))]
+ ""
+ "mabsd %1,%0")
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (abs:SF (match_operand:SF 1 "register_operand" "r")))]
+ ""
+ "mabsf %1,%0")
+
+;______________________________________________________________________
+;
+; Logical and Shift Instructions.
+;______________________________________________________________________
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "general_operand" "%r")
+ (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"bitw %1,%0\";
+}")
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,r")
+ (match_operand:SI 2 "general_operand" "g,K")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ return \"andw %2,%0\";
+
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return (INTVAL (operands[2]) == 255
+ ? \"movzbw %1,%0\" : \"movzhw %1,%0\");
+}")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "0")
+ (not:SI (match_operand:SI 2 "general_operand" "g"))))]
+ ""
+ "bicw %2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (not:SI (match_operand:SI 1 "general_operand" "g"))
+ (match_operand:SI 2 "register_operand" "0")))]
+ ""
+ "bicw %1,%0")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "orw %2,%0")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "xorw %2,%0")
+
+; The arithmetic left shift instructions work strangely on pyramids.
+; They fail to modify the sign bit. Therefore, use logic shifts.
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"lshlw %2,%0\", operands[2], 32); ")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"ashrw %2,%0\", operands[2], 32); ")
+
+(define_insn "ashrdi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"ashrl %2,%0\", operands[2], 64); ")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"lshrw %2,%0\", operands[2], 32); ")
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"rotlw %2,%0\", operands[2], 32); ")
+
+(define_insn "rotrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotatert:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "general_operand" "rnm")))]
+ ""
+ "* return output_shift (\"rotrw %2,%0\", operands[2], 32); ")
+
+;______________________________________________________________________
+;
+; Fixed and Floating Moves.
+;______________________________________________________________________
+
+;; If the destination is a memory operand, indexed source operands are
+;; disallowed. Big DImode constants are always loaded into a reg pair,
+;; although offsetable memory addresses really could be dealt with.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (match_operand:DI 1 "nonindexed_operand" "gF"))]
+ "(GET_CODE (operands[1]) == CONST_DOUBLE
+ ? ((CONST_DOUBLE_HIGH (operands[1]) == 0
+ && CONST_DOUBLE_LOW (operands[1]) >= 0)
+ || (CONST_DOUBLE_HIGH (operands[1]) == -1
+ && CONST_DOUBLE_LOW (operands[1]) < 0))
+ : 1)"
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[1]));
+ return \"movl %1,%0\";
+}")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=r")
+ (match_operand:DI 1 "general_operand" "gF"))]
+ ""
+ "* return output_move_double (operands); ")
+
+;; If the destination is a memory address, indexed source operands are
+;; disallowed.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "nonindexed_operand" "g"))]
+ ""
+ "movw %1,%0")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ""
+ "movw %1,%0")
+
+;; If the destination is a memory address, indexed source operands are
+;; disallowed.
+
+(define_insn ""
+ [(set (match_operand:HI 0 "memory_operand" "=m")
+ (match_operand:HI 1 "nonindexed_operand" "g"))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"cvtwh %1,%0\"; /* reg -> mem */
+ else
+ return \"movh %1,%0\"; /* mem imm -> mem */
+}")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=r")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) != MEM)
+ return \"movw %1,%0\"; /* reg imm -> reg */
+ return \"cvthw %1,%0\"; /* mem -> reg */
+}")
+
+;; If the destination is a memory address, indexed source operands are
+;; disallowed.
+
+(define_insn ""
+ [(set (match_operand:QI 0 "memory_operand" "=m")
+ (match_operand:QI 1 "nonindexed_operand" "g"))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"cvtwb %1,%0\"; /* reg -> mem */
+ else
+ return \"movb %1,%0\"; /* mem imm -> mem */
+}")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=r")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) != MEM)
+ return \"movw %1,%0\"; /* reg imm -> reg */
+ return \"cvtbw %1,%0\"; /* mem -> reg */
+}")
+
+;; If the destination is a memory address, indexed source operands are
+;; disallowed.
+
+(define_insn ""
+ [(set (match_operand:DF 0 "memory_operand" "=m")
+ (match_operand:DF 1 "nonindexed_operand" "g"))]
+ "GET_CODE (operands[1]) != CONST_DOUBLE"
+ "movl %1,%0")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=r")
+ (match_operand:DF 1 "general_operand" "gF"))]
+ ""
+ "* return output_move_double (operands); ")
+
+;; If the destination is a memory address, indexed source operands are
+;; disallowed.
+
+(define_insn ""
+ [(set (match_operand:SF 0 "memory_operand" "=m")
+ (match_operand:SF 1 "nonindexed_operand" "g"))]
+ ""
+ "movw %1,%0")
+
+;; Force the destination to a register, so all source operands are allowed.
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=r")
+ (match_operand:SF 1 "general_operand" "g"))]
+ ""
+ "movw %1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ forget_cc_if_dependent (operands[0]);
+ return \"mova %a1,%0\";
+}")
+
+;______________________________________________________________________
+;
+; Conversion patterns.
+;______________________________________________________________________
+
+;; The trunc patterns are used only when non compile-time constants are used.
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ forget_cc_if_dependent (operands[0]);
+ return \"movw %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "*
+{
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ forget_cc_if_dependent (operands[0]);
+ return \"movw %1,%0\";
+}")
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r,m")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "*
+{
+ extern int optimize;
+ if (optimize && REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1])
+ && already_sign_extended (insn, HImode, operands[0]))
+ {
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"cvthw %1,%0\";
+}")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=r,m")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "*
+{
+ extern int optimize;
+ if (optimize && REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1])
+ && already_sign_extended (insn, QImode, operands[0]))
+ {
+ cc_status = cc_prev_status;
+ return \"\";
+ }
+ return \"cvtbw %1,%0\";
+}")
+
+; Pyramid doesn't have insns *called* "cvtbh" or "movzbh".
+; But we can cvtbw/movzbw into a register, where there is no distinction
+; between words and halfwords.
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "cvtbw %1,%0")
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "*
+{
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"movzhw %1,%0\";
+}")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "*
+{
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"movzbw %1,%0\";
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+ ""
+ "*
+{
+ cc_status.flags = CC_NOT_NEGATIVE;
+ return \"movzbw %1,%0\";
+}")
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=&r,m")
+ (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "cvtfd %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=&r,m")
+ (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "cvtdf %1,%0")
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=&r,m")
+ (float:SF (match_operand:SI 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "cvtwf %1,%0")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=&r,m")
+ (float:DF (match_operand:SI 1 "nonimmediate_operand" "rm,r")))]
+ ""
+ "cvtwd %1,%0")
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=&r,m")
+ (fix:SI (fix:SF (match_operand:SF 1 "nonimmediate_operand" "rm,r"))))]
+ ""
+ "cvtfw %1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=&r,m")
+ (fix:SI (fix:DF (match_operand:DF 1 "nonimmediate_operand" "rm,r"))))]
+ ""
+ "cvtdw %1,%0")
+
+;______________________________________________________________________
+;
+; Flow Control Patterns.
+;______________________________________________________________________
+
+;; Prefer "br" to "jump" for unconditional jumps, since it's faster.
+;; (The assembler can manage with out-of-range branches.)
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "br %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (match_operator 0 "relop" [(cc0) (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ extern int optimize;
+ if (optimize)
+ switch (GET_CODE (operands[0]))
+ {
+ case EQ: case NE:
+ break;
+ case LT: case LE: case GE: case GT:
+ if (cc_prev_status.mdep == CC_VALID_FOR_UNSIGNED)
+ return 0;
+ break;
+ case LTU: case LEU: case GEU: case GTU:
+ if (cc_prev_status.mdep != CC_VALID_FOR_UNSIGNED)
+ return 0;
+ break;
+ }
+
+ return \"b%N0 %l1\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (match_operator 0 "relop" [(cc0) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "*
+{
+ extern int optimize;
+ if (optimize)
+ switch (GET_CODE (operands[0]))
+ {
+ case EQ: case NE:
+ break;
+ case LT: case LE: case GE: case GT:
+ if (cc_prev_status.mdep == CC_VALID_FOR_UNSIGNED)
+ return 0;
+ break;
+ case LTU: case LEU: case GEU: case GTU:
+ if (cc_prev_status.mdep != CC_VALID_FOR_UNSIGNED)
+ return 0;
+ break;
+ }
+
+ return \"b%C0 %l1\";
+}")
+
+(define_insn "call"
+ [(call (match_operand:QI 0 "memory_operand" "m")
+ (match_operand:SI 1 "immediate_operand" "n"))]
+ ""
+ "call %0")
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=r")
+ (call (match_operand:QI 1 "memory_operand" "m")
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ ;; Operand 2 not really used on Pyramid architecture.
+ ""
+ "call %1")
+
+(define_insn "return"
+ [(return)]
+ ""
+ "*
+{
+ if (get_frame_size () + current_function_pretend_args_size
+ + current_function_args_size != 0
+ || current_function_calls_alloca)
+ {
+ int dealloc_size = current_function_pretend_args_size;
+ if (current_function_pops_args)
+ dealloc_size += current_function_args_size;
+ operands[0] = gen_rtx (CONST_INT, VOIDmode, dealloc_size);
+ return \"retd %0\";
+ }
+ else
+ return \"ret\";
+}")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jump (%0)")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "movw gr0,gr0 # nop")
+
+;______________________________________________________________________
+;
+; Peep-hole Optimization Patterns.
+;______________________________________________________________________
+
+;; Optimize fullword move followed by a test of the moved value.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "nonimmediate_operand" "rm"))
+ (set (cc0) (match_operand:SI 2 "nonimmediate_operand" "rm"))]
+ "rtx_equal_p (operands[2], operands[0])
+ || rtx_equal_p (operands[2], operands[1])"
+ "*
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"mtstw %1,%0\";
+")
+
+;; Same for HI and QI mode move-test as well.
+
+(define_peephole
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (match_operand:HI 1 "nonimmediate_operand" "rm"))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 3 "nonimmediate_operand" "rm")))
+ (set (cc0) (match_dup 2))]
+ "dead_or_set_p (insn, operands[2])
+ && (rtx_equal_p (operands[3], operands[0])
+ || rtx_equal_p (operands[3], operands[1]))"
+ "*
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"cvthw %1,%0\";
+")
+
+(define_peephole
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (match_operand:QI 1 "nonimmediate_operand" "rm"))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 3 "nonimmediate_operand" "rm")))
+ (set (cc0) (match_dup 2))]
+ "dead_or_set_p (insn, operands[2])
+ && (rtx_equal_p (operands[3], operands[0])
+ || rtx_equal_p (operands[3], operands[1]))"
+ "*
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"cvtbw %1,%0\";
+")
+
+;; Optimize loops with an incremented/decremented variable.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_dup 0)
+ (const_int -1)))
+ (set (cc0)
+ (compare (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "ri")))
+ (set (pc)
+ (if_then_else (match_operator:SI 3 "signed_comparison"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ ? (unsigned)INTVAL (operands[2]) + 32 >= 64
+ : 1) && (rtx_equal_p (operands[0], operands[1])
+ || rtx_equal_p (operands[0], operands[2]))"
+ "*
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ output_asm_insn (\"dcmpw %2,%0\", operands);
+ return \"b%N3 %l4\";
+ }
+ else
+ {
+ output_asm_insn (\"dcmpw %1,%0\", operands);
+ return \"b%R3 %l4\";
+ }
+")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_dup 0)
+ (const_int 1)))
+ (set (cc0)
+ (compare (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "ri")))
+ (set (pc)
+ (if_then_else (match_operator:SI 3 "signed_comparison"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 4 "" ""))
+ (pc)))]
+ "(GET_CODE (operands[2]) == CONST_INT
+ ? (unsigned)INTVAL (operands[2]) + 32 >= 64
+ : 1) && (rtx_equal_p (operands[0], operands[1])
+ || rtx_equal_p (operands[0], operands[2]))"
+ "*
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ output_asm_insn (\"icmpw %2,%0\", operands);
+ return \"b%N3 %l4\";
+ }
+ else
+ {
+ output_asm_insn (\"icmpw %1,%0\", operands);
+ return \"b%R3 %l4\";
+ }
+")
+
+;; Combine two word moves with consecutive operands into one long move.
+;; Also combines immediate moves, if the high-order destination operand
+;; is loaded with 0 or -1 and the low-order destination operand is loaded
+;; with a constant with the same sign.
+
+(define_peephole
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (set (match_operand:SI 2 "general_operand" "=g")
+ (match_operand:SI 3 "general_operand" "g"))]
+ "movdi_possible (operands)"
+ "*
+ output_asm_insn (\"# COMBINE movw %1,%0\", operands);
+ output_asm_insn (\"# COMBINE movw %3,%2\", operands);
+ movdi_possible (operands);
+ if (CONSTANT_P (operands[1]))
+ return (swap_operands) ? \"movl %3,%0\" : \"movl %1,%2\";
+
+ return (swap_operands) ? \"movl %1,%0\" : \"movl %3,%2\";
+")
+
+;; Optimize certain tests after memory stores.
+
+(define_peephole
+ [(set (match_operand 0 "memory_operand" "=m")
+ (match_operand 1 "register_operand" "r"))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (sign_extend:SI (match_dup 1)))
+ (set (cc0)
+ (match_dup 2))]
+ "dead_or_set_p (insn, operands[2])"
+ "*
+ cc_status.flags |= CC_NO_OVERFLOW;
+ if (GET_MODE (operands[0]) == QImode)
+ return \"cvtwb %1,%0\";
+ else
+ return \"cvtwh %1,%0\";
+")
+
+;______________________________________________________________________
+;
+; DImode Patterns.
+;______________________________________________________________________
+
+(define_expand "extendsidi2"
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (set (subreg:SI (match_dup 0) 0)
+ (subreg:SI (match_dup 0) 1))
+ (set (subreg:SI (match_dup 0) 0)
+ (ashiftrt:SI (subreg:SI (match_dup 0) 0)
+ (const_int 31)))]
+ ""
+ "")
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "nonmemory_operand" "%0")
+ (match_operand:DI 2 "nonmemory_operand" "rF")))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ CC_STATUS_INIT;
+ xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[2]))
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[2]));
+ }
+ output_asm_insn (\"addw %1,%0\", xoperands);
+ return \"addwc %2,%0\";
+}")
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "rF")))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ CC_STATUS_INIT;
+ xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[2]))
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[2]));
+ }
+ output_asm_insn (\"subw %1,%0\", xoperands);
+ return \"subwb %2,%0\";
+}")
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (match_operand:DI 1 "nonmemory_operand" "%0")
+ (match_operand:DI 2 "nonmemory_operand" "rF")))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ CC_STATUS_INIT;
+ xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[2]))
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[2]));
+ }
+ output_asm_insn (\"orw %1,%0\", xoperands);
+ return \"orw %2,%0\";
+}")
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (match_operand:DI 1 "nonmemory_operand" "%0")
+ (match_operand:DI 2 "nonmemory_operand" "rF")))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ CC_STATUS_INIT;
+ xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[2]))
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[2]));
+ }
+ output_asm_insn (\"andw %1,%0\", xoperands);
+ return \"andw %2,%0\";
+}")
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "nonmemory_operand" "%0")
+ (match_operand:DI 2 "nonmemory_operand" "rF")))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ CC_STATUS_INIT;
+ xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ if (REG_P (operands[2]))
+ xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (operands[2]));
+ }
+ output_asm_insn (\"xorw %1,%0\", xoperands);
+ return \"xorw %2,%0\";
+}")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/sparc.md b/gcc-1.40/config/sparc.md
new file mode 100644
index 0000000..e3d7b64
--- /dev/null
+++ b/gcc-1.40/config/sparc.md
@@ -0,0 +1,2370 @@
+
+;;- Machine description for SPARC chip for GNU C compiler
+;; Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+;; Contributed by Michael Tiemann (tiemann@mcc.com)
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+
+;; Compare instructions.
+;; This controls RTL generation and register allocation.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "arith_operand" "r,rI")
+ (match_operand:SI 1 "arith_operand" "I,r")))]
+ ""
+ "*
+{
+ if (! REG_P (operands[0]))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"cmp %1,%0\";
+ }
+ return \"cmp %0,%1\";
+}")
+
+(define_expand "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "nonmemory_operand" "f,fG")
+ (match_operand:DF 1 "nonmemory_operand" "G,f")))]
+ ""
+ "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, DFmode, 32)));")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:DF 0 "nonmemory_operand" "f,fG")
+ (match_operand:DF 1 "nonmemory_operand" "G,f")))]
+ "GET_CODE (operands[0]) != CONST_INT && GET_CODE (operands[1]) != CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == CONST_DOUBLE
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ make_f0_contain_0 (2);
+
+ cc_status.flags |= CC_IN_FCCR;
+ if (GET_CODE (operands[0]) == CONST_DOUBLE)
+ return \"fcmped %%f0,%1\;nop\";
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"fcmped %0,%%f0\;nop\";
+ return \"fcmped %0,%1\;nop\";
+}")
+
+(define_expand "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "nonmemory_operand" "f,fG")
+ (match_operand:SF 1 "nonmemory_operand" "G,f")))]
+ ""
+ "emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SFmode, 32)));")
+
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SF 0 "nonmemory_operand" "f,fG")
+ (match_operand:SF 1 "nonmemory_operand" "G,f")))]
+ "GET_CODE (operands[0]) != CONST_INT && GET_CODE (operands[1]) != CONST_INT"
+ "*
+{
+ if (GET_CODE (operands[0]) == CONST_DOUBLE
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ make_f0_contain_0 (1);
+
+ cc_status.flags |= CC_IN_FCCR;
+ if (GET_CODE (operands[0]) == CONST_DOUBLE)
+ return \"fcmpes %%f0,%1\;nop\";
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ return \"fcmpes %0,%%f0\;nop\";
+ return \"fcmpes %0,%1\;nop\";
+}")
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "tst %0")
+
+;; Need this to take a general operand because cse can make
+;; a CONST which won't be in a register.
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SI 0 "immediate_operand" "i"))]
+ ""
+ "set %0,%%g1\;tst %%g1")
+
+;; Optimize the case of following a reg-reg move with a test
+;; of reg just moved.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (set (cc0) (match_operand:SI 2 "register_operand" "r"))]
+ "operands[2] == operands[0]
+ || operands[2] == operands[1]"
+ "orcc %1,%%g0,%0 ! 2-insn combine")
+
+;; Optimize 5(6) insn sequence to 3(4) insns.
+;; These patterns could also optimize more complicated sets
+;; before conditional branches.
+
+;; Turned off because (1) this case is rarely encounted
+;; (2) to be correct, more conditions must be checked
+;; (3) the conditions must be checked with rtx_equal_p, not ==
+;; (4) when branch scheduling is added to the compiler,
+;; this optimization will be performed by the branch scheduler
+;; Bottom line: it is not worth the trouble of fixing or
+;; maintaining it.
+
+;(define_peephole
+; [(set (match_operand:SI 0 "register_operand" "=r")
+; (match_operand:SI 1 "general_operand" "g"))
+; (set (match_operand:SI 2 "register_operand" "=r")
+; (match_operand:SI 3 "reg_or_0_operand" "rJ"))
+; (set (cc0) (match_operand:SI 4 "register_operand" "r"))
+; (set (pc) (match_operand 5 "" ""))]
+; "GET_CODE (operands[5]) == IF_THEN_ELSE
+; && operands[0] != operands[3]
+; && ! reg_mentioned_p (operands[2], operands[1])
+; && (operands[4] == operands[0]
+; || operands[4] == operands[2]
+; || operands[4] == operands[3])"
+; "*
+;{
+; rtx xoperands[2];
+; int parity;
+; xoperands[0] = XEXP (operands[5], 0);
+; if (GET_CODE (XEXP (operands[5], 1)) == PC)
+; {
+; parity = 1;
+; xoperands[1] = XEXP (XEXP (operands[5], 2), 0);
+; }
+; else
+; {
+; parity = 0;
+; xoperands[1] = XEXP (XEXP (operands[5], 1), 0);
+; }
+;
+; if (operands[4] == operands[0])
+; {
+; /* Although the constraints for operands[1] permit a general
+; operand (and hence possibly a const_int), we know that
+; in this branch it cannot be a CONST_INT, since that would give
+; us a fixed condition, and those should have been optimized away. */
+; if (REG_P (operands[1]))
+; output_asm_insn (\"orcc %1,%%g0,%0 ! 3-insn reorder\", operands);
+; else if (GET_CODE (operands[1]) != MEM)
+; abort ();
+; else
+; {
+; if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+; output_asm_insn (\"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;tst %0 ! 4-insn reorder\", operands);
+; else
+; output_asm_insn (\"ld %1,%0\;tst %0 ! 3.5-insn reorder\", operands);
+; }
+; XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 2);
+; XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 3);
+; }
+; else
+; {
+; output_asm_insn (\"orcc %3,%%g0,%2 ! 3-insn reorder\", operands);
+; }
+; if (parity)
+; return output_delayed_branch (\"b%N0 %l1\", xoperands, insn);
+; else
+; return output_delayed_branch (\"b%C0 %l1\", xoperands, insn);
+;}")
+
+;; By default, operations don't set the condition codes.
+;; These patterns allow cc's to be set, while doing some work
+
+(define_insn ""
+ [(set (cc0)
+ (zero_extend:SI (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)))]
+ ""
+ "andcc %0,0xff,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (plus:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ "ignore_overflow_conditional_p (NEXT_INSN (insn))"
+ "*
+{
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"addcc %0,%1,%%g0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (plus:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (plus:SI (match_dup 0) (match_dup 1)))]
+ "ignore_overflow_conditional_p (NEXT_INSN (insn))"
+ "*
+{
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"addcc %0,%1,%2\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (minus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ "ignore_overflow_conditional_p (NEXT_INSN (insn))"
+ "*
+{
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"subcc %0,%1,%%g0\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (minus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (minus:SI (match_dup 0) (match_dup 1)))]
+ "ignore_overflow_conditional_p (NEXT_INSN (insn))"
+ "*
+{
+ cc_status.flags |= CC_NO_OVERFLOW;
+ return \"subcc %0,%1,%2\";
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "andcc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (and:SI (match_dup 0) (match_dup 1)))]
+ ""
+ "andcc %0,%1,%2")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
+ ""
+ "andncc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (and:SI (match_dup 0) (not:SI (match_dup 1))))]
+ ""
+ "andncc %0,%1,%2")
+
+(define_insn ""
+ [(set (cc0)
+ (ior:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "orcc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (ior:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (ior:SI (match_dup 0) (match_dup 1)))]
+ ""
+ "orcc %0,%1,%2")
+
+(define_insn ""
+ [(set (cc0)
+ (ior:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
+ ""
+ "orncc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (ior:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (ior:SI (match_dup 0) (not:SI (match_dup 1))))]
+ ""
+ "orncc %0,%1,%2")
+
+(define_insn ""
+ [(set (cc0)
+ (xor:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "xorcc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (xor:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (xor:SI (match_dup 0) (match_dup 1)))]
+ ""
+ "xorcc %0,%1,%2")
+
+(define_insn ""
+ [(set (cc0)
+ (xor:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))]
+ ""
+ "xnorcc %0,%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (xor:SI (match_operand:SI 0 "register_operand" "r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI"))))
+ (set (match_operand:SI 2 "register_operand" "=r")
+ (xor:SI (match_dup 0) (not:SI (match_dup 1))))]
+ ""
+ "xnorcc %0,%1,%2")
+
+(define_expand "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "register_operand" "f"))]
+ ""
+ "emit_insn (gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, DFmode, 32)));")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:DF 0 "register_operand" "f"))]
+ ""
+ "*
+{
+ make_f0_contain_0 (2);
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmped %0,%%f0\;nop\";
+}")
+
+(define_expand "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "f"))]
+ ""
+ "emit_insn (gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SFmode, 32)));")
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "f"))]
+ ""
+ "*
+{
+ make_f0_contain_0 (1);
+ cc_status.flags |= CC_IN_FCCR;
+ return \"fcmpes %0,%%f0\;nop\";
+}")
+
+;; There are no logical links for the condition codes. This
+;; would not normally be a problem, but on the SPARC (and possibly
+;; other RISC machines), when argument passing, the insn which sets
+;; the condition code and the insn which uses the set condition code
+;; may not be performed adjacently (due to optimizations performed
+;; in combine.c). To make up for this, we emit insn patterns which
+;; cannot possibly be rearranged on us.
+(define_expand "seq"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (eq (cc0) (const_int 0)))]
+ ""
+ "gen_scc_insn (EQ, VOIDmode, operands); DONE;")
+
+(define_expand "sne"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (ne (cc0) (const_int 0)))]
+ ""
+ "gen_scc_insn (NE, VOIDmode, operands); DONE;")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r,r")
+ (match_operator 1 "eq_or_neq"
+ [(compare (match_operand:SI 2 "general_operand" "r,rI")
+ (match_operand:SI 3 "general_operand" "I,r"))
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ if (! REG_P (operands[2]))
+ {
+ output_asm_insn (\"cmp %3,%2\", operands);
+ cc_status.flags |= CC_REVERSED;
+ }
+ else
+ output_asm_insn (\"cmp %2,%3\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (match_operator 1 "eq_or_neq"
+ [(match_operand:SI 2 "general_operand" "r")
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ output_asm_insn (\"tst %2\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r,r")
+ (match_operator 1 "eq_or_neq"
+ [(compare (match_operand:DF 2 "general_operand" "f,fG")
+ (match_operand:DF 3 "general_operand" "G,f"))
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ cc_status.flags |= CC_IN_FCCR;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[3]) == CONST_DOUBLE)
+ make_f0_contain_0 (2);
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ output_asm_insn (\"fcmped %%f0,%3\;nop\", operands);
+ else if (GET_CODE (operands[3]) == CONST_DOUBLE)
+ output_asm_insn (\"fcmped %2,%%f0\;nop\", operands);
+ else output_asm_insn (\"fcmped %2,%3\;nop\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (match_operator 1 "eq_or_neq"
+ [(match_operand:DF 2 "general_operand" "f")
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ cc_status.flags |= CC_IN_FCCR;
+
+ make_f0_contain_0 (2);
+ output_asm_insn (\"fcmped %2,%%f0\;nop\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r,r")
+ (match_operator 1 "eq_or_neq"
+ [(compare (match_operand:SF 2 "general_operand" "f,fG")
+ (match_operand:SF 3 "general_operand" "G,f"))
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ cc_status.flags |= CC_IN_FCCR;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[3]) == CONST_DOUBLE)
+ make_f0_contain_0 (1);
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ output_asm_insn (\"fcmpes %%f0,%3\;nop\", operands);
+ else if (GET_CODE (operands[3]) == CONST_DOUBLE)
+ output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands);
+ else output_asm_insn (\"fcmpes %2,%3\;nop\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (match_operator 1 "eq_or_neq"
+ [(match_operand:SF 2 "general_operand" "f")
+ (const_int 0)]))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ cc_status.value1 = operands[0];
+ cc_status.flags |= CC_IN_FCCR;
+
+ make_f0_contain_0 (1);
+ output_asm_insn (\"fcmpes %2,%%f0\;nop\", operands);
+ return output_scc_insn (GET_CODE (operands[1]), operands[0]);
+}")
+
+;; These control RTL generation for conditional jump insns
+;; and match them for register allocation.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"be %l0\;nop\", \"be %l0\;nop\", \"fbe %l0\;nop\");
+}")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"bne %l0\;nop\", \"bne %l0\;nop\", \"fbne %l0\;nop\");
+}")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"bg %l0\;nop\", 0, \"fbg %l0\;nop\");
+}")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ abort ();
+ return \"bgu %l0\;nop\";
+}")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"bl %l0\;nop\", \"bneg %l0\;nop\", \"fbl %l0\;nop\");
+}")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ abort ();
+ return \"blu %l0\;nop\";
+}")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"bge %l0\;nop\", \"bpos %l0\;nop\", \"fbge %l0\;nop\");
+}")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ abort ();
+ return \"bgeu %l0\;nop\";
+}")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ OUTPUT_JUMP (\"ble %l0\;nop\", 0, \"fble %l0\;nop\");
+}")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ abort ();
+ return \"bleu %l0\;nop\";
+}")
+
+;; This matches inverted jump insns for register allocation.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (match_operator 0 "relop" [(cc0) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "*
+{
+ if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ {
+ if (GET_CODE (operands[0]) == GT || GET_CODE (operands[0]) == LE)
+ /* These two conditions can't ignore overflow,
+ so reinsert the deleted test instruction. */
+ return 0;
+ return \"b%U0 %l1\;nop\";
+ }
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ return \"fb%F0 %l1\;nop\";
+ return \"b%N0 %l1\;nop\";
+}")
+
+;; Move instructions
+
+(define_insn "swapsi"
+ [(set (match_operand:SI 0 "general_operand" "r,rm")
+ (match_operand:SI 1 "general_operand" "m,r"))
+ (set (match_dup 1) (match_dup 0))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ output_asm_insn (\"set %a1,%%g1\", operands),
+ operands[1] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 1)),
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ output_asm_insn (\"swap %1,%0\", operands);
+ }
+ if (REG_P (operands[0]))
+ {
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"\";
+ return \"xor %0,%1,%0\;xor %1,%0,%1\;xor %0,%1,%0\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ output_asm_insn (\"set %a0,%%g1\", operands);
+ operands[0] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 1));
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ }
+ return \"swap %0,%1\";
+}")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r,m")
+ (match_operand:SI 1 "general_operand" "rmif,rJ"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ return \"st %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_fixed (operands);
+ return \"ld %1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
+ if (REG_P (operands[1])
+ || (GET_CODE (operands[1]) == CONST_INT
+ && SMALL_INT (operands[1])))
+ return \"mov %1,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & 0x3ff) == 0)
+ return \"sethi %%hi(%1),%0\";
+ return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=r,m")
+ (match_operand:HI 1 "general_operand" "rmi,rJ"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ return \"sth %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_fixed (operands);
+ return \"ldsh %1,%0\";
+ }
+ if (REG_P (operands[1])
+ || (GET_CODE (operands[1]) == CONST_INT
+ && SMALL_INT (operands[1])))
+ return \"mov %1,%0\";
+ return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=r,m")
+ (match_operand:QI 1 "general_operand" "rmi,rJ"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ return \"stb %r1,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_fixed (operands);
+ return \"ldsb %1,%0\";
+ }
+ if (REG_P (operands[1])
+ || (GET_CODE (operands[1]) == CONST_INT
+ && SMALL_INT (operands[1])))
+ return \"mov %1,%0\";
+ return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
+}")
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+(define_expand "movstrsi"
+ [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
+ (mem:BLK (match_operand:BLK 1 "general_operand" "")))
+ (use (match_operand:SI 2 "arith32_operand" ""))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (clobber (match_dup 4))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))])]
+ ""
+ "
+{
+ operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
+ operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
+ operands[4] = gen_reg_rtx (SImode);
+}")
+
+(define_insn ""
+ [(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
+ (mem:BLK (match_operand:SI 1 "register_operand" "r")))
+ (use (match_operand:SI 2 "arith32_operand" "rn"))
+ (use (match_operand:SI 3 "immediate_operand" "i"))
+ (clobber (match_operand:SI 4 "register_operand" "=r"))
+ (clobber (match_operand:SI 5 "register_operand" "=0"))
+ (clobber (match_operand:SI 6 "register_operand" "=1"))]
+ ""
+ "* return output_block_move (operands);")
+
+;; Floating point move insns
+
+;; This pattern forces (set (reg:DF ...) (const_double ...))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general movdf pattern.
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=r,f,o")
+ (match_operand:DF 1 "" "mG,m,G"))]
+ "GET_CODE (operands[1]) == CONST_DOUBLE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return output_fp_move_double (operands);
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
+ {
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"mov %%g0,%0\;mov %%g0,%1\";
+ }
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
+ {
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"st %%g0,[%%g1+%%lo(%%m0)]\;st %%g0,[%%g1+%%lo(%%m0)+4]\";
+ }
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"st %%g0,%0\;st %%g0,%1\";
+ }
+ return output_move_double (operands);
+}")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=rm,&r,?f,?rm")
+ (match_operand:DF 1 "general_operand" "r,m,rfm,f"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_floating (operands);
+
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=rm,&r,?f,?rm")
+ (match_operand:DI 1 "general_operand" "r,mi,rfm,f"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_fixed (operands);
+
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=rf,m")
+ (match_operand:SF 1 "general_operand" "rfm,rf"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ return output_store (operands);
+ if (GET_CODE (operands[1]) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ return output_load_floating (operands);
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmovs %1,%0\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\";
+ }
+ return \"ld %1,%0\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == REG)
+ return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\";
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"st %r1,[%%g1+%%lo(%m0)]\";
+ }
+ return \"st %r1,%0\";
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st %r1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+;;- truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"stb %1,[%%g1+%%lo(%m0)]\";
+ }
+ else
+ return \"stb %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"stb %1,[%%g1+%%lo(%m0)]\";
+ }
+ else
+ return \"stb %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (truncate:HI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"sth %1,[%%g1+%%lo(%m0)]\";
+ }
+ else
+ return \"sth %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+;;- zero extension instructions
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"sll %1,0x10,%0\;srl %0,0x10,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) & 0xffff);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;lduh [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"lduh %1,%0\";
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"and %1,0xff,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) & 0xff);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"ldub %1,%0\";
+}")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"and %1,0xff,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) & 0xff);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"ldub %1,%0\";
+}")
+
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"sll %1,0x10,%0\;sra %0,0x10,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int i = (short)INTVAL (operands[1]);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldsh [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"ldsh %1,%0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"sll %1,0x18,%0\;sra %0,0x18,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int i = (char)INTVAL (operands[1]);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"ldsb %1,%0\";
+}")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (REG_P (operands[1]))
+ return \"sll %1,0x18,%0\;sra %0,0x18,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int i = (char)INTVAL (operands[1]);
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
+ output_asm_insn (\"set %1,%0\", operands);
+ return \"\";
+ }
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
+ }
+ else
+ return \"ldsb %1,%0\";
+}")
+
+;; Signed bitfield extractions come out looking like
+;; (shiftrt (shift (sign_extend <Y>) <C1>) <C2>)
+;; which we expand poorly as four shift insns.
+;; These patters yeild two shifts:
+;; (shiftrt (shift <Y> <C3>) <C4>)
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI
+ (sign_extend:SI
+ (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:SI 2 "small_int" "n")))]
+ ""
+ "sll %1,0x18,%0\;sra %0,0x18+%2,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI
+ (sign_extend:SI
+ (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "small_int" "n")) 0))
+ (match_operand:SI 3 "small_int" "n")))]
+ ""
+ "sll %1,0x18+%2,%0\;sra %0,0x18+%3,%0")
+
+;; Special patterns for optimizing bit-field instructions.
+
+;; First two patterns are for bitfields that came from memory
+;; testing only the high bit. They work with old combiner.
+;; @@ Actually, the second pattern does not work if we
+;; @@ need to set the N bit.
+(define_insn ""
+ [(set (cc0)
+ (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 7)) 0)))]
+ "0"
+ "andcc %0,128,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 7)) 0)))]
+ "0"
+ "andcc %0,128,%%g0")
+
+;; next two patterns are good for bitfields coming from memory
+;; (via pseudo-register) or from a register, though this optimization
+;; is only good for values contained wholly within the bottom 13 bits
+(define_insn ""
+ [(set (cc0)
+ (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "small_int" "n"))
+ (match_operand:SI 2 "small_int" "n")))]
+ "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000"
+ "andcc %0,%2<<%1,%%g0")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "small_int" "n"))
+ (match_operand:SI 2 "small_int" "n")))]
+ "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000"
+ "andcc %0,%2<<%1,%%g0")
+
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "fstod %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "fdtos %1,%0")
+
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...)))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general floatsisf2 pattern.
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand 1 "" "m")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\";
+ }
+ return \"ld %1,%0\;fitos %0,%0\";
+}")
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=f")
+ (float:SF (match_operand:SI 1 "general_operand" "rfm")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\";
+ }
+ else
+ return \"ld %1,%0\;fitos %0,%0\";
+ else if (FP_REG_P (operands[1]))
+ return \"fitos %1,%0\";
+ return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitos %0,%0\";
+}")
+
+;; This pattern forces (set (reg:DF ...) (float:DF (const_int ...)))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general floatsidf2 pattern.
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand 1 "" "m")))]
+ "GET_CODE (operands[1]) == CONST_INT"
+ "*
+{
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\";
+ }
+ return \"ld %1,%0\;fitod %0,%0\";
+}")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=f")
+ (float:DF (match_operand:SI 1 "general_operand" "rfm")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\";
+ }
+ else
+ return \"ld %1,%0\;fitod %0,%0\";
+ else if (FP_REG_P (operands[1]))
+ return \"fitod %1,%0\";
+ else
+ return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitod %0,%0\";
+}")
+
+;; Convert a float to an actual integer.
+;; Truncation is performed as part of the conversion.
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
+ ""
+ "*
+{
+ cc_status.flags &= ~(CC_F1_IS_0);
+ if (FP_REG_P (operands[1]))
+ output_asm_insn (\"fstoi %1,%%f1\", operands);
+ else if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ output_asm_insn (\"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%%f1\;fstoi %%f1,%%f1\", operands);
+ }
+ else
+ output_asm_insn (\"ld %1,%%f1\;fstoi %%f1,%%f1\", operands);
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"st %%f1,[%%g1+%%lo(%m0)]\";
+ }
+ else
+ return \"st %%f1,%0\";
+ else
+ return \"st %%f1,[%%fp-4]\;ld [%%fp-4],%0\";
+}")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=rm")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
+ ""
+ "*
+{
+ cc_status.flags &= ~CC_F0_IS_0;
+ if (FP_REG_P (operands[1]))
+ output_asm_insn (\"fdtoi %1,%%f0\", operands);
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (REG, DFmode, 32);
+ xoperands[1] = operands[1];
+ output_asm_insn (output_fp_move_double (xoperands), xoperands);
+ output_asm_insn (\"fdtoi %%f0,%%f0\", 0);
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
+ {
+ if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
+ && XEXP (operands[0], 0) == cc_prev_status.mdep))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[0], 0);
+ output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands);
+ }
+ return \"st %%f0,[%%g1+%%lo(%m0)]\";
+ }
+ else
+ return \"st %%f0,%0\";
+ else
+ return \"st %%f0,[%%fp-4]\;ld [%%fp-4],%0\";
+}")
+
+;;- arithmetic instructions
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "arith32_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"add %1,%2,%0\";
+ if (SMALL_INT (operands[2]))
+ return \"add %1,%2,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;add %1,%%g1,%0\";
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]))
+ return \"sub %1,%2,%0\";
+ if (SMALL_INT (operands[2]))
+ return \"sub %1,%2,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;sub %1,%%g1,%0\";
+}")
+
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (mult:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "
+{
+ rtx src;
+
+ if (GET_CODE (operands[1]) == CONST_INT)
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_move_insn (operands[0],
+ gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) * INTVAL (operands[2])));
+ DONE;
+ }
+ else
+ src = gen_rtx (MULT, SImode,
+ copy_to_mode_reg (SImode, operands[2]),
+ operands[1]);
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ src = gen_rtx (MULT, SImode,
+ copy_to_mode_reg (SImode, operands[1]),
+ operands[2]);
+ else src = 0;
+
+ if (src)
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], src));
+ else
+ emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
+ gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (MULT, SImode, operands[1], operands[2])),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 8)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 9)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 12)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 13)))));
+ DONE;
+}")
+
+(define_expand "umulsi3"
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (umult:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "
+{
+ rtx src;
+
+ if (GET_CODE (operands[1]) == CONST_INT)
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_move_insn (operands[0],
+ gen_rtx (CONST_INT, VOIDmode,
+ (unsigned)INTVAL (operands[1]) * (unsigned)INTVAL (operands[2])));
+ DONE;
+ }
+ else
+ src = gen_rtx (UMULT, SImode,
+ copy_to_mode_reg (SImode, operands[2]),
+ operands[1]);
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ src = gen_rtx (UMULT, SImode,
+ copy_to_mode_reg (SImode, operands[1]),
+ operands[2]);
+ else src = 0;
+
+ if (src)
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], src));
+ else
+ emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
+ gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (UMULT, SImode, operands[1], operands[2])),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 8)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 9)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 12)),
+ gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 13)))));
+ DONE;
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ ""
+ "* return output_mul_by_constant (insn, operands, 0);")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umult:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ ""
+ "* return output_mul_by_constant (insn, operands, 1);")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "general_operand" "%r")
+ (match_operand:SI 2 "general_operand" "r")))
+ (clobber (reg:SI 8))
+ (clobber (reg:SI 9))
+ (clobber (reg:SI 12))
+ (clobber (reg:SI 13))]
+ ""
+ "* return output_mul_insn (operands, 0);")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umult:SI (match_operand:SI 1 "general_operand" "%r")
+ (match_operand:SI 2 "general_operand" "r")))
+ (clobber (reg:SI 8))
+ (clobber (reg:SI 9))
+ (clobber (reg:SI 12))
+ (clobber (reg:SI 13))]
+ ""
+ "* return output_mul_insn (operands, 1);")
+
+;; this pattern is needed because cse may eliminate the multiplication,
+;; but leave the clobbers behind.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "general_operand" "g"))
+ (clobber (reg:SI 8))
+ (clobber (reg:SI 9))
+ (clobber (reg:SI 12))
+ (clobber (reg:SI 13))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (SMALL_INT (operands[1]))
+ return \"mov %1,%0\";
+ return \"sethi %%hi(%1),%0\;or %%lo(%1),%0,%0\";
+ }
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld %1,%0\";
+ return \"mov %1,%0\";
+}")
+
+;; In case constant factor turns out to be -1.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "general_operand" "rI")))
+ (clobber (reg:SI 8))
+ (clobber (reg:SI 9))
+ (clobber (reg:SI 12))
+ (clobber (reg:SI 13))]
+ ""
+ "sub %%g0,%1,%0")
+
+;;- and instructions (with compliment also)
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "arith32_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]) || SMALL_INT (operands[2]))
+ return \"and %1,%2,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;and %1,%%g1,%0\";
+}")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "andn %1,%2,%0")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "arith32_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]) || SMALL_INT (operands[2]))
+ return \"or %1,%2,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;or %1,%%g1,%0\";
+}")
+
+(define_insn "iorcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "register_operand" "r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "orn %1,%2,%0")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "arith32_operand" "%r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (REG_P (operands[2]) || SMALL_INT (operands[2]))
+ return \"xor %1,%2,%0\";
+ cc_status.flags &= ~CC_KNOW_HI_G1;
+ return \"sethi %%hi(%2),%%g1\;or %%lo(%2),%%g1,%%g1\;xor %1,%%g1,%0\";
+}")
+
+(define_insn "xorcbsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "register_operand" "r")
+ (not:SI (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "xnor %1,%2,%0")
+
+;; We cannot use the "neg" pseudo insn because the Sun assembler
+;; does not know how to make it work for constants.
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "sub %%g0,%1,%0")
+
+;; We cannot use the "not" pseudo insn because the Sun assembler
+;; does not know how to make it work for constants.
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "xnor %%g0,%1,%0")
+
+;; Floating point arithmetic instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "faddd %1,%2,%0")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fadds %1,%2,%0")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (minus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fsubd %1,%2,%0")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (minus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fsubs %1,%2,%0")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fmuld %1,%2,%0")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fmuls %1,%2,%0")
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ ""
+ "fdivd %1,%2,%0")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ ""
+ "fdivs %1,%2,%0")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ output_asm_insn (\"fnegs %1,%0\", operands);
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ {
+ operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"fmovs %1,%0\", operands);
+ }
+ return \"\";
+}")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "fnegs %1,%0")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+{
+ output_asm_insn (\"fabss %1,%0\", operands);
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ {
+ operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
+ output_asm_insn (\"fmovs %1,%0\", operands);
+ }
+ return \"\";
+}")
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "fabss %1,%0")
+
+;; Shift instructions
+
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ ""
+ "*
+{
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\";
+ }
+ return \"ldsb %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (const_int 24)))]
+ ""
+ "*
+{
+ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
+ {
+ cc_status.flags |= CC_KNOW_HI_G1;
+ cc_status.mdep = XEXP (operands[1], 0);
+ return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\";
+ }
+ return \"ldub %1,%0\";
+}")
+
+;;- arithmetic shift instructions
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
+ return \"sll %1,%2,%0\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
+ return \"sra %1,%2,%0\";
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith32_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >= 32)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 31);
+ return \"srl %1,%2,%0\";
+}")
+
+;; Unconditional and other jump instructions
+;; Note that for the Sparc, by setting the annul bit on an unconditional
+;; branch, the following insn is never executed. This saves us a nop,
+;; but requires a debugger which can handle annuled branches.
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ extern int optimize;
+ extern int flag_no_peephole;
+
+ if (optimize && !flag_no_peephole)
+ return \"b,a %l0\";
+ return \"b %l0\;nop\";
+}")
+
+;; Peephole optimizers recognize a few simple cases when delay insns are safe.
+;; Complex ones are up front. Simple ones after.
+
+;; This pattern is just like the following one, but matches when there
+;; is a jump insn after the "delay" insn. Without this pattern, we
+;; de-optimize that case.
+
+(define_peephole
+ [(set (pc) (match_operand 0 "" ""))
+ (set (match_operand:SI 1 "" "")
+ (match_operand:SI 2 "" ""))
+ (set (pc) (label_ref (match_operand 3 "" "")))]
+ "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 2)"
+ "*
+{
+ rtx xoperands[2];
+ rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]);
+ rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
+ rtx label, head;
+ int parity;
+
+ if (GET_CODE (XEXP (operands[0], 1)) == PC)
+ {
+ parity = 1;
+ label = XEXP (XEXP (operands[0], 2), 0);
+ }
+ else
+ {
+ parity = 0;
+ label = XEXP (XEXP (operands[0], 1), 0);
+ }
+ xoperands[0] = XEXP (operands[0], 0);
+ xoperands[1] = label;
+
+ head = next_real_insn_no_labels (label);
+
+ /* If at the target of this label we set the condition codes,
+ and the condition codes are already set for that value,
+ advance, if we can, to the following insn. */
+ if (GET_CODE (PATTERN (head)) == SET
+ && GET_CODE (SET_DEST (PATTERN (head))) == CC0
+ && cc_status.value2 == SET_SRC (PATTERN (head)))
+ {
+ rtx nhead = next_real_insn_no_labels (head);
+ if (nhead
+ && GET_CODE (nhead) == INSN
+ && GET_CODE (PATTERN (nhead)) == SET
+ && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)),
+ GET_MODE (SET_DEST (PATTERN (nhead))))
+ && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode)
+ /* Moves between FP regs and CPU regs are two insns. */
+ && !(GET_CODE (SET_SRC (PATTERN (nhead))) == REG
+ && GET_CODE (SET_DEST (PATTERN (nhead))) == REG
+ && (FP_REG_P (SET_SRC (PATTERN (nhead)))
+ != FP_REG_P (SET_DEST (PATTERN (nhead))))))
+ {
+ head = nhead;
+ }
+ }
+
+ /* Output the branch instruction first. */
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ {
+ if (parity)
+ output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands);
+ }
+ else if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ {
+ if (parity)
+ output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands);
+ }
+ else
+ {
+ if (parity)
+ output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands);
+ }
+
+ /* Now steal the first insn of the target. */
+ output_eager_then_insn (head, operands);
+
+ XVECEXP (PATTERN (insn), 0, 0) = XVECEXP (PATTERN (insn), 0, 1);
+ XVECEXP (PATTERN (insn), 0, 1) = XVECEXP (PATTERN (insn), 0, 2);
+
+ return output_delayed_branch (\"b %l3 ! eager2\", operands, insn);
+}")
+
+;; Here is a peephole which recognizes where delay insns can be made safe:
+;; (1) following a conditional branch, if the target of the conditional branch
+;; has only one user (this insn), move the first insn into our delay slot
+;; and emit an annulled branch.
+;; (2) following a conditional branch, if we can execute the fall-through
+;; insn without risking any evil effects, then do that instead of a nop.
+
+(define_peephole
+ [(set (pc) (match_operand 0 "" ""))
+ (set (match_operand:SI 1 "" "")
+ (match_operand:SI 2 "" ""))]
+ "TARGET_EAGER && operands_satisfy_eager_branch_peephole (operands, 1)"
+ "*
+{
+ rtx xoperands[2];
+ rtx pat = gen_rtx (SET, VOIDmode, operands[1], operands[2]);
+ rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
+ rtx label, head, prev = (rtx)1;
+ int parity;
+
+ if (GET_CODE (XEXP (operands[0], 1)) == PC)
+ {
+ parity = 1;
+ label = XEXP (XEXP (operands[0], 2), 0);
+ }
+ else
+ {
+ parity = 0;
+ label = XEXP (XEXP (operands[0], 1), 0);
+ }
+ xoperands[0] = XEXP (operands[0], 0);
+ xoperands[1] = label;
+
+ if (LABEL_NUSES (label) == 1)
+ {
+ prev = PREV_INSN (label);
+ while (prev
+ && (GET_CODE (prev) == NOTE
+ || (GET_CODE (prev) == INSN
+ && (GET_CODE (PATTERN (prev)) == CLOBBER
+ || GET_CODE (PATTERN (prev)) == USE))))
+ prev = PREV_INSN (prev);
+ if (prev == 0
+ || GET_CODE (prev) == BARRIER)
+ {
+ prev = 0;
+ head = next_real_insn_no_labels (label);
+ }
+ }
+ if (prev == 0
+ && head != 0
+ && ! INSN_DELETED_P (head)
+ && GET_CODE (head) == INSN
+ && GET_CODE (PATTERN (head)) == SET
+ && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
+ GET_MODE (SET_DEST (PATTERN (head))))
+ && strict_single_insn_op_p (SET_DEST (PATTERN (head)), VOIDmode)
+ /* Moves between FP regs and CPU regs are two insns. */
+ && !(GET_CODE (SET_SRC (PATTERN (head))) == REG
+ && GET_CODE (SET_DEST (PATTERN (head))) == REG
+ && (FP_REG_P (SET_SRC (PATTERN (head)))
+ != FP_REG_P (SET_DEST (PATTERN (head))))))
+ {
+ /* If at the target of this label we set the condition codes,
+ and the condition codes are already set for that value,
+ advance, if we can, to the following insn. */
+ if (GET_CODE (PATTERN (head)) == SET
+ && GET_CODE (SET_DEST (PATTERN (head))) == CC0
+ && cc_status.value2 == SET_SRC (PATTERN (head)))
+ {
+ rtx nhead = next_real_insn_no_labels (head);
+ if (nhead
+ && GET_CODE (nhead) == INSN
+ && GET_CODE (PATTERN (nhead)) == SET
+ && strict_single_insn_op_p (SET_SRC (PATTERN (nhead)),
+ GET_MODE (SET_DEST (nhead)))
+ && strict_single_insn_op_p (SET_DEST (PATTERN (nhead)), VOIDmode)
+ /* Moves between FP regs and CPU regs are two insns. */
+ && !(GET_CODE (SET_SRC (PATTERN (nhead))) == REG
+ && GET_CODE (SET_DEST (PATTERN (nhead))) == REG
+ && (FP_REG_P (SET_SRC (PATTERN (nhead)))
+ != FP_REG_P (SET_DEST (PATTERN (nhead))))))
+ head = nhead;
+ }
+
+ /* Output the branch instruction first. */
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ {
+ if (parity)
+ output_asm_insn (\"fb%F0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"fb%C0,a %l1 ! eager\", xoperands);
+ }
+ else if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ {
+ if (parity)
+ output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands);
+ }
+ else
+ {
+ if (parity)
+ output_asm_insn (\"b%N0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%C0,a %l1 ! eager\", xoperands);
+ }
+
+ /* Now steal the first insn of the target. */
+ output_eager_then_insn (head, operands);
+ }
+ else
+ {
+ /* Output the branch instruction first. */
+ if (cc_prev_status.flags & CC_IN_FCCR)
+ {
+ if (parity)
+ output_asm_insn (\"fb%F0 %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"fb%C0 %l1 ! eager\", xoperands);
+ }
+ else if (cc_prev_status.flags & CC_NO_OVERFLOW)
+ {
+ if (parity)
+ output_asm_insn (\"b%U0,a %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%I0,a %l1 ! eager\", xoperands);
+ }
+ else
+ {
+ if (parity)
+ output_asm_insn (\"b%N0 %l1 ! eager\", xoperands);
+ else
+ output_asm_insn (\"b%C0 %l1 ! eager\", xoperands);
+ }
+ }
+ return output_delay_insn (delay_insn);
+}")
+
+;; Here are two simple peepholes which fill the delay slot of
+;; an unconditional branch.
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (set (pc) (label_ref (match_operand 2 "" "")))]
+ "single_insn_extra_test (operands[0], operands[1])"
+ "* return output_delayed_branch (\"b %l2\", operands, insn);")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+ (set (pc) (label_ref (match_operand 2 "" "")))]
+ ""
+ "* return output_delayed_branch (\"b %l2\", operands, insn);")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp %0\;nop")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (parallel [(set (pc) (match_operand:SI 2 "register_operand" "r"))
+ (use (label_ref (match_operand 3 "" "")))])]
+ "REGNO (operands[0]) != REGNO (operands[2])
+ && single_insn_extra_test (operands[0], operands[1])"
+ "* return output_delayed_branch (\"jmp %2\", operands, insn);")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+ (parallel [(set (pc) (match_operand:SI 2 "register_operand" "r"))
+ (use (label_ref (match_operand 3 "" "")))])]
+ ""
+ "* return output_delayed_branch (\"jmp %2\", operands, insn);")
+
+;;- jump to subroutine
+(define_expand "call"
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))]
+ ;; operand[2] is next_arg_register
+ ""
+ "
+{
+ rtx fn_rtx, nregs_rtx;
+
+ if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[0], 0)) == REG)
+ {
+ rtx g1_rtx = gen_rtx (REG, SImode, 1);
+ emit_move_insn (g1_rtx, XEXP (operands[0], 0));
+ fn_rtx = gen_rtx (MEM, SImode, g1_rtx);
+ }
+ else
+ fn_rtx = operands[0];
+
+ /* Count the number of parameter registers being used by this call.
+ if that argument is NULL, it means we are using them all, which
+ means 6 on the sparc. */
+#if 0
+ if (operands[2])
+ nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
+ else
+ nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
+#else
+ nregs_rtx = const0_rtx;
+#endif
+
+ emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
+ gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
+ gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)))));
+ DONE;
+}")
+
+(define_insn ""
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))
+ (use (reg:SI 31))]
+ ;;- Don't use operand 1 for most machines.
+ "CONSTANT_P (XEXP (operands[0], 0))
+ || GET_CODE (XEXP (operands[0], 0)) == REG"
+ "*
+{
+ /* strip the MEM. */
+ operands[0] = XEXP (operands[0], 0);
+ CC_STATUS_INIT;
+ if (TARGET_SUN_ASM && GET_CODE (operands[0]) == REG)
+ return \"jmpl %a0,%%o7\;nop\";
+ return \"call %a0,%1\;nop\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (parallel [(call (match_operand:SI 2 "memory_operand" "m")
+ (match_operand 3 "" "i"))
+ (use (reg:SI 31))])]
+ ;;- Don't use operand 1 for most machines.
+ "! reg_mentioned_p (operands[0], operands[2])
+ && single_insn_extra_test (operands[0], operands[1])"
+ "*
+{
+ /* strip the MEM. */
+ operands[2] = XEXP (operands[2], 0);
+ if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG)
+ return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn);
+ return output_delayed_branch (\"call %a2,%3\", operands, insn);
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+ (parallel [(call (match_operand:SI 2 "memory_operand" "m")
+ (match_operand 3 "" "i"))
+ (use (reg:SI 31))])]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[2] = XEXP (operands[2], 0);
+ if (TARGET_SUN_ASM && GET_CODE (operands[2]) == REG)
+ return output_delayed_branch (\"jmpl %a2,%%o7\", operands, insn);
+ return output_delayed_branch (\"call %a2,%3\", operands, insn);
+}")
+
+(define_expand "call_value"
+ [(set (match_operand 0 "register_operand" "=rf")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))]
+ ;; operand 3 is next_arg_register
+ ""
+ "
+{
+ rtx fn_rtx, nregs_rtx;
+ rtvec vec;
+
+ if (TARGET_SUN_ASM && GET_CODE (XEXP (operands[1], 0)) == REG)
+ {
+ rtx g1_rtx = gen_rtx (REG, SImode, 1);
+ emit_move_insn (g1_rtx, XEXP (operands[1], 0));
+ fn_rtx = gen_rtx (MEM, SImode, g1_rtx);
+ }
+ else
+ fn_rtx = operands[1];
+
+#if 0
+ if (operands[3])
+ nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[3]) - 8);
+ else
+ nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
+#else
+ nregs_rtx = const0_rtx;
+#endif
+
+ vec = gen_rtvec (2,
+ gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx)),
+ gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
+
+ emit_call_insn (gen_rtx (PARALLEL, VOIDmode, vec));
+ DONE;
+}")
+
+(define_insn ""
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))
+ (use (reg:SI 31))]
+ ;;- Don't use operand 2 for most machines.
+ "CONSTANT_P (XEXP (operands[1], 0))
+ || GET_CODE (XEXP (operands[1], 0)) == REG"
+ "*
+{
+ /* strip the MEM. */
+ operands[1] = XEXP (operands[1], 0);
+ CC_STATUS_INIT;
+ if (TARGET_SUN_ASM && GET_CODE (operands[1]) == REG)
+ return \"jmpl %a1,%%o7\;nop\";
+ return \"call %a1,%2\;nop\";
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "single_insn_src_p" "p"))
+ (parallel [(set (match_operand 2 "" "=rf")
+ (call (match_operand:SI 3 "memory_operand" "m")
+ (match_operand 4 "" "i")))
+ (use (reg:SI 31))])]
+ ;;- Don't use operand 4 for most machines.
+ "! reg_mentioned_p (operands[0], operands[3])
+ && single_insn_extra_test (operands[0], operands[1])"
+ "*
+{
+ /* strip the MEM. */
+ operands[3] = XEXP (operands[3], 0);
+ if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG)
+ return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn);
+ return output_delayed_branch (\"call %a3,%4\", operands, insn);
+}")
+
+(define_peephole
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+ (parallel [(set (match_operand 2 "" "=rf")
+ (call (match_operand:SI 3 "memory_operand" "m")
+ (match_operand 4 "" "i")))
+ (use (reg:SI 31))])]
+ ;;- Don't use operand 4 for most machines.
+ ""
+ "*
+{
+ /* strip the MEM. */
+ operands[3] = XEXP (operands[3], 0);
+ if (TARGET_SUN_ASM && GET_CODE (operands[3]) == REG)
+ return output_delayed_branch (\"jmpl %a3,%%o7\", operands, insn);
+ return output_delayed_branch (\"call %a3,%4\", operands, insn);
+}")
+
+(define_insn "return"
+ [(return)]
+ "! TARGET_EPILOGUE"
+ "ret\;restore")
+
+(define_peephole
+ [(set (reg:SI 24)
+ (match_operand:SI 0 "reg_or_0_operand" "rJ"))
+ (return)]
+ "! TARGET_EPILOGUE"
+ "ret\;restore %r0,0x0,%%o0")
+
+(define_peephole
+ [(set (reg:SI 24)
+ (plus:SI (match_operand:SI 0 "register_operand" "r%")
+ (match_operand:SI 1 "arith_operand" "rI")))
+ (return)]
+ "! TARGET_EPILOGUE"
+ "ret\;restore %r0,%1,%%o0")
+
+(define_peephole
+ [(set (reg:SI 24)
+ (minus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "small_int" "I")))
+ (return)]
+ "! TARGET_EPILOGUE"
+ "ret\;restore %0,-(%1),%%o0")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
+
diff --git a/gcc-1.40/config/spur.md b/gcc-1.40/config/spur.md
new file mode 100644
index 0000000..62070be
--- /dev/null
+++ b/gcc-1.40/config/spur.md
@@ -0,0 +1,1119 @@
+;;- Machine description for SPUR chip for GNU C compiler
+;; Copyright (C) 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+;;- Operand classes for the register allocator:
+
+;; Compare instructions.
+;; This pattern is used for generating an "insn"
+;; which does just a compare and sets a (fictitious) condition code.
+
+;; The actual SPUR insns are compare-and-conditional-jump.
+;; The define_peephole's below recognize the combinations of
+;; compares and jumps, and output each pair as a single assembler insn.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+;; This controls RTL generation and register allocation.
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonmemory_operand" "rK")
+ (match_operand:SI 1 "nonmemory_operand" "rK")))]
+ ""
+ "*
+{
+ cc_status.value1 = operands[0], cc_status.value2 = operands[1];
+ return \"\";
+}")
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+;; We have to have this because cse can optimize the previous pattern
+;; into this one.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "*
+{
+ cc_status.value1 = operands[0], cc_status.value2 = const0_rtx;
+ return \"\";
+}")
+
+
+;; These control RTL generation for conditional jump insns
+;; and match them for register allocation.
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
+
+;; These match inverted jump insns for register allocation.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
+
+;; Move instructions
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r,m")
+ (match_operand:SI 1 "general_operand" "rmi,rJ"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st_32 %r1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld_32 %0,%1\;nop\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"add_nt %0,%1,$0\";
+ if (GET_CODE (operands[1]) == SYMBOL_REF && operands[1]->unchanging)
+ return \"add_nt %0,r24,$(%1-0b)\";
+ return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "ld_32 %0,%1,%2\;nop")
+
+;; Generate insns for moving single bytes.
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[1] = copy_to_reg (operands[1]);
+
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ rtx tem = gen_reg_rtx (SImode);
+ rtx addr = force_reg (SImode, XEXP (operands[1], 0));
+ rtx subreg;
+
+ emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
+ if (GET_CODE (operands[0]) == SUBREG)
+ subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[0]),
+ SUBREG_WORD (operands[0]));
+ else
+ subreg = gen_rtx (SUBREG, SImode, operands[0], 0);
+
+ emit_insn (gen_rtx (SET, VOIDmode, subreg,
+ gen_rtx (ZERO_EXTRACT, SImode, tem,
+ gen_rtx (CONST_INT, VOIDmode, 8),
+ addr)));
+ }
+ else if (GET_CODE (operands[0]) == MEM)
+ {
+ rtx tem = gen_reg_rtx (SImode);
+ rtx addr = force_reg (SImode, XEXP (operands[0], 0));
+ rtx subreg;
+
+ emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
+ if (! CONSTANT_ADDRESS_P (operands[1]))
+ {
+ if (GET_CODE (operands[1]) == SUBREG)
+ subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ subreg = gen_rtx (SUBREG, SImode, operands[1], 0);
+ }
+
+ emit_insn (gen_rtx (SET, VOIDmode,
+ gen_rtx (ZERO_EXTRACT, SImode, tem,
+ gen_rtx (CONST_INT, VOIDmode, 8),
+ addr),
+ subreg));
+ emit_move_insn (gen_rtx (MEM, SImode, addr), tem);
+ }
+ else
+ {
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ }
+ DONE;
+}")
+
+;; Recognize insns generated for moving single bytes.
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=r,m")
+ (match_operand:QI 1 "general_operand" "rmi,r"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st_32 %1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld_32 %0,%1\;nop\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"add_nt %0,%1,$0\";
+ return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 8)
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "extract %0,%1,%2")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (const_int 8)
+ (match_operand:SI 1 "nonmemory_operand" "rI"))
+ (match_operand:SI 2 "nonmemory_operand" "ri"))]
+ ""
+ "wr_insert %1\;insert %0,%0,%2")
+
+;; Constant propagation can optimize the previous pattern into this pattern.
+;[Not any more. It could when the position-operand contains a MULT.]
+
+;(define_insn ""
+; [(set (zero_extract:QI (match_operand:SI 0 "register_operand" "+r")
+; (const_int 8)
+; (match_operand:SI 1 "immediate_operand" "I"))
+; (match_operand:QI 2 "register_operand" "r"))]
+; "GET_CODE (operands[1]) == CONST_INT
+; && INTVAL (operands[1]) % 8 == 0
+; && (unsigned) INTVAL (operands[1]) < 32"
+; "*
+;{
+; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
+; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
+;}")
+
+;; The three define_expand patterns on this page
+;; serve as subroutines of "movhi".
+
+;; Generate code to fetch an aligned halfword from memory.
+;; Operand 0 is the destination register (HImode).
+;; Operand 1 is the memory address (SImode).
+;; Operand 2 is a temporary (SImode).
+;; Operand 3 is a temporary (SImode).
+;; Operand 4 is a temporary (QImode).
+
+;; Operand 5 is an internal temporary (HImode).
+
+(define_expand "loadhi"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 1 "register_operand" "")))
+ ;; Extract the low byte.
+ (set (subreg:SI (match_dup 5) 0)
+ (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 1)))
+ ;; Form address of high byte.
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (match_dup 1) (const_int 1)))
+ ;; Extract the high byte.
+ (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
+ (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)))
+ ;; Put the high byte in with the low one.
+ (set (zero_extract:SI (match_dup 5) (const_int 8) (const_int 1))
+ (subreg:SI (match_dup 4) 0))
+ (set (match_operand:HI 0 "register_operand" "") (match_dup 5))]
+ ""
+ "operands[5] = gen_reg_rtx (HImode);")
+
+;; Generate code to store an aligned halfword into memory.
+;; Operand 0 is the destination address (SImode).
+;; Operand 1 is the source register (HImode, not constant).
+;; Operand 2 is a temporary (SImode).
+;; Operand 3 is a temporary (SImode).
+;; Operand 4 is a temporary (QImode).
+
+;; Operand 5 is an internal variable made from operand 1.
+
+(define_expand "storehi"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 0 "register_operand" "")))
+ ;; Insert the low byte.
+ (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
+ (match_dup 5))
+ ;; Form address of high byte.
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (match_dup 0) (const_int 1)))
+ ;; Extract the high byte from the source.
+ (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
+ (zero_extract:SI (match_operand:HI 1 "register_operand" "")
+ (const_int 8) (const_int 1)))
+ ;; Store high byte into the memory word
+ (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
+ (subreg:SI (match_dup 4) 0))
+ ;; Put memory word back into memory.
+ (set (mem:SI (match_dup 0))
+ (match_dup 2))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[5] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ operands[5] = gen_rtx (SUBREG, SImode, operands[1], 0);
+}")
+
+;; Like storehi but operands[1] is a CONST_INT.
+
+(define_expand "storeinthi"
+ [(set (match_operand:SI 2 "register_operand" "")
+ (mem:SI (match_operand:SI 0 "register_operand" "")))
+ ;; Insert the low byte.
+ (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
+ (match_dup 5))
+ ;; Form address of high byte.
+ (set (match_operand:SI 3 "register_operand" "")
+ (plus:SI (match_dup 0) (const_int 1)))
+ ;; Store high byte into the memory word
+ (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
+ (match_dup 6))
+ ;; Put memory word back into memory.
+ (set (mem:SI (match_dup 0))
+ (match_dup 2))]
+ ""
+ " operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 255);
+ operands[6] = gen_rtx (CONST_INT, VOIDmode,
+ (INTVAL (operands[1]) >> 8) & 255);
+")
+
+;; Main entry for generating insns to move halfwords.
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ operands[1] = copy_to_reg (operands[1]);
+
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ rtx insn =
+ emit_insn (gen_loadhi (operands[0],
+ force_reg (SImode, XEXP (operands[1], 0)),
+ gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+ gen_reg_rtx (QImode)));
+ /* Tell cse what value the loadhi produces, so it detect duplicates. */
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1],
+ REG_NOTES (insn));
+ }
+ else if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (operands[1]) == CONST_INT)
+ emit_insn (gen_storeinthi (force_reg (SImode, XEXP (operands[0], 0)),
+ operands[1],
+ gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+ gen_reg_rtx (QImode)));
+ else
+ {
+ if (CONSTANT_P (operands[1]))
+ operands[1] = force_reg (HImode, operands[1]);
+ emit_insn (gen_storehi (force_reg (SImode, XEXP (operands[0], 0)),
+ operands[1],
+ gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+ gen_reg_rtx (QImode)));
+ }
+ }
+ else
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ DONE;
+}")
+
+;; Recognize insns generated for moving halfwords.
+;; (Note that the extract and insert patterns for single-byte moves
+;; are also involved in recognizing some of the insns used for this purpose.)
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=r,m")
+ (match_operand:HI 1 "general_operand" "rmi,r"))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st_32 %1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld_32 %0,%1\;nop\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"add_nt %0,%1,$0\";
+ return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
+ (const_int 8)
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "extract %0,%1,%2")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:HI 0 "register_operand" "+r")
+ (const_int 8)
+ (match_operand:SI 1 "nonmemory_operand" "rI"))
+ (match_operand:SI 2 "nonmemory_operand" "ri"))]
+ ""
+ "wr_insert %1\;insert %0,%0,%2")
+
+;; Constant propagation can optimize the previous pattern into this pattern.
+
+;(define_insn ""
+; [(set (zero_extract:QI (match_operand:HI 0 "register_operand" "+r")
+; (const_int 8)
+; (match_operand:SI 1 "immediate_operand" "I"))
+; (match_operand:QI 2 "register_operand" "r"))]
+; "GET_CODE (operands[1]) == CONST_INT
+; && INTVAL (operands[1]) % 8 == 0
+; && (unsigned) INTVAL (operands[1]) < 32"
+; "*
+;{
+; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
+; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
+;}")
+
+;; This pattern forces (set (reg:DF ...) (const_double ...))
+;; to be reloaded by putting the constant into memory.
+;; It must come before the more general movdf pattern.
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=&r,f,&o")
+ (match_operand:DF 1 "" "mG,m,G"))]
+ "GET_CODE (operands[1]) == CONST_DOUBLE"
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ return output_fp_move_double (operands);
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
+ {
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"add_nt %0,r0,$0\;add_nt %1,r0,$0\";
+ }
+ if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"st_32 r0,%0\;st_32 r0,%1\";
+ }
+ return output_move_double (operands);
+}
+")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=r,&r,m,?f,?rm")
+ (match_operand:DF 1 "general_operand" "r,m,r,rfm,f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}
+")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=r,&r,m,?f,?rm")
+ (match_operand:DI 1 "general_operand" "r,m,r,rfm,f"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+ return output_fp_move_double (operands);
+ return output_move_double (operands);
+}
+")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=rf,m")
+ (match_operand:SF 1 "general_operand" "rfm,rf"))]
+ ""
+ "*
+{
+ if (FP_REG_P (operands[0]))
+ {
+ if (FP_REG_P (operands[1]))
+ return \"fmov %0,%1\";
+ if (GET_CODE (operands[1]) == REG)
+ {
+ rtx xoperands[2];
+ int offset = - get_frame_size () - 8;
+ xoperands[1] = operands[1];
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+ output_asm_insn (\"st_32 %1,r25,%0\", xoperands);
+ xoperands[1] = operands[0];
+ output_asm_insn (\"ld_sgl %1,r25,%0\;nop\", xoperands);
+ return \"\";
+ }
+ return \"ld_sgl %0,%1\;nop\";
+ }
+ if (FP_REG_P (operands[1]))
+ {
+ if (GET_CODE (operands[0]) == REG)
+ {
+ rtx xoperands[2];
+ int offset = - get_frame_size () - 8;
+ xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+ xoperands[1] = operands[1];
+ output_asm_insn (\"st_sgl %1,r25,%0\", xoperands);
+ xoperands[1] = operands[0];
+ output_asm_insn (\"ld_32 %1,r25,%0\;nop\", xoperands);
+ return \"\";
+ }
+ return \"st_sgl %1,%0\";
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ return \"st_32 %r1,%0\";
+ if (GET_CODE (operands[1]) == MEM)
+ return \"ld_32 %0,%1\;nop\";
+ if (GET_CODE (operands[1]) == REG)
+ return \"add_nt %0,%1,$0\";
+ return \"add_nt %0,r0,%1\";
+}")
+
+;;- truncation instructions
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "add_nt %0,%1,$0")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "add_nt %0,%1,$0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "add_nt %0,%1,$0")
+
+;;- zero extension instructions
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
+ ;; This constant is invalid, but reloading will handle it.
+ ;; It's useless to generate here the insns to construct it
+ ;; because constant propagation would simplify them anyway.
+ (match_dup 2)))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+ operands[2] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI
+ (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "extract %0,%1,$0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "extract %0,%1,$0")
+
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_expand "extendhisi2"
+ [(set (match_dup 2)
+ (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
+ (match_dup 4)))
+ (set (match_dup 3) (plus:SI (match_dup 2) (match_dup 5)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (xor:SI (match_dup 3) (match_dup 5)))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+ operands[2] = gen_reg_rtx (SImode);
+ operands[3] = gen_reg_rtx (SImode);
+ operands[4] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
+ operands[5] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, -32768));
+}")
+
+(define_expand "extendqihi2"
+ [(set (match_dup 2)
+ (and:HI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
+ (const_int 255)))
+ (set (match_dup 3)
+ (plus:SI (match_dup 2) (const_int -128)))
+ (set (match_operand:HI 0 "register_operand" "")
+ (xor:SI (match_dup 3) (const_int -128)))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ operands[1] = gen_rtx (SUBREG, HImode, operands[1], 0);
+
+ operands[2] = gen_reg_rtx (HImode);
+ operands[3] = gen_reg_rtx (HImode);
+}")
+
+(define_expand "extendqisi2"
+ [(set (match_dup 2)
+ (and:SI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
+ (const_int 255)))
+ (set (match_dup 3) (plus:SI (match_dup 2) (const_int -128)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (xor:SI (match_dup 3) (const_int -128)))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == SUBREG)
+ operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+ SUBREG_WORD (operands[1]));
+ else
+ operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+ operands[2] = gen_reg_rtx (SImode);
+ operands[3] = gen_reg_rtx (SImode);
+}")
+
+;;- arithmetic instructions
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "add %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "big_immediate_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (INTVAL (operands[2]) + 0x8000000) < 0x10000000"
+ "*
+{
+ return
+ output_add_large_offset (operands[0], operands[1], INTVAL (operands[2]));
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "sub %0,%1,%2")
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "and %0,%1,%2")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "or %0,%1,%2")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+ (match_operand:SI 2 "nonmemory_operand" "rI")))]
+ ""
+ "xor %0,%1,%2")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "nonmemory_operand" "rI")))]
+ ""
+ "sub %0,r0,%1")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "xor %0,%1,$-1")
+
+;; Floating point arithmetic instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (plus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fadd %0,%1,%2")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (plus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fadd %0,%1,%2")
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (minus:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fsub %0,%1,%2")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (minus:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fsub %0,%1,%2")
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fmul %0,%1,%2")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mult:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fmul %0,%1,%2")
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fdiv %0,%1,%2")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_FPU"
+ "fdiv %0,%1,%2")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
+ "TARGET_FPU"
+ "fneg %0,%1")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
+ "TARGET_FPU"
+ "fneg %0,%1")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
+ "TARGET_FPU"
+ "fabs %0,%1")
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
+ "TARGET_FPU"
+ "fabs %0,%1")
+
+;; Shift instructions
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "I")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{
+ unsigned int amount = INTVAL (operands[2]);
+
+ switch (amount)
+ {
+ case 0:
+ return \"add_nt %0,%1,$0\";
+ case 1:
+ return \"sll %0,%1,$1\";
+ case 2:
+ return \"sll %0,%1,$2\";
+ default:
+ output_asm_insn (\"sll %0,%1,$3\", operands);
+
+ for (amount -= 3; amount >= 3; amount -= 3)
+ output_asm_insn (\"sll %0,%0,$3\", operands);
+
+ if (amount > 0)
+ output_asm_insn (amount == 1 ? \"sll %0,%0,$1\" : \"sll %0,%0,$2\",
+ operands);
+ return \"\";
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "I")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{
+ unsigned int amount = INTVAL (operands[2]);
+
+ if (amount == 0)
+ return \"add_nt %0,%1,$0\";
+ else
+ output_asm_insn (\"sra %0,%1,$1\", operands);
+
+ for (amount -= 1; amount > 0; amount -= 1)
+ output_asm_insn (\"sra %0,%0,$1\", operands);
+
+ return \"\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "I")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{
+ unsigned int amount = INTVAL (operands[2]);
+
+ if (amount == 0)
+ return \"add_nt %0,%1,$0\";
+ else
+ output_asm_insn (\"srl %0,%1,$1\", operands);
+
+ for (amount -= 1; amount > 0; amount -= 1)
+ output_asm_insn (\"srl %0,%0,$1\", operands);
+
+ return \"\";
+}")
+
+(define_expand "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
+ FAIL;
+}")
+
+(define_expand "lshlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
+ FAIL;
+}")
+
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
+ FAIL;
+}")
+
+(define_expand "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) != CONST_INT
+ || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
+ FAIL;
+}")
+
+;; Unconditional and other jump instructions
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "jump %l0\;nop")
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jump_reg r0,%0\;nop")
+
+;;- jump to subroutine
+(define_insn "call"
+ [(call (match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "add_nt r2,%0\;call .+8\;jump_reg r0,r2\;nop")
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=g")
+ (call (match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;;- Don't use operand 1 for most machines.
+ ""
+ "add_nt r2,%1\;call .+8\;jump_reg r0,r2\;nop")
+
+;; A memory ref with constant address is not normally valid.
+;; But it is valid in a call insns. This pattern allows the
+;; loading of the address to combine with the call.
+(define_insn ""
+ [(call (mem:SI (match_operand:SI 0 "" "i"))
+ (match_operand:SI 1 "general_operand" "g"))]
+ ;;- Don't use operand 1 for most machines.
+ "GET_CODE (operands[0]) == SYMBOL_REF"
+ "call %0\;nop")
+
+(define_insn ""
+ [(set (match_operand 0 "" "=g")
+ (call (mem:SI (match_operand:SI 1 "" "i"))
+ (match_operand:SI 2 "general_operand" "g")))]
+ ;;- Don't use operand 1 for most machines.
+ "GET_CODE (operands[1]) == SYMBOL_REF"
+ "call %1\;nop")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
+
diff --git a/gcc-1.40/config/tahoe.md b/gcc-1.40/config/tahoe.md
new file mode 100644
index 0000000..a96dd45
--- /dev/null
+++ b/gcc-1.40/config/tahoe.md
@@ -0,0 +1,1497 @@
+;;- Machine description for GNU compiler
+;;- Tahoe version
+;; Copyright (C) 1989 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+; File: tahoe.md
+;
+; This port made at the University of Buffalo by Devon Bowen,
+; Dale Wiles and Kevin Zachmann.
+;
+; Mail bugs reports or fixes to: gcc@cs.buffalo.edu
+
+
+; movdi must call the output_move_double routine to move it around since
+; the tahoe doesn't efficiently support 8 bit moves.
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=g")
+ (match_operand:DI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return output_move_double (operands);
+}")
+
+
+; The trick in the movsi is accessing the contents of the sp register. The
+; tahoe doesn't allow you to access it directly so you have to access the
+; address of the top of the stack instead.
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ && no_labels_between_p (XEXP (link, 0), insn))
+ return \"incl %0\";
+ if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
+ {
+ if (push_operand (operands[0], SImode))
+ return \"pushab %a1\";
+ return \"movab %a1,%0\";
+ }
+ if (operands[1] == const0_rtx)
+ return \"clrl %0\";
+ if (push_operand (operands[0], SImode))
+ return \"pushl %1\";
+ if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 14)
+ return \"moval (sp),%0\";
+ return \"movl %1,%0\";
+}")
+
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ && no_labels_between_p (XEXP (link, 0), insn))
+ return \"incw %0\";
+ if (operands[1] == const0_rtx)
+ return \"clrw %0\";
+ return \"movw %1,%0\";
+}")
+
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clrb %0\";
+ return \"movb %1,%0\";
+}")
+
+
+; movsf has three cases since they can move from one place to another
+; or to/from the fpp and since different instructions are needed for
+; each case. The fpp related instructions don't set the flags properly.
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=g,=a,=g")
+ (match_operand:SF 1 "general_operand" "g,g,a"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ switch (which_alternative)
+ {
+ case 0:
+ return \"movl %1,%0\";
+ case 1:
+ return \"ldf %1\";
+ case 2:
+ return \"stf %0\";
+ }
+}")
+
+
+; movdf has a number of different cases. If it's going to or from
+; the fpp, use the special instructions to do it. If not, use the
+; output_move_double function.
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=a,=g,?=g")
+ (match_operand:DF 1 "general_operand" "g,a,g"))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ switch (which_alternative)
+ {
+ case 0:
+ return \"ldd %1\";
+ case 1:
+ if (push_operand (operands[0], DFmode))
+ return \"pushd\";
+ else
+ return \"std %0\";
+ case 2:
+ return output_move_double (operands);
+ }
+}")
+
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (plus:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incl %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == -1)
+ return \"decl %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subl2 $%n2,%0\";
+ return \"addl2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addl2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[1]) == REG)
+ {
+ if (push_operand (operands[0], SImode))
+ return \"pushab %c2(%1)\";
+ return \"movab %c2(%1),%0\";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subl3 $%n2,%1,%0\";
+ return \"addl3 %1,%2,%0\";
+}")
+
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (plus:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incw %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ return \"decw %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subw2 $%n2,%0\";
+ return \"addw2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addw2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subw3 $%n2,%1,%0\";
+ return \"addw3 %1,%2,%0\";
+}")
+
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (plus:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incb %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ return \"decb %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subb2 $%n2,%0\";
+ return \"addb2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addb2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subb3 $%n2,%1,%0\";
+ return \"addb3 %1,%2,%0\";
+}")
+
+
+; addsf3 can only add into the fpp register since the fpp is treated
+; as a separate unit in the machine. It also doesn't set the flags at
+; all.
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (plus:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"addf %2\";
+}")
+
+
+; adddf3 can only add into the fpp reg since the fpp is treated as a
+; separate entity. Doubles can only be read from a register or memory
+; since a double is not an immediate mode. Flags are not set by this
+; instruction.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (plus:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"addd %2\";
+}")
+
+
+; Subtraction from the sp (needed by the built in alloc funtion) needs
+; to be different since the sp cannot be directly read on the tahoe.
+; If it's a simple constant, you just use displacment. Otherwise, you
+; push the sp, and then do the subtraction off the stack.
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (minus:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decl %0\";
+ if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 14)
+ if (GET_CODE (operands[2]) == CONST_INT)
+ return \"movab %n2(sp),sp\";
+ else
+ return \"pushab (sp)\;subl3 %2,(sp),sp\";
+ return \"subl2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"clrl %0\";
+ return \"subl3 %2,%1,%0\";
+}")
+
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (minus:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decw %0\";
+ return \"subw2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"clrw %0\";
+ return \"subw3 %2,%1,%0\";
+}")
+
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (minus:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decb %0\";
+ return \"subb2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"clrb %0\";
+ return \"subb3 %2,%1,%0\";
+}")
+
+
+; subsf3 can only subtract into the fpp accumulator due to the way
+; the fpp reg is limited by the instruction set. This also doesn't
+; bother setting up flags.
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (minus:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"subf %2\";
+}")
+
+
+; subdf3 is set up to subtract into the fpp reg due to limitations
+; of the fpp instruction set. Doubles can not be immediate. This
+; instruction does not set the flags.
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (minus:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"subd %2\";
+}")
+
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (mult:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mull2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mull2 %1,%0\";
+ return \"mull3 %1,%2,%0\";
+}")
+
+
+; mulsf3 can only multiply into the fpp accumulator due to limitations
+; of the fpp. It also does not set the condition codes properly.
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (mult:SF (match_operand:SF 1 "register_operand" "%0")
+ (match_operand:SF 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"mulf %2\";
+}")
+
+
+; muldf3 can only multiply into the fpp reg since the fpp is limited
+; from the rest. Doubles may not be immediate mode. This does not set
+; the flags like GCC would expect.
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (mult:DF (match_operand:DF 1 "register_operand" "%0")
+ (match_operand:DF 2 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"muld %2\";
+}")
+
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (div:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"movl $1,%0\";
+ if (operands[1] == const0_rtx)
+ return \"clrl %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == -1)
+ return \"mnegl %1,%0\";
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"divl2 %2,%0\";
+ return \"divl3 %2,%1,%0\";
+}")
+
+
+; divsf3 must divide into the fpp accumulator. Flags are not set by
+; this instruction, so they are cleared.
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (div:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"divf %2\";
+}")
+
+
+; divdf3 also must divide into the fpp reg so optimization isn't
+; possible. Note that doubles cannot be immediate. The flags here
+; are not set correctly so they must be ignored.
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (div:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "general_operand" "rm")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"divd %2\";
+}")
+
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "andl3 %2,%1,%0")
+
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "andw3 %1,%2,%0")
+
+
+(define_insn "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "andb3 %1,%2,%0")
+
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ior:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "orl3 %2,%1,%0")
+
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (ior:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "orw3 %2,%1,%0")
+
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ior:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "orb3 %2,%1,%0")
+
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (xor:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "xorl3 %1,%2,%0")
+
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (xor:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "xorw3 %1,%2,%0")
+
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (xor:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "xorb3 %1,%2,%0")
+
+
+; Shifts on the tahoe are expensive, so try to do an add instead.
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
+ {
+ CC_STATUS_INIT;
+ return \"addl2 %0,%0\";
+ }
+ return \"shal %2,%1,%0\";
+}")
+
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ashiftrt:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "shar %2,%1,%0")
+
+
+; Shifts are very expensive, so try to do an add if possible.
+
+(define_insn "lshlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (lshift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
+ {
+ CC_STATUS_INIT;
+ return \"addl2 %0,%0\";
+ }
+ return \"shll %2,%1,%0\";
+}")
+
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (lshiftrt:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "shrl %2,%1,%0")
+
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (neg:SI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "mnegl %1,%0")
+
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (neg:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "mnegw %1,%0")
+
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (neg:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "mnegb %1,%0")
+
+
+; negsf2 can only negate the value already in the fpp accumulator.
+; The value remains in the fpp accumulator. No flags are set.
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "register_operand" "=a,=a")
+ (neg:SF (match_operand:SF 1 "register_operand" "a,g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ switch (which_alternative)
+ {
+ case 0:
+ return \"negf\";
+ case 1:
+ return \"lnf %1\";
+ }
+}")
+
+
+; negdf2 can only negate the value already in the fpp accumulator.
+; The value remains in the fpp accumulator. No flags are set.
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=a,=a")
+ (neg:DF (match_operand:DF 1 "register_operand" "a,g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ switch (which_alternative)
+ {
+ case 0:
+ return \"negd\";
+ case 1:
+ return \"lnd %1\";
+ }
+}")
+
+
+; sqrtsf2 tahoe can calculate the square root of a float in the
+; fpp accumulator. The answer remains in the fpp accumulator. No
+; flags are set by this function.
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"sqrtf\";
+}")
+
+
+; ffssi2 tahoe instruction gives one less than GCC desired result for
+; any given input. So the increment is necessary here.
+
+(define_insn "ffssi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ffs:SI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "ffs %1,%0\;incl %0")
+
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (not:SI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "mcoml %1,%0")
+
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (not:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "mcomw %1,%0")
+
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (not:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "mcomb %1,%0")
+
+
+; cmpsi works fine, but due to microcode problems, the tahoe doesn't
+; properly compare hi's and qi's. Leaving them out seems to be acceptable
+; to the compiler, so they were left out. Compares of the stack are
+; possible, though.
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cmpl %0,%1")
+
+
+; cmpsf similar to vax, but first operand is expected to be in the
+; fpp accumulator.
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "register_operand" "a")
+ (match_operand:SF 1 "general_operand" "g")))]
+ ""
+ "cmpf %1")
+
+
+; cmpdf similar to vax, but first operand is expected to be in the
+; fpp accumulator. Immediate doubles not allowed.
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "a")
+ (match_operand:DF 1 "general_operand" "rm")))]
+ ""
+ "cmpd %1")
+
+
+;; Put tstsi first among test insns so it matches a CONST_INT operand.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "g"))]
+ ""
+ "tstl %0")
+
+
+; Small tests from memory are normal, but testing from registers don't
+; expand the data properly. So test in this case does a convert and tests
+; the new register data from the stack.
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "m,?r"))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"tstw %0\";
+ case 1:
+ return \"pushl %0\;cvtwl 2(sp),(sp)\;tstl (sp)+\";
+ }
+}")
+
+
+; Small tests from memory are normal, but testing from registers don't
+; expand the data properly. So test in this case does a convert and tests
+; the new register data from the stack.
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "m,?r"))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"tstb %0\";
+ case 1:
+ return \"pushl %0\;cvtbl 3(sp),(sp)\;tstl (sp)+\";
+ }
+}")
+
+
+; tstsf compares a given value to a value already in the fpp accumulator.
+; No flags are set by this so ignore them.
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "register_operand" "a"))]
+ ""
+ "tstf")
+
+
+; tstdf compares a given value to a value already in the fpp accumulator.
+; immediate doubles not allowed. Flags are ignored after this.
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "register_operand" "a"))]
+ ""
+ "tstd")
+
+
+; movstrhi tahoe instruction does not load registers by itself like
+; the vax counterpart does. registers 0-2 must be primed by hand.
+; we have loaded the registers in the order: dst, src, count.
+
+(define_insn "movstrhi"
+ [(set (match_operand:BLK 0 "general_operand" "p")
+ (match_operand:BLK 1 "general_operand" "p"))
+ (use (match_operand:HI 2 "general_operand" "g"))
+ (clobber (reg:SI 0))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))]
+ ""
+ "movab %0,r1\;movab %1,r0\;movl %2,r2\;movblk")
+
+
+; floatsisf2 on tahoe converts the long from reg/mem into the fpp
+; accumulator. There are no hi and qi counterparts. Flags are not
+; set correctly here.
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (float:SF (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"cvlf %1\";
+}")
+
+
+; floatsidf2 on tahoe converts the long from reg/mem into the fpp
+; accumulator. There are no hi and qi counterparts. Flags are not
+; set correctly here.
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (float:DF (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"cvld %1\";
+}")
+
+
+; fix_truncsfsi2 to convert a float to long, tahoe must have the float
+; in the fpp accumulator. Flags are not set here.
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "a"))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"cvfl %0\";
+}")
+
+
+; fix_truncsfsi2 to convert a double to long, tahoe must have the double
+; in the fpp accumulator. Flags are not set here.
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a"))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"cvdl %0\";
+}")
+
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (truncate:HI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtlw %1,%0")
+
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtlb %1,%0")
+
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cvtwb %1,%0")
+
+
+; The fpp related instructions don't set flags, so ignore them
+; after this instruction.
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=a")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "0")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"cvdf\";
+}")
+
+
+; This monster is to cover for the Tahoe's nasty habit of not extending
+; a number if the source is in a register. (It just moves it!) Case 0 is
+; a normal extend from memory. Case 1 does the extension from the top of
+; the stack. Extension from the stack doesn't set the flags right since
+; the moval changes them.
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g,?=g")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"cvtwl %1,%0\";
+ case 1:
+ if (push_operand(operands[0], SImode))
+ return \"pushl %1\;cvtwl 2(sp),(sp)\";
+ else
+ {
+ CC_STATUS_INIT;
+ return \"pushl %1\;cvtwl 2(sp),%0\;moval 4(sp),sp\";
+ }
+ }
+}")
+
+
+; This monster is to cover for the Tahoe's nasty habit of not extending
+; a number if the source is in a register. (It just moves it!) Case 0 is
+; a normal extend from memory. Case 1 does the extension from the top of
+; the stack. Extension from the stack doesn't set the flags right since
+; the moval changes them.
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g,?=g")
+ (sign_extend:SI (match_operand:QI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"cvtbl %1,%0\";
+ case 1:
+ if (push_operand(operands[0], SImode))
+ return \"pushl %1\;cvtbl 3(sp),(sp)\";
+ else
+ {
+ CC_STATUS_INIT;
+ return \"pushl %1\;cvtbl 3(sp),%0\;moval 4(sp),sp\";
+ }
+ }
+}")
+
+
+; This monster is to cover for the Tahoe's nasty habit of not extending
+; a number if the source is in a register. (It just moves it!) Case 0 is
+; a normal extend from memory. Case 1 does the extension from the top of
+; the stack. Extension from the stack doesn't set the flags right since
+; the moval changes them.
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g,?=g")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"cvtbw %1,%0\";
+ case 1:
+ if (push_operand(operands[0], SImode))
+ return \"pushl %1\;cvtbw 3(sp),2(sp)\";
+ else {
+ CC_STATUS_INIT;
+ return \"pushl %1\;cvtbw 3(sp),%0\;moval 4(sp),sp\";
+ }
+ }
+}")
+
+
+; extendsfdf2 tahoe uses the fpp accumulator to do the extension.
+; It takes a float and loads it up directly as a double.
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=a")
+ (float_extend:DF (match_operand:SF 1 "general_operand" "g")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ return \"ldfd %1\";
+}")
+
+
+; movz works fine from memory but not from register for the same reasons
+; the cvt instructions don't work right. So we use the normal instruction
+; from memory and we use an and to simulate it from register. This is faster
+; than pulling it off the stack.
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g,?=g")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"movzwl %1,%0\";
+ case 1:
+ return \"andl3 $0xffff,%1,%0\";
+ }
+}")
+
+
+; movz works fine from memory but not from register for the same reasons
+; the cvt instructions don't work right. So we use the normal instruction
+; from memory and we use an and to simulate it from register. This is faster
+; than pulling it off the stack.
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g,?=g")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"movzbw %1,%0\";
+ case 1:
+ return \"andw3 $0xff,%1,%0\";
+ }
+}")
+
+
+; movz works fine from memory but not from register for the same reasons
+; the cvt instructions don't work right. So we use the normal instruction
+; from memory and we use an and to simulate it from register. This is faster
+; than pulling it off the stack.
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g,?=g")
+ (zero_extend:SI (match_operand:QI 1 "general_operand" "m,r")))]
+ ""
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"movzbl %1,%0\";
+ case 1:
+ return \"andl3 $0xff,%1,%0\";
+ }
+}")
+
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jeql %l0")
+
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jneq %l0")
+
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgtr %l0")
+
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgtru %l0")
+
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlss %l0")
+
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlssu %l0")
+
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgeq %l0")
+
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgequ %l0")
+
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jleq %l0")
+
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlequ %l0")
+
+
+; GCC does not account for register mask/argc longword. Thus the number
+; for the call = number bytes for args + 4
+
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 4));
+ return \"calls %1,%0\";
+}")
+
+
+; GCC does not account for register mask/argc longword. Thus the number
+; for the call = number bytes for args + 4
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=g")
+ (call (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 4));
+ return \"calls %2,%1\";
+}")
+
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+
+(define_insn "return"
+ [(return)]
+ ""
+ "ret")
+
+
+; casesi, extracted from the vax code. The instructions are
+; very similar. Tahoe requires that the table be word aligned. GCC
+; places the table immediately after, thus the alignment directive.
+
+(define_insn "casesi"
+ [(set (pc)
+ (if_then_else (le (minus:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (match_operand:SI 2 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (minus:SI (match_dup 0)
+ (match_dup 1)))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,%1,%2\;.align %@")
+
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "jbr %l0")
+
+
+;; This is the list of all the non-standard insn patterns
+
+
+; This is used to access the address of a byte. This is similar to
+; movqi, but the second operand had to be "address_operand" type, so
+; it had to be an unnamed one.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushab %a1\";
+ return \"movab %a1,%0\";
+}")
+
+; This is used to access the address of a word. This is similar to
+; movhi, but the second operand had to be "address_operand" type, so
+; it had to be an unnamed one.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:HI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushaw %a1\";
+ return \"movaw %a1,%0\";
+}")
+
+; This is used to access the address of a long. This is similar to
+; movsi, but the second operand had to be "address_operand" type, so
+; it had to be an unnamed one.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushal %a1\";
+ return \"moval %a1,%0\";
+}")
+
+; The tahoe doesn't have an 8 byte indexed move address command
+; and GCC needs it. To work around it, double the index (%2) and
+; then use the 4 byte indexed move address command.
+;
+;(define_insn ""
+; [(set (match_operand:SI 0 "general_operand" "=g")
+; (plus:SI (match_operand:SI 1 "general_operand" "g")
+; (mult:SI (match_operand:SI 2 "register_operand" "r")
+; (const_int 8))))]
+; ""
+; "*
+;{
+; if (GET_CODE (operands[0]) == REG &&
+; REGNO (operands[0]) == REGNO (operands[2])) {
+; return \"shll $3,%2,%2\;addl3 %1,%2,%0\";
+; } else {
+; return \"shll $3,%2,%2\;addl3 %1,%2,%0\;shrl $3,%2,%2\"; }
+;}")
+
+
+; Bit test longword instruction, same as vax.
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "bitl %0,%1")
+
+
+; Bit test word instructions, same as vax.
+
+(define_insn ""
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "general_operand" "g")
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "bitw %0,%1")
+
+
+; Bit test instructions, same as vax.
+
+(define_insn ""
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "bitb %0,%1")
+
+
+; bne counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jneq %l0")
+
+
+; beq counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jeql %l0")
+
+
+; ble counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jleq %l0")
+
+
+; bleu counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlequ %l0")
+
+
+; bge counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgeq %l0")
+
+
+; bgeu counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgequ %l0")
+
+
+; blt counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlss %l0")
+
+
+; bltu counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlssu %l0")
+
+
+; bgt counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgtr %l0")
+
+
+; bgtu counterpart. In case GCC reverses the conditional.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgtru %l0")
+
+
+; casesi alternate form as found in vax code. This form is to
+; compensate for the table's offset being no distance (0 displacement)
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (minus:SI (match_dup 0)
+ (const_int 0)))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,$0,%1\;.align %@")
+
+
+; casesi alternate form as found in vax code. Another form to
+; compensate for the table's offset being no distance (0 displacement)
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (match_dup 0))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,$0,%1 \;.align %@")
diff --git a/gcc-1.40/config/tm-3b1.h b/gcc-1.40/config/tm-3b1.h
new file mode 100644
index 0000000..13b8f12
--- /dev/null
+++ b/gcc-1.40/config/tm-3b1.h
@@ -0,0 +1,482 @@
+/* Definitions of target machine for GNU compiler.
+ AT&T UNIX PC version (pc7300, 3b1)
+
+ Written by Alex Crain
+ bug reports to alex@umbc3.umd.edu
+
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define SGS_3B1
+
+#include "tm-hp9k320.h"
+
+/* See tm-m68k.h. 0 means 680[01]0 with no 68881. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+
+/* -m68020 requires special flags to the assembler. */
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{m68020:-68020}%{!m68020:-68010}"
+
+/* we use /lib/libp/lib* when profiling */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
+
+/* shared libraries need to use crt0s.o */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} "
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Make output for SDB. */
+
+#define SDB_DEBUGGING_INFO
+
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) sdbout_filename ((FILE), main_input_filename)
+
+/* Don't try to define `gcc_compiled.' since the assembler might not
+ accept symbols with periods and GDB doesn't run on this machine anyway. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68k -Dunix -Dunixpc"
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+
+#define FUNCTION_ARG_PADDING(mode, size) \
+ (((mode) == BLKmode \
+ ? (GET_CODE (size) == CONST_INT \
+ && INTVAL (size) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* Override part of the obstack macros. */
+
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
+
+/* Override parts of tm-m68k.h to fit the SGS-3b1 assembler. */
+
+#undef TARGET_VERSION
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SOURCE_FILENAME
+#undef ASM_OUTPUT_SOURCE_LINE
+#undef PRINT_OPERAND_ADDRESS
+#undef ASM_GENERATE_INTERNAL_LABEL
+#undef FUNCTION_PROFILER
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef ASM_OUTPUT_OPCODE
+#undef ASM_OUTPUT_LOCAL
+#undef ASM_OUTPUT_LABELREF
+#undef ASM_OUTPUT_ASCII
+
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
+
+/* The unixpc doesn't know about double's and float's */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { union { double d; long l[2]; } tem; \
+ tem.d = (VALUE); \
+ fprintf(FILE, "\tlong 0x%x,0x%x\n", tem.l[0], tem.l[1]); \
+ } while (0)
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fprintf (FILE, "\tlong 0x%x\n", tem.l); \
+ } while (0)
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\teven\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+/* The `space' pseudo in the text segment outputs nop insns rather than 0s,
+ so we must output 0s explicitly in the text segment. */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ if (in_text_section ()) \
+ { \
+ int i; \
+ for (i = 0; i < (SIZE) - 20; i += 20) \
+ fprintf (FILE, "\tbyte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); \
+ if (i < (SIZE)) \
+ { \
+ fprintf (FILE, "\tbyte 0"); \
+ i++; \
+ for (; i < (SIZE); i++) \
+ fprintf (FILE, ",0"); \
+ fprintf (FILE, "\n"); \
+ } \
+ } \
+ else \
+ fprintf (FILE, "\tspace %u\n", (SIZE))
+
+/* The beginnings of sdb support... */
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ fprintf (FILE, "\tfile\t\"%s\"\n", FILENAME)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+/* Yet another null terminated string format. */
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ { register int sp = 0, lp = 0; \
+ fprintf (FILE, "\tbyte\t"); \
+ loop: \
+ if (PTR[sp] > ' ' && ! (PTR[sp] & 0x80) && PTR[sp] != '\\') \
+ { lp += 3; \
+ fprintf (FILE, "'%c", PTR[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf (FILE, "0x%x", PTR[sp]); } \
+ if (++sp < LEN) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf (FILE, "\n%s ", ASCII_DATA_ASM_OP); } \
+ else \
+ putc (',', FILE); \
+ goto loop; } \
+ putc ('\n', FILE); }
+
+/* Note that in the case of the movhi which fetches an element of
+ an ADDR_DIFF_VEC the offset output is too large by 2.
+ This is because the 3b1 assembler refuses to subtract 2.
+ ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "LD%%%d(%%pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "LD%%%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ fprintf (FILE, ")"); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "LD%%%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "LD%%%d(%%pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
+
+/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+
+/* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
+ `short L%nn-L%nn' supposedly works. */
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ if (! RTX_INTEGRATED_P (TABLE)) \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
+ else \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n\tshort %s%%%d-%s%%%d\n", \
+ XVECLEN (PATTERN (TABLE), 1) + 1, (PREFIX), (NUM), \
+ (PREFIX), (NUM), (PREFIX), (NUM))
+
+/* At end of a switch table, define LD%n iff the symbol LI%n was defined. */
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+ if (RTX_INTEGRATED_P (TABLE)) \
+ fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM))
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' || \
+ (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' || \
+ (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' || \
+ (PTR)[0] == 'm') (PTR)++; } \
+}
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
+
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+/* Define subroutines to call to handle multiply, divide, and remainder.
+ Use the subroutines that the 3b1's library provides.
+ The `*' prevents an underscore from being prepended by the compiler. */
+
+#define DIVSI3_LIBCALL "*ldiv"
+#define UDIVSI3_LIBCALL "*uldiv"
+#define MODSI3_LIBCALL "*lrem"
+#define UMODSI3_LIBCALL "*ulrem"
+#define MULSI3_LIBCALL "*lmul"
+#define UMULSI3_LIBCALL "*ulmul"
diff --git a/gcc-1.40/config/tm-3b1g.h b/gcc-1.40/config/tm-3b1g.h
new file mode 100644
index 0000000..783613e
--- /dev/null
+++ b/gcc-1.40/config/tm-3b1g.h
@@ -0,0 +1,63 @@
+/* Definitions of target machine for GNU compiler, for a 3b1 using GAS.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 0 means 68000 with no 68881. */
+#define TARGET_DEFAULT 0
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68k -Dunix -Dunixpc"
+
+/* This is (not really) BSD, so (but) it wants DBX format. */
+#define DBX_DEBUGGING_INFO
+
+/* Brain damage. */
+#define SCCS_DIRECTIVE
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+#define FUNCTION_ARG_PADDING(mode, size) \
+ (((mode) == BLKmode \
+ ? (GET_CODE (size) == CONST_INT \
+ && INTVAL (size) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* Override part of the obstack macros. */
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
diff --git a/gcc-1.40/config/tm-aix386.h b/gcc-1.40/config/tm-aix386.h
new file mode 100644
index 0000000..b9fd6ed
--- /dev/null
+++ b/gcc-1.40/config/tm-aix386.h
@@ -0,0 +1,129 @@
+/* Definitions for IBM PS2 running AIX/386.
+ From: Minh Tran-Le <TRANLE@intellicorp.com>
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+
+/* Use the ATT assembler syntax. */
+
+#include "tm-att386.h"
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#define STARTFILE_SPEC \
+ "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
+
+#define LIB_SPEC "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lc crtn.o%s"
+
+/* Special flags for the linker. I don't know what they do. */
+
+#define LINK_SPEC "%{K} %{!K:-K} %{T*} %{z:-lm}"
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-D_I386 -Di386 -DAIX -D_AIX"
+
+/* special flags for the aix assembler to generate the short form for all
+ qualifying forward reference */
+
+#define ASM_SPEC "-s2"
+
+/* Allow #sccs in preprocessor. */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { \
+ char *p = (char *) strrchr (main_input_filename, '/'); \
+ if (!p) \
+ p = main_input_filename; \
+ else p++; \
+ fprintf ((FILE), "\t.file\t\"%s\"\n", p); \
+ } while (0)
+
+/* This used to output .noopt if nonoptimizing and run ASM_FILE_START_1
+ if optimizing, but that loses with the AIX assembler. */
+
+/* This was suggested, but it shouldn't be right for DBX output. -- RMS
+ #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) */
+
+/* We want to output SDB debugging information. */
+
+#define SDB_DEBUGGING_INFO
+
+/* We don't want to output DBX debugging information. Becaus IBM AIX dbx
+ use COFF format */
+
+#undef DBX_DEBUGGING_INFO
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Writing `int' for a bitfield forces int alignment for the structure. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Don't write a `.optim' pseudo; this assembler
+ is said to have a bug when .optim is used. */
+
+#if 0
+#undef ASM_FILE_START_1
+#define ASM_FILE_START_1(FILE) fprintf (FILE, "\t.noopt\n");
+#endif
+
+/* Machines that use the AT&T assembler syntax
+ also return floating point values in an FP register. */
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tleal %sP%d,%%eax\n\tcall mcount\n", LPREFIX, (LABELNO));
+
+/* Note that using bss_section here caused errors
+ in building shared libraries on system V.3.
+ but AIX 1.2 does not have yet shareable libraries on PS2 */
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+ (bss_section (), \
+ ASM_OUTPUT_LABEL ((FILE), (NAME)), \
+ fprintf ((FILE), "\t.set .,.+%u\n", (ROUNDED)))
diff --git a/gcc-1.40/config/tm-alliant.h b/gcc-1.40/config/tm-alliant.h
new file mode 100644
index 0000000..c1926e6
--- /dev/null
+++ b/gcc-1.40/config/tm-alliant.h
@@ -0,0 +1,1440 @@
+/* Definitions of target machine for GNU compiler. Alliant FX version.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Adapted from tm-m68k.h by Paul Petersen (petersen@uicsrd.csrd.uiuc.edu)
+ and Joe Weening (weening@gang-of-four.stanford.edu).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file is based on tm-m68k.h, simplified by removing support for
+ the Sun FPA and other things not applicable to the Alliant. Some
+ remnants of these features remain. */
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dalliant -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (Alliant)");
+
+/* Run-time compilation parameters selecting different hardware
+ subsets. The Alliant IP is an mc68020. (Older mc68010-based IPs
+ are no longer supported.) The Alliant CE is 68020-compatible, and
+ also has floating point, vector and concurrency instructions.
+
+ Although the IP doesn't have floating point, it emulates it in the
+ operating system. Using this generally is faster than running code
+ compiled with -msoft-float, because the soft-float code still uses
+ (simulated) FP registers and ends up emulating several fmove{s,d}
+ instructions per call. So I don't recommend using soft-float for
+ any Alliant code. -- JSW
+*/
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Compile for a 68020 (not a 68000 or 68010). */
+#define TARGET_68020 (target_flags & 1)
+/* Compile CE insns for floating point (not library calls). */
+#define TARGET_CE (target_flags & 2)
+/* Compile using 68020 bitfield insns. */
+#define TARGET_BITFIELD (target_flags & 4)
+/* Compile with 16-bit `int'. */
+#define TARGET_SHORT (target_flags & 040)
+
+/* Default 3 means compile 68020 and CE instructions. We don't use
+ bitfield instructions because there appears to be a bug in the
+ implementation of bfins on the CE. */
+
+#define TARGET_DEFAULT 3
+
+/* Define __HAVE_CE__ in preprocessor according to the -m flags.
+ This will control the use of inline FP insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & 02
+
+/* -mce is the default */
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_CE__ }\
+%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{mce:-D__HAVE_CE__ }\
+%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}"
+
+#endif
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { { "68020", 5}, \
+ { "c68020", 5}, \
+ { "bitfield", 4}, \
+ { "68000", -7}, \
+ { "c68000", -7}, \
+ { "soft-float", -2}, \
+ { "nobitfield", -4}, \
+ { "short", 040}, \
+ { "noshort", -040}, \
+ { "", TARGET_DEFAULT}}
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is true for 68020 insns such as bfins and bfexts.
+ We make it true always by avoiding using the single-bit insns
+ except in special cases with constant bit numbers. */
+#define BITS_BIG_ENDIAN
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the 68000. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For 68000 we can decide arbitrarily
+ since there are no machine instructions for them. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32)
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 16
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Define number of bits in most basic integer type.
+ (If undefined, default is BITS_PER_WORD). */
+
+#define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32)
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+ For the Alliant, we give the data registers numbers 0-7,
+ the address registers numbers 010-017,
+ and the floating point registers numbers 020-027. */
+#define FIRST_PSEUDO_REGISTER 24
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the Alliant, these are a0 (argument pointer),
+ a6 (frame pointer) and a7 (stack pointer). */
+#define FIXED_REGISTERS \
+ {0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 0, 0, 0, 0, 0, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like.
+ The Alliant calling sequence allows a function to use any register,
+ so we include them all here. */
+
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1 }
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the Alliant, ordinary registers hold 32 bits worth;
+ for the FP registers, a single register is always enough for
+ anything that can be stored in them at all. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((REGNO) >= 16 ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the Alliant, the cpu registers can hold any mode but the FP registers
+ can hold only SFmode or DFmode. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((REGNO) < 16 || (MODE) == SFmode || (MODE) == DFmode)
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* m68000 pc isn't overloaded on a register. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 15
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 14
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+/* Set for now on Alliant until we find a way to make this work with
+ their calling sequence. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 8
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 8
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 9
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The Alliant has three kinds of registers, so eight classes would be
+ a complete set. One of them is not needed. */
+
+enum reg_class { NO_REGS, FP_REGS, DATA_REGS, DATA_OR_FP_REGS,
+ ADDR_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ { "NO_REGS", "FP_REGS", "DATA_REGS", "DATA_OR_FP_REGS", \
+ "ADDR_REGS", "GENERAL_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ 0, /* NO_REGS */ \
+ 0x00ff0000, /* FP_REGS */ \
+ 0x000000ff, /* DATA_REGS */ \
+ 0x00ff00ff, /* DATA_OR_FP_REGS */ \
+ 0x0000ff00, /* ADDR_REGS */ \
+ 0x0000ffff, /* GENERAL_REGS */ \
+ 0x00ffffff /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+extern enum reg_class regno_reg_class[];
+#define REGNO_REG_CLASS(REGNO) (regno_reg_class[(REGNO)>>3])
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS ADDR_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? ADDR_REGS : \
+ ((C) == 'd' ? DATA_REGS : \
+ ((C) == 'f' ? FP_REGS : \
+ NO_REGS)))
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For the 68000, `I' is used for the range 1 to 8
+ allowed as immediate shift counts and in addq.
+ `J' is used for the range of signed numbers that fit in 16 bits.
+ `K' is for numbers that moveq can't handle.
+ `L' is for range -8 to -1, range of values that can be added with subq. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (VALUE) > 0 && (VALUE) <= 8 : \
+ (C) == 'J' ? (VALUE) >= -0x8000 && (VALUE) <= 0x7FFF : \
+ (C) == 'K' ? (VALUE) < -0x80 || (VALUE) >= 0x80 : \
+ (C) == 'L' ? (VALUE) < 0 && (VALUE) >= -8 : 0)
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class.
+ On the 68000 series, use a data reg if possible when the
+ value is a constant in the range where moveq could be used
+ and we ensure that QImodes are reloaded into data regs. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ ((GET_CODE (X) == CONST_INT \
+ && (unsigned) (INTVAL (X) + 0x80) < 0x100 \
+ && (CLASS) != ADDR_REGS) \
+ ? DATA_REGS \
+ : GET_MODE (X) == QImode \
+ ? DATA_REGS \
+ : (CLASS))
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the 68000, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* The Alliant uses -fcaller-saves by default. */
+#define DEFAULT_CALLER_SAVES
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET -4
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the 68000, sp@- in a byte insn really pushes a word. */
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ On the Alliant we define this as 1 and make the calling sequence
+ (in alliant.md) pop the args. This wouldn't be necessary if we
+ could add to the pending stack adjustment the size of the argument
+ descriptors that are pushed after the arguments. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 1
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the Alliant the return value is in FP0 if real, else D0. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 16) \
+ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On the Alliant the return value is in FP0 if real, else D0. The
+ Alliant library functions for floating-point emulation return their
+ values both in FP0 and in D0/D1. But since not all gnulib functions
+ return the results of these directly, we cannot assume that D0/D1
+ contain the values we expect on return from a gnulib function. */
+
+#define LIBCALL_VALUE(MODE) \
+ (((MODE) == DFmode || (MODE) == SFmode) \
+ ? gen_rtx (REG, MODE, 16) \
+ : gen_rtx (REG, MODE, 0))
+
+/* 1 if N is a possible register number for a function value.
+ On the Alliant, D0 and FP0 are the only registers thus used.
+ (No need to mention D1 when used as a pair with D0.) */
+
+#define FUNCTION_VALUE_REGNO_P(N) (((N) & ~16) == 0)
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for function argument passing.
+ On the Alliant, no registers are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the Alliant, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the Alliant, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the Alliant all args are pushed. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used.
+ The Alliant uses caller-saves, so this macro is very simple. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ int fsize = ((SIZE) - STARTING_FRAME_OFFSET + 3) & -4; \
+ if (frame_pointer_needed) \
+ { \
+ if (fsize < 0x8000) \
+ fprintf(FILE,"\tlinkw a6,#%d\n", -fsize); \
+ else if (TARGET_68020) \
+ fprintf(FILE,"\tlinkl a6,#%d\n", -fsize); \
+ else \
+ fprintf(FILE,"\tlinkw a6,#0\n\tsubl #%d,sp\n", fsize); \
+ fprintf(FILE, "\tmovl a0,a6@(-4)\n" ); }}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tjbsr __mcount_\n")
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk a6\n"); \
+ fprintf (FILE, "\trts\n"); }
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ rtx regs = stack_pointer_rtx; \
+ if (ADDR == frame_pointer_rtx) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 1); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 0); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 1); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 1) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 0); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 12; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (regs, offset + (DEPTH)); } } \
+
+/* Addressing modes, and classification of registers for them. */
+
+#define HAVE_POST_INCREMENT
+/* #define HAVE_POST_DECREMENT */
+
+#define HAVE_PRE_DECREMENT
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+(((REGNO) ^ 010) < 8 || (unsigned) (reg_renumber[REGNO] ^ 010) < 8)
+#define REGNO_OK_FOR_DATA_P(REGNO) \
+((REGNO) < 8 || (unsigned) reg_renumber[REGNO] < 8)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 020) < 8 || (unsigned) (reg_renumber[REGNO] ^ 020) < 8)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the 68000, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is a data register. */
+
+#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* 1 if X is an address register */
+
+#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+/* Alliant FP instructions don't take immediate operands, so this
+ forces them into memory. */
+#define LEGITIMATE_CONSTANT_P(X) (GET_CODE (X) != CONST_DOUBLE)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) ((REGNO (X) ^ 020) >= 8)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) ((REGNO (X) & ~027) != 0)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
+
+#define INDIRECTABLE_1_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
+ && REG_P (XEXP (X, 0)) \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ || (GET_CODE (X) == PLUS \
+ && REG_P (XEXP (X, 0)) && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))
+
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }
+
+#define GO_IF_INDEXABLE_BASE(X, ADDR) \
+{ if (GET_CODE (X) == LABEL_REF) goto ADDR; \
+ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; }
+
+#define GO_IF_INDEXING(X, ADDR) \
+{ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
+ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
+
+#define GO_IF_INDEXED_ADDRESS(X, ADDR) \
+{ GO_IF_INDEXING (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100) \
+ { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); } \
+ if (GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100) \
+ { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } }
+
+#define LEGITIMATE_INDEX_REG_P(X) \
+ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
+ || (GET_CODE (X) == SIGN_EXTEND \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && GET_MODE (XEXP (X, 0)) == HImode \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 0))))
+
+#define LEGITIMATE_INDEX_P(X) \
+ (LEGITIMATE_INDEX_REG_P (X) \
+ || (TARGET_68020 && GET_CODE (X) == MULT \
+ && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (INTVAL (XEXP (X, 1)) == 2 \
+ || INTVAL (XEXP (X, 1)) == 4 \
+ || INTVAL (XEXP (X, 1)) == 8)))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
+ GO_IF_INDEXED_ADDRESS (X, ADDR); }
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the 68000, we handle X+REG by loading X into a register R and
+ using R+REG. R will go in an address reg and indexing will be used.
+ However, if REG is a broken-out memory address or multiplication,
+ nothing needs to be done because REG can certainly go in an address reg. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ register int ch = (X) != (OLDX); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 0)) == MULT) \
+ ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \
+ if (GET_CODE (XEXP (X, 1)) == MULT) \
+ ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \
+ if (ch && GET_CODE (XEXP (X, 1)) == REG \
+ && GET_CODE (XEXP (X, 0)) == REG) \
+ return X; \
+ if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 1), 0); \
+ emit_move_insn (temp, val); \
+ XEXP (X, 1) = temp; \
+ return X; } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 0), 0); \
+ emit_move_insn (temp, val); \
+ XEXP (X, 0) = temp; \
+ return X; }}}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the 68000, only predecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand). */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) goto LABEL
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE HImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+#define SLOW_ZERO_EXTEND
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE -1
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ /* Constant zero is super cheap due to clr instruction. */ \
+ if (RTX == const0_rtx) return 0; \
+ if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/* Check a `double' value for validity for a particular machine mode.
+ This is defined to avoid crashes outputting certain constants. */
+
+#define CHECK_FLOAT_VALUE(mode, d) \
+ if ((mode) == SFmode) \
+ { \
+ if ((d) > 3.4028234663852890e+38) \
+ { warning ("magnitude of value too large for `float'"); \
+ (d) = 3.4028234663852890e+38; } \
+ else if ((d) < -3.4028234663852890e+38) \
+ { warning ("magnitude of value too large for `float'"); \
+ (d) = -3.4028234663852890e+38; } \
+ else if (((d) > 0) && ((d) < 1.1754943508222873e-38)) \
+ (d) = 0.0; \
+ else if (((d) < 0) && ((d) > -1.1754943508222873e-38)) \
+ (d) = 0.0; \
+ }
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* On the Alliant, floating-point instructions do not modify the
+ ordinary CC register. Only fcmp and ftest instructions modify the
+ floating-point CC register. We should actually keep track of what
+ both kinds of CC registers contain, but for now we only consider
+ the most recent instruction that has set either register. */
+
+/* Set if the cc value came from a floating point test, so a floating
+ point conditional branch must be output. */
+#define CC_IN_FP 04000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* On the 68000, all the insns to store in an address register
+ fail to set the cc's. However, in some cases these instructions
+ can make it possibly invalid to use the saved cc's. In those
+ cases we clear out some or all of the saved cc's so they won't be used. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ \
+ if (GET_CODE (EXP) == SET) \
+ { if (ADDRESS_REG_P (SET_DEST (EXP)) || FP_REG_P (SET_DEST (EXP))) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2)) \
+ cc_status.value2 = 0; } \
+ else if (SET_DEST (EXP) != cc0_rtx \
+ && (FP_REG_P (SET_SRC (EXP)) \
+ || GET_CODE (SET_SRC (EXP)) == FIX \
+ || GET_CODE (SET_SRC (EXP)) == FLOAT_TRUNCATE \
+ || GET_CODE (SET_SRC (EXP)) == FLOAT_EXTEND)) \
+ { CC_STATUS_INIT; } \
+ /* A pair of move insns doesn't produce a useful overall cc. */ \
+ else if (!FP_REG_P (SET_DEST (EXP)) \
+ && !FP_REG_P (SET_SRC (EXP)) \
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (EXP))) > 4 \
+ && (GET_CODE (SET_SRC (EXP)) == REG \
+ || GET_CODE (SET_SRC (EXP)) == MEM \
+ || GET_CODE (SET_SRC (EXP)) == CONST_DOUBLE))\
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (SET_SRC (EXP)) == CALL) \
+ { CC_STATUS_INIT; } \
+ else if (XEXP (EXP, 0) != pc_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = XEXP (EXP, 0); \
+ cc_status.value2 = XEXP (EXP, 1); } } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \
+ { \
+ if (ADDRESS_REG_P (XEXP (XVECEXP (EXP, 0, 0), 0))) \
+ CC_STATUS_INIT; \
+ else if (XEXP (XVECEXP (EXP, 0, 0), 0) != pc_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = XEXP (XVECEXP (EXP, 0, 0), 0); \
+ cc_status.value2 = XEXP (XVECEXP (EXP, 0, 0), 1); } } \
+ else CC_STATUS_INIT; \
+ if (cc_status.value2 != 0 \
+ && ADDRESS_REG_P (cc_status.value2) \
+ && GET_MODE (cc_status.value2) == QImode) \
+ CC_STATUS_INIT; \
+ if (cc_status.value2 != 0) \
+ switch (GET_CODE (cc_status.value2)) \
+ { case PLUS: case MINUS: case MULT: case UMULT: \
+ case DIV: case UDIV: case MOD: case UMOD: case NEG: \
+ case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT: \
+ case ROTATE: case ROTATERT: \
+ if (GET_MODE (cc_status.value2) != VOIDmode) \
+ cc_status.flags |= CC_NO_OVERFLOW; \
+ break; \
+ case ZERO_EXTEND: \
+ /* (SET r1 (ZERO_EXTEND r2)) on this machine
+ ends with a move insn moving r2 in r2's mode.
+ Thus, the cc's are set for r2.
+ This can set N bit spuriously. */ \
+ cc_status.flags |= CC_NOT_NEGATIVE; } \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \
+ && cc_status.value2 \
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \
+ cc_status.value2 = 0; \
+ if ((cc_status.value1 && FP_REG_P (cc_status.value1)) \
+ || (cc_status.value2 && FP_REG_P (cc_status.value2))) \
+ cc_status.flags = CC_IN_FP; }
+
+#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
+{ if (cc_prev_status.flags & CC_IN_FP) \
+ return FLOAT; \
+ if (cc_prev_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7" }
+
+/* How to renumber registers for dbx and gdb.
+ On the Sun-3, the floating point registers have numbers
+ 18 to 25, not 16 to 23 as they do in the compiler. */
+/* (On the Alliant, dbx isn't working yet at all. */
+
+#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2)
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { union { double d; long v[2];} tem; \
+ tem.d = (VALUE); \
+ fprintf (FILE, "\t.long 0x%x,0x%x\n", tem.v[0], tem.v[1]); \
+ } while (0)
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fprintf (FILE, "\t.long 0x%x\n", tem.l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,SIZE) \
+{ int i; unsigned char *pp = (unsigned char *) PTR; \
+ fprintf(FILE, "\t.byte %d", (unsigned int)*pp++); \
+ for (i = 1; i < SIZE; ++i, ++pp) { \
+ if ((i % 8) == 0) \
+ fprintf(FILE, "\n\t.byte %d", (unsigned int) *pp); \
+ else \
+ fprintf(FILE, ",%d", (unsigned int) *pp); } \
+ fprintf (FILE, "\n"); }
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmovl %s,sp@-\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovl sp@+,%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\t.even\n"); \
+ else if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %dn", (LOG));
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t. = . + %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the Alliant, we use several CODE characters:
+ '.' for dot needed in Motorola-style opcode names.
+ '-' for an operand pushing on the stack:
+ sp@-, -(sp) or -(%sp) depending on the style of syntax.
+ '+' for an operand pushing on the stack:
+ sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
+ '@' for a reference to the top word on the stack:
+ sp@, (sp) or (%sp) depending on the style of syntax.
+ '#' for an immediate operand prefix (# in MIT and Motorola syntax
+ but & in SGS syntax).
+ '!' for the cc register (used in an `and to cc' insn).
+
+ 'b' for byte insn (no effect, on the Sun; this is for the ISI).
+ 'd' to force memory addressing to be absolute, not relative.
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
+ or print pair of registers as rx:ry. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
+ || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ int i; \
+ if (CODE == '.') ; \
+ else if (CODE == '#') fprintf (FILE, "#"); \
+ else if (CODE == '-') fprintf (FILE, "sp@-"); \
+ else if (CODE == '+') fprintf (FILE, "sp@+"); \
+ else if (CODE == '@') fprintf (FILE, "sp@"); \
+ else if (CODE == '!') fprintf (FILE, "cc"); \
+ else if ((X) == 0 ) ; \
+ else if (GET_CODE (X) == REG) \
+ { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \
+ fprintf (FILE, "%s,%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
+ else \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ } \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ output_address (XEXP (X, 0)); \
+ if (CODE == 'd' && ! TARGET_68020 \
+ && CONSTANT_ADDRESS_P (XEXP (X, 0)) \
+ && !(GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && INTVAL (XEXP (X, 0)) < 0x8000 \
+ && INTVAL (XEXP (X, 0)) >= -0x8000)) \
+ fprintf (FILE, ":l"); \
+ } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "#0r%.9g", u1.f); \
+ else \
+ fprintf (FILE, "#0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "#0r%.20g", u.d); } \
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+
+/* Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...))
+ is in the insn before a tablejump, and we know that m68k.md
+ generates a label LInnn: on such an insn. */
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ static char *sz = ".BW.L...D"; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "%s@", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "%s@-", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "%s@+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:W", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ fprintf (FILE, ":%c", sz[scale]); \
+ putc (']', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L:B]", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ fprintf (FILE, "%s@", reg_names[REGNO (breg)]); \
+ if (addr != 0) { \
+ putc( '(', FILE ); \
+ output_addr_const (FILE, addr); \
+ if (ireg != 0) { \
+ if (GET_CODE(addr) == CONST_INT) { \
+ int size_of = 1, val = INTVAL(addr); \
+ if (val < -0x8000 || val >= 0x8000) \
+ size_of = 4; \
+ else if (val < -0x80 || val >= 0x80) \
+ size_of = 2; \
+ fprintf(FILE, ":%c", sz[size_of]); \
+ } \
+ else \
+ fprintf(FILE, ":L"); } \
+ putc( ')', FILE ); } \
+ if (ireg != 0) { \
+ putc ('[', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s:W", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s:L", reg_names[REGNO (ireg)]); \
+ fprintf (FILE, ":%c", sz[scale]); \
+ putc (']', FILE); \
+ } \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "pc@(L%d-LI%d-2:B)[%s:L:B]", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d:W", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+/*
+Local variables:
+version-control: t
+End:
+*/
+
diff --git a/gcc-1.40/config/tm-altos3068.h b/gcc-1.40/config/tm-altos3068.h
new file mode 100644
index 0000000..36c63c5
--- /dev/null
+++ b/gcc-1.40/config/tm-altos3068.h
@@ -0,0 +1,107 @@
+/* Definitions of target machine for GNU compiler. Altos 3068 68020 version.
+ Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+Written by Jyrki Kuoppala <jkp@cs.hut.fi>
+Last modified: Mon Mar 6 22:47:58 1989
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+/* 5 is without 68881. Change to 7 if you have 68881 */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 5
+#endif
+
+/* Define __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & 02
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#endif
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -DPORTAR -Dmc68k32 -Uvax -Dm68k -Dunix"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+/* We use gnu assembler, linker and gdb, so we want DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Tell some conditionals we will use GAS. Is this really used? */
+
+#define USE_GAS
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0r%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.single 0r%.20e\n", (VALUE))
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ fprintf (FILE, "#0r%.9g", (VALUE))
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ fprintf (FILE, "#0r%.20g", (VALUE))
+
+/* Return pointer values in both d0 and a0. */
+
+#undef FUNCTION_EXTRA_EPILOGUE
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE) \
+{ \
+ extern int current_function_returns_pointer; \
+ if ((current_function_returns_pointer) && \
+ ! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode))\
+ fprintf (FILE, "\tmovel d0,a0\n"); \
+}
diff --git a/gcc-1.40/config/tm-apollo68.h b/gcc-1.40/config/tm-apollo68.h
new file mode 100644
index 0000000..cddfd07
--- /dev/null
+++ b/gcc-1.40/config/tm-apollo68.h
@@ -0,0 +1,177 @@
+/* Definitions of target machine for GNU compiler. Apollo 680X0 version.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-m68k.h"
+
+/* This symbol may be tested in other files for special Apollo handling */
+
+#define TM_APOLLO
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+#endif
+
+/* Target switches for the Apollo is the same as in tm-m68k.h, except
+ there is no Sun FPA. */
+
+#undef TARGET_SWITCHES
+#define TARGET_SWITCHES \
+ { { "68020", 5}, \
+ { "c68020", 5}, \
+ { "68881", 2}, \
+ { "bitfield", 4}, \
+ { "68000", -5}, \
+ { "c68000", -5}, \
+ { "soft-float", -0102}, \
+ { "nobitfield", -4}, \
+ { "rtd", 8}, \
+ { "nortd", -8}, \
+ { "short", 040}, \
+ { "noshort", -040}, \
+ { "", TARGET_DEFAULT}}
+
+/* Define __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & 02
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\
+%{!ansi:%{m68000:-Dmc68010 }%{mc68000:-Dmc68010 }%{!mc68000:%{!m68000:-Dmc68020 }}\
+%{!ansi:-D_APOLLO_SOURCE}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
+%{!ansi:%{m68000:-Dmc68010 }%{mc68000:-Dmc68010 }%{!mc68000:%{!m68000:-Dmc68020 }}\
+%{!ansi:-D_APOLLO_SOURCE}}"
+
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* These are the ones defined by Apollo, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#define CPP_PREDEFINES "-Dapollo -Daegis -Dunix"
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Allow #ident but output nothing for it. */
+
+#define IDENT_DIRECTIVE
+#define ASM_OUTPUT_IDENT(FILE, NAME)
+
+/* Allow dollarsigns in identifiers */
+
+#define DOLLARS_IN_IDENTIFIERS 1
+
+/* -m68000 requires special flags to the assembler.
+ The -C flag is passed to a modified GNU assembler to cause COFF
+ modules to be produced. Remove it if you're not using this.
+ (See vasta@apollo.com.) */
+
+#define ASM_SPEC \
+ "-C %{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* STARTFILE_SPEC
+ Note that includes knowledge of the default specs for gcc, ie. no
+ args translates to the same effect as -m68881 */
+
+/* To get ANSI-conformant behavior, a special version of crt0.o must be used.
+ We use the -ansi switch to pick up that version. */
+
+#define STARTFILE_SPEC \
+ "%{ansi:/usr/apollo/lib/%{pg:gcrt0.o}%{!pg:%{p:mcrt0.o}%{!p:crt0.o}}}\
+%{!ansi:%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}"
+
+/* Make sure ld sets the entry point to _start.
+ This is in LIB_SPEC rather than LINK_SPEC because it needs to
+ come after _start is defined, and to eliminate the default LIB_SPEC. */
+#define LIB_SPEC "-e _start"
+
+/* Debugging is not supported yet */
+
+#undef DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* Functions which return large structures get the address
+ to place the wanted value at offset 8 from the frame. */
+
+#undef PCC_STATIC_STRUCT_RETURN
+#undef STRUCT_VALUE_REGNUM
+
+/* Caller treats address of return area like a parm. */
+#define STRUCT_VALUE 0
+
+#define STRUCT_VALUE_INCOMING \
+ gen_rtx (MEM, Pmode, \
+ gen_rtx (PLUS, SImode, frame_pointer_rtx, \
+ gen_rtx (CONST_INT, VOIDmode, 8)))
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 32
+
+/* Specify how to pad function arguments.
+ Arguments are not padded at all; the stack is kept aligned on long
+ boundaries. */
+
+#define FUNCTION_ARG_PADDING(mode, size) none
+
+/* Short integral argument prototype promotion is not done */
+
+#undef PROMOTE_PROTOTYPES
+
+/* The definition of this macro imposes a limit on the size of
+ an aggregate object which can be treated as if it were a scalar
+ object. */
+
+#define MAX_FIXED_MODE_SIZE BITS_PER_WORD
+
+/* The definition of this macro implies that there are cases where
+ a scalar value cannot be returned in registers.
+ For Apollo, anything larger than one integer register is returned
+ using the structure-value mechanism, i.e. objects of DFmode are
+ returned that way. */
+
+#define RETURN_IN_MEMORY(type) \
+ (GET_MODE_SIZE (TYPE_MODE (type)) > UNITS_PER_WORD)
+
+/* This is how to output a reference to a user-level label named NAME.
+ In order to link to Apollo libraries, no underscore is prepended to names.
+ `assemble_name' uses this. */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
+
+
diff --git a/gcc-1.40/config/tm-att386.h b/gcc-1.40/config/tm-att386.h
new file mode 100644
index 0000000..c359166
--- /dev/null
+++ b/gcc-1.40/config/tm-att386.h
@@ -0,0 +1,244 @@
+/* Definitions for AT&T assembler syntax for the Intel 80386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define TARGET_VERSION fprintf (stderr, " (80386, ATT syntax)");
+
+/* Define the syntax of instructions and addresses. */
+
+/* Define some concatenation macros to concatenate an opcode
+ and one, two or three operands. In other assembler syntaxes
+ they may alter the order of ther operands. */
+
+#ifdef __STDC__
+#define AS2(a,b,c) #a " " #b "," #c
+#define AS3(a,b,c,d) #a " " #b "," #c "," #d
+#define AS1(a,b) #a " " #b
+#else
+#define AS1(a,b) "a b"
+#define AS2(a,b,c) "a b,c"
+#define AS3(a,b,c,d) "a b,c,d"
+#endif
+
+/* Output the size-letter for an opcode.
+ CODE is the letter used in an operand spec (L, B, W, S or Q).
+ CH is the corresponding lower case letter
+ (except if CODE is L then CH is `l'). */
+#define PUT_OP_SIZE(CODE,CH,FILE) putc (CH,(FILE))
+
+/* Opcode suffix for fullword insn. */
+#define L_SIZE "l"
+
+/* Prefix for register names in this syntax. */
+#define RP "%"
+
+/* Prefix for immediate operands in this syntax. */
+#define IP "$"
+
+/* Prefix for internally generated assembler labels. */
+#define LPREFIX ".L"
+
+/* Output the prefix for an immediate operand, or for an offset operand. */
+#define PRINT_IMMED_PREFIX(FILE) fputs ("$", (FILE))
+#define PRINT_OFFSET_PREFIX(FILE) fputs ("$", (FILE))
+
+/* Indirect call instructions should use `*'. */
+#define USE_STAR 1
+
+/* Prefix for a memory-operand X. */
+#define PRINT_PTR(X, FILE)
+
+/* Delimiters that surround base reg and index reg. */
+#define ADDR_BEG(FILE) putc('(', (FILE))
+#define ADDR_END(FILE) putc(')', (FILE))
+
+/* Print an index register (whose rtx is IREG). */
+#define PRINT_IREG(FILE,IREG) \
+ do \
+ { fputs (",", (FILE)); PRINT_REG ((IREG), 0, (FILE)); } \
+ while (0)
+
+/* Print an index scale factor SCALE. */
+#define PRINT_SCALE(FILE,SCALE) \
+ if ((SCALE) != 1) fprintf ((FILE), ",%d", (SCALE))
+
+/* Print a base/index combination.
+ BREG is the base reg rtx, IREG is the index reg rtx,
+ and SCALE is the index scale factor (an integer). */
+
+#define PRINT_B_I_S(BREG,IREG,SCALE,FILE) \
+ { ADDR_BEG (FILE); \
+ if (BREG) PRINT_REG ((BREG), 0, (FILE)); \
+ if ((IREG) != 0) \
+ { PRINT_IREG ((FILE), (IREG)); \
+ PRINT_SCALE ((FILE), (SCALE)); } \
+ ADDR_END (FILE); }
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#define ASM_BYTE "\t.byte "
+#define ASM_SHORT "\t.value "
+#define ASM_LONG "\t.long "
+#define ASM_DOUBLE "\t.double "
+
+/* String containing the assembler's comment-starter. */
+
+#define COMMENT_BEGIN "/"
+
+/* Output at beginning of assembler file. */
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { sdbout_filename ((FILE), main_input_filename); \
+ if (optimize) ASM_FILE_START_1 (FILE); \
+ } while (0)
+
+#define ASM_FILE_START_1(FILE) fprintf (FILE, "\t.optim\n")
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "/APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "/NO_APP\n"
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+/* The `space' pseudo in the text segment outputs nop insns rather than 0s,
+ so we must output 0s explicitly in the text segment. */
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ if (in_text_section ()) \
+ { \
+ int i; \
+ for (i = 0; i < (SIZE) - 20; i += 20) \
+ fprintf (FILE, "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); \
+ if (i < (SIZE)) \
+ { \
+ fprintf (FILE, "\t.byte 0"); \
+ i++; \
+ for (; i < (SIZE); i++) \
+ fprintf (FILE, ",0"); \
+ fprintf (FILE, "\n"); \
+ } \
+ } \
+ else \
+ fprintf ((FILE), "\t.set .,.+%u\n", (SIZE))
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* Output before uninitialized data. */
+
+#define BSS_SECTION_ASM_OP ".bss"
+
+#define EXTRA_SECTIONS in_bss
+
+#define EXTRA_SECTION_FUNCTIONS \
+void \
+bss_section () \
+{ \
+ if (in_section != in_bss) \
+ { \
+ fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
+ in_section = in_bss; \
+ } \
+}
+
+/* Define the syntax of labels and symbol definitions/declarations. */
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+/* We don't use ROUNDED because the standard compiler doesn't,
+ and the linker gives error messages if a common symbol
+ has more than one length value. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+/* Note that using bss_section here caused errors
+ in building shared libraries on system V.3. */
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+ do { \
+ int align = exact_log2 (ROUNDED); \
+ if (align > 2) align = 2; \
+ data_section (); \
+ ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \
+ ASM_OUTPUT_LABEL ((FILE), (NAME)); \
+ fprintf ((FILE), "\t.set .,.+%u\n", (ROUNDED)); \
+ } while (0)
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), ".%s%d", (PREFIX), (NUMBER))
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
+
+/* How to output an ASCII string constant. */
+
+#define ASM_OUTPUT_ASCII(FILE, p, size) \
+{ int i=0; \
+ while (i < size) \
+ { if (i%10 == 0) { if (i!=0) fprintf (FILE, "\n"); \
+ fprintf (FILE, ASM_BYTE); } \
+ else fprintf (FILE, ","); \
+ fprintf (FILE, "0x%x",(p[i++] & 0377)) ;} \
+ fprintf (FILE, "\n"); }
diff --git a/gcc-1.40/config/tm-bsd386.h b/gcc-1.40/config/tm-bsd386.h
new file mode 100644
index 0000000..2bfc61d
--- /dev/null
+++ b/gcc-1.40/config/tm-bsd386.h
@@ -0,0 +1,202 @@
+/* Definitions for BSD assembler syntax for Intel 386
+ (actually AT&T syntax for insns and operands,
+ adapted to BSD conventions for symbol names and debugging.)
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Use the Sequent Symmetry assembler syntax. */
+
+#define TARGET_VERSION fprintf (stderr, " (80386, BSD syntax)");
+
+/* Define some concatenation macros to concatenate an opcode
+ and one, two or three operands. In other assembler syntaxes
+ they may alter the order of ther operands. */
+
+#ifdef __STDC__
+#define AS2(a,b,c) #a " " #b "," #c
+#define AS3(a,b,c,d) #a " " #b "," #c "," #d
+#define AS1(a,b) #a " " #b
+#else
+#define AS1(a,b) "a b"
+#define AS2(a,b,c) "a b,c"
+#define AS3(a,b,c,d) "a b,c,d"
+#endif
+
+/* Output the size-letter for an opcode.
+ CODE is the letter used in an operand spec (L, B, W, S or Q).
+ CH is the corresponding lower case letter
+ (except if CODE is L then CH is `l'). */
+#define PUT_OP_SIZE(CODE,CH,FILE) putc (CH,(FILE))
+
+/* Opcode suffix for fullword insn. */
+#define L_SIZE "l"
+
+/* Prefix for register names in this syntax. */
+#define RP "%"
+
+/* Prefix for immediate operands in this syntax. */
+#define IP "$"
+
+/* Prefix for internally generated assembler labels. */
+#define LPREFIX "L"
+
+/* Output the prefix for an immediate operand, or for an offset operand. */
+#define PRINT_IMMED_PREFIX(FILE) fputs ("$", (FILE))
+#define PRINT_OFFSET_PREFIX(FILE) fputs ("$", (FILE))
+
+/* Indirect call instructions should use `*'. */
+#define USE_STAR 1
+
+/* Prefix for a memory-operand X. */
+#define PRINT_PTR(X, FILE)
+
+/* Delimiters that surround base reg and index reg. */
+#define ADDR_BEG(FILE) putc('(', (FILE))
+#define ADDR_END(FILE) putc(')', (FILE))
+
+/* Print an index register (whose rtx is IREG). */
+#define PRINT_IREG(FILE,IREG) \
+ do \
+ { fputs (",", (FILE)); PRINT_REG ((IREG), 0, (FILE)); } \
+ while (0)
+
+/* Print an index scale factor SCALE. */
+#define PRINT_SCALE(FILE,SCALE) \
+ if ((SCALE) != 1) fprintf ((FILE), ",%d", (SCALE))
+
+/* Print a base/index combination.
+ BREG is the base reg rtx, IREG is the index reg rtx,
+ and SCALE is the index scale factor (an integer). */
+
+#define PRINT_B_I_S(BREG,IREG,SCALE,FILE) \
+ { ADDR_BEG (FILE); \
+ if (BREG) PRINT_REG ((BREG), 0, (FILE)); \
+ if ((IREG) != 0) \
+ { PRINT_IREG ((FILE), (IREG)); \
+ PRINT_SCALE ((FILE), (SCALE)); } \
+ ADDR_END (FILE); }
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#define ASM_BYTE "\t.byte "
+#define ASM_SHORT "\t.word "
+#define ASM_LONG "\t.long "
+#define ASM_DOUBLE "\t.double "
+
+/* String containing the assembler's comment-starter. */
+
+#define COMMENT_BEGIN "/"
+
+/* Output at beginning of assembler file.
+ ??? I am skeptical of this -- RMS. */
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "\t.file\t\"%s\"\n", dump_base_name);
+
+/* This was suggested, but it shouldn't be right for DBX output. -- RMS
+ #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) */
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "/APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "/NO_APP\n"
+
+/* Define the syntax of labels and symbol definitions/declarations. */
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* Define the syntax of labels and symbol definitions/declarations. */
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", (LOG))
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), "*%s%d", (PREFIX), (NUMBER))
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* Sequent has some changes in the format of DBX symbols. */
+#define DBX_NO_XREFS 1
+
+/* Don't split DBX symbols into continuations. */
+#define DBX_CONTIN_LENGTH 0
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
diff --git a/gcc-1.40/config/tm-compaq.h b/gcc-1.40/config/tm-compaq.h
new file mode 100644
index 0000000..6aa7d5f
--- /dev/null
+++ b/gcc-1.40/config/tm-compaq.h
@@ -0,0 +1,39 @@
+/* Definitions for Compaq as target machine. NOT TESTED!
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+
+/* Use the ATT assembler syntax. */
+
+#include "tm-att386.h"
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+#define ASM_SPEC ""
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Di386 -Di80386 -Dunix"
+
+
+#include "tm-i386.h"
+#include "tm-att386.h"
diff --git a/gcc-1.40/config/tm-conv1os7.h b/gcc-1.40/config/tm-conv1os7.h
new file mode 100644
index 0000000..ec522dd
--- /dev/null
+++ b/gcc-1.40/config/tm-conv1os7.h
@@ -0,0 +1,6 @@
+#include "tm-convex1.h"
+
+#undef LINK_SPEC
+#undef STARTFILE_SPEC
+#undef CPP_SPEC
+#undef LIB_SPEC
diff --git a/gcc-1.40/config/tm-conv2os7.h b/gcc-1.40/config/tm-conv2os7.h
new file mode 100644
index 0000000..9735905
--- /dev/null
+++ b/gcc-1.40/config/tm-conv2os7.h
@@ -0,0 +1,6 @@
+#include "tm-convex2.h"
+
+#undef LINK_SPEC
+#undef STARTFILE_SPEC
+#undef CPP_SPEC
+#undef LIB_SPEC
diff --git a/gcc-1.40/config/tm-convex.h b/gcc-1.40/config/tm-convex.h
new file mode 100644
index 0000000..71be483
--- /dev/null
+++ b/gcc-1.40/config/tm-convex.h
@@ -0,0 +1,1034 @@
+/* Definitions of target machine for GNU compiler. Convex version.
+ Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Use the proper incantation to search Posix-compliant libraries. */
+
+#define LINK_SPEC \
+"%{!traditional:-Eposix}%{traditional:-Enoposix}\
+ -A__iob=___ap$iob\
+ -A_use_libc_sema=___ap$use_libc_sema\
+ -L /usr/lib"
+
+/* Use the matching startup files. */
+
+#define STARTFILE_SPEC \
+"%{pg:/usr/lib/crt/gcrt0.o}\
+%{!pg:%{p:/usr/lib/crt/mcrt0.o}\
+%{!p:/usr/lib/crt/crt0.o}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dconvex -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (convex)");
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/*
+ -mc1 avoid C2-only instructions; default on C1 host
+ -mc2 use C2-only instructions; default on C2 host
+ -margcount use standard calling sequence, with arg count word
+ -mnoargcount don't push arg count (it's in the symbol table) (usually)
+*/
+
+#define TARGET_C1 (target_flags & 1)
+#define TARGET_C2 (target_flags & 2)
+#define TARGET_ARGCOUNT (target_flags & 4)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { { "c1", 1 }, \
+ { "c2", 2 }, \
+ { "noc1", -1 }, \
+ { "noc2", -2 }, \
+ { "argcount", 4 }, \
+ { "noargcount", -4 }, \
+ { "", TARGET_DEFAULT }}
+
+/* Default target_flags if no switches specified. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+#endif
+
+/* Allow $ in identifiers */
+
+#define DOLLARS_IN_IDENTIFIERS 1
+
+/* Definitions for g++. */
+
+/* Do not put out GNU stabs for constructors and destructors.
+ ld does not like them. */
+
+#define FASCIST_ASSEMBLER
+
+/* Convex has negative addresses, so use positive numbers
+ to mean `vtable index'. */
+
+#define VTABLE_USES_MASK
+#define VINDEX_MAX ((unsigned) 0x80000000)
+
+/* Target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields. */
+#define BITS_BIG_ENDIAN
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* Lie, so that gcc will take the low part of double reg N in reg N. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* Number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* No data type wants to be aligned rounder than this. */
+/* beware of doubles in structs -- 64 is incompatible with pcc */
+#define BIGGEST_ALIGNMENT 32
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+/* #define STRICT_ALIGNMENT */
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+#define FIRST_PSEUDO_REGISTER 16
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ For Convex, these are AP, FP, and SP. */
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+ On Convex, all values fit in one register. */
+#define HARD_REGNO_NREGS(REGNO, MODE) 1
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On Convex, S registers can hold any type, A registers can any nonfloat */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((REGNO) < 8 || ((MODE) != SFmode && (MODE) != DFmode && (MODE) != DImode))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == SFmode || (MODE1) == DFmode || (MODE1) == DImode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode || (MODE2) == DImode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 8
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 15
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 14
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 0
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 9
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* Convex has classes A (address) and S (scalar). Seems to work
+ better to put S first, here and in the md. */
+
+enum reg_class { NO_REGS, S_REGS, A_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Since GENERAL_REGS is the same class as ALL_REGS,
+ don't give it a different class number; just make it an alias. */
+
+#define GENERAL_REGS ALL_REGS
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "S_REGS", "A_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {0, 0x00ff, 0xff00, 0xffff}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ (S_REGNO_P (REGNO) ? S_REGS : A_REGS)
+
+#define S_REGNO_P(REGNO) ((REGNO) < 8)
+#define A_REGNO_P(REGNO) ((REGNO) >= 8)
+
+#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X)))
+#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X)))
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS A_REGS
+#define BASE_REG_CLASS A_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+/* S regs use the letter 'd' because 's' is taken. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? A_REGS : (C) == 'd' ? S_REGS : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C. */
+
+/* Convex uses only I:
+ 32-bit value with sign bit off, usable as immediate in DImode logical
+ instructions and, or, xor */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) ((VALUE) >= 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+/* Convex uses only G:
+ value usable in ld.d (low word 0) or ld.l (high word all sign) */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ (LD_D_P (VALUE) || LD_L_P (VALUE))
+
+#define LD_D_P(X) (const_double_low_int (X) == 0)
+
+#define LD_L_P(X) (const_double_low_int (X) >= 0 \
+ ? const_double_high_int (X) == 0 \
+ : const_double_high_int (X) == -1)
+
+extern int const_double_low_int ();
+extern int const_double_high_int ();
+extern int const_double_float_int ();
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+#define CLASS_MAX_NREGS(CLASS, MODE) 1
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Define this if should default to -fcaller-saves. */
+
+#define DEFAULT_CALLER_SAVES
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by. */
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 3) & ~3)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+/* The standard Convex call, with arg count word, includes popping the
+ args as part of the call template. We optionally omit the arg count
+ word and let gcc combine the arg pops. */
+#define RETURN_POPS_ARGS(FUNTYPE) TARGET_ARGCOUNT
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On Convex the return value is in S0 regardless. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On Convex the return value is in S0 regardless. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0)
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for a function value.
+ On the Convex, S0 is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+/* 1 if N is a possible register number for function argument passing. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the vax, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On Convex, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On Convex, all args are pushed. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ if ((SIZE) != 0) fprintf (FILE, "\tsub.w #%d,sp\n", ((SIZE) + 3) & -4);}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tldea LP%d,a1\n\tcallq mcount\n", (LABELNO));
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE. */
+
+/* #define FUNCTION_EPILOGUE(FILE, SIZE) */
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) abort ();
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(regno) \
+ ((((regno) ^ 010) < 8 || ((reg_renumber[regno] ^ 010) & -8) == 0) \
+ && regno != 8)
+
+#define REGNO_OK_FOR_BASE_P(regno) REGNO_OK_FOR_INDEX_P (regno)
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 1
+
+/* 1 if X is an rtx for a constant that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+/* For convex, any single-word constant is ok; the only contexts
+ allowing general_operand of mode DI or DF are movdi and movdf. */
+
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) != CONST_DOUBLE ? 1 : (LD_D_P (X) || LD_L_P (X)))
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (REGNO (X) > 8)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (REGNO (X) > 8)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ For Convex, valid addresses are
+ indirectable or (MEM indirectable)
+ where indirectable is
+ const, reg, (PLUS reg const) */
+
+/* 1 if X is an address that we could indirect through. */
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 0))))
+
+/* Go to ADDR if X is a valid address. */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ register rtx xfoob = (X); \
+ if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \
+ xfoob = XEXP (X, 0); \
+ if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \
+ goto ADDR; \
+ if (GET_CODE (X) == PRE_DEC && REG_P (xfoob) \
+ && REGNO (xfoob) == STACK_POINTER_REGNUM) \
+ goto ADDR; }
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For Convex, nothing needs to be done. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the case instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Define this if the case instruction drops through after the table
+ when the index is out of range. Don't define it if the case insn
+ jumps to the default label instead. */
+/* #define CASE_DROPS_THROUGH */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* This flag, if defined, says the same insns that convert to a signed fixnum
+ also convert validly to an unsigned one. */
+#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 8
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* On Convex, it is as good to call a constant function address as to
+ call an address kept in a register. */
+#define NO_FUNCTION_CSE
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ case CONST_INT: \
+ return 0; \
+ case CONST_DOUBLE: \
+ return 2;
+
+/* Check a `double' value for validity for a particular machine mode. */
+
+#define CHECK_FLOAT_VALUE(mode, d) \
+ if ((mode) == SFmode) \
+ { \
+ if ((d) > 1.7014117331926443e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = 1.7014117331926443e+38; } \
+ else if ((d) < -1.7014117331926443e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = -1.7014117331926443e+38; } \
+ else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ }
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for convex. */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP,INSN) {CC_STATUS_INIT;}
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) fprintf (FILE, ";NO_APP\n")
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ";APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ";NO_APP\n"
+
+/* Alignment with Convex's assembler goes like this:
+ .text can be .aligned up to a halfword.
+ .data and .bss can be .aligned up to a longword.
+ .lcomm is not supported, explicit declarations in .bss must be used instead.
+ We get alignment for word and longword .text data by conventionally
+ using .text 2 for word-aligned data and .text 3 for longword-aligned
+ data. This requires that this data's size be a multiple of its alignment,
+ which seems to be always true. */
+
+/* Boolean to keep track of whether the current section is .text or not. */
+
+extern int current_section_is_text;
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP (current_section_is_text = 1, ".text")
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP (current_section_is_text = 0, ".data")
+
+/* Output before uninitialized data. */
+
+#define BSS_SECTION_ASM_OP (current_section_is_text = 0, ".bss")
+
+#define EXTRA_SECTIONS in_bss
+
+#define EXTRA_SECTION_FUNCTIONS \
+void \
+bss_section () \
+{ \
+ if (in_section != in_bss) \
+ { \
+ fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
+ in_section = in_bss; \
+ } \
+}
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if (current_section_is_text && (LOG) > 1) \
+ fprintf (FILE, ".text %d\n", LOG); \
+ else if (current_section_is_text) \
+ fprintf (FILE, ".text\n.align %d\n", 1 << (LOG)); \
+ else \
+ fprintf (FILE, ".align %d\n", 1 << (LOG))
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "sp", "a1", "a2", "a3", "a4", "a5", "ap", "fp"}
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* Put case tables in .text 2, where they will be word-aligned */
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ ASM_OUTPUT_ALIGN (FILE, 2); \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM)
+
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+ ASM_OUTPUT_ALIGN (FILE, 1)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\tds.d %.17e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\tds.s %.9e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tds.w "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tds.h "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tds.b "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tds.b %#x\n", (VALUE))
+
+/* This is how to output a string */
+
+#define ASM_OUTPUT_ASCII(FILE,STR,SIZE) do { \
+ int i; \
+ fprintf (FILE, "\tds.b \""); \
+ for (i = 0; i < (SIZE); i++) { \
+ register int c = (STR)[i] & 0377; \
+ if (c >= ' ' && c < 0177 && c != '\\' && c != '"') \
+ putc (c, FILE); \
+ else \
+ fprintf (FILE, "\\%03o", c);} \
+ fprintf (FILE, "\"\n");} while (0)
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tpsh.%c %s\n", \
+ S_REGNO_P (REGNO) ? 'l' : 'w', \
+ reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tpop.%c %s\n", \
+ S_REGNO_P (REGNO) ? 'l' : 'w', \
+ reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tds.w L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ (not used on Convex) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tds.w L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tds.b %u(0)\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( bss_section (), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ":\tbs.b %u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print an instruction operand X on file FILE.
+ CODE is the code from the %-spec that requested printing this operand;
+ if `%z3' was used to print operand 3, then CODE is 'z'. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "#%.9e", u.d); } \
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+
+/* Print a memory operand whose address is X, on file FILE. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ \
+ register rtx addr = ADDR; \
+ register rtx index = 0; \
+ register rtx offset = 0; \
+ \
+ if (GET_CODE (addr) == MEM) \
+ { \
+ fprintf (FILE, "@"); \
+ addr = XEXP (addr, 0); \
+ } \
+ \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ index = addr; \
+ break; \
+ \
+ case PLUS: \
+ index = XEXP (addr, 0); \
+ if (REG_P (index)) \
+ offset = XEXP (addr, 1); \
+ else \
+ { \
+ offset = XEXP (addr, 0); \
+ index = XEXP (addr, 1); \
+ if (! REG_P (index)) abort (); \
+ } \
+ break; \
+ \
+ default: \
+ offset = addr; \
+ break; \
+ } \
+ \
+ if (offset) \
+ output_addr_const (FILE, offset); \
+ \
+ if (index) \
+ fprintf (FILE, "(%s)", reg_names[REGNO (index)]); \
+}
+
+
diff --git a/gcc-1.40/config/tm-convex1.h b/gcc-1.40/config/tm-convex1.h
new file mode 100644
index 0000000..573af46
--- /dev/null
+++ b/gcc-1.40/config/tm-convex1.h
@@ -0,0 +1,24 @@
+/* tm.h file for a Convex C1. */
+
+#include "tm-convex.h"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 1
+
+#define CC1_SPEC "%{mc2:-mnoc1}"
+
+/* Include Posix prototypes unless -traditional. */
+
+#define CPP_SPEC \
+"%{mc2:-D__convex_c2__}%{!mc2:-D__convex_c1__}\
+ -D__NO_INLINE_MATH\
+ %{!traditional:-D__stdc__ -D_POSIX_SOURCE -D_CONVEX_SOURCE}"
+
+/* Search Posix or else backward-compatible libraries depending
+ on -traditional. */
+
+#define LIB_SPEC \
+"%{mc2:-lC2}%{!mc2:-lC1}\
+ %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\
+%{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\
+%{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}"
diff --git a/gcc-1.40/config/tm-convex2.h b/gcc-1.40/config/tm-convex2.h
new file mode 100644
index 0000000..4e0307b
--- /dev/null
+++ b/gcc-1.40/config/tm-convex2.h
@@ -0,0 +1,24 @@
+/* tm.h file for a Convex C2. */
+
+#include "tm-convex.h"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 2
+
+#define CC1_SPEC "%{mc1:-mnoc2}"
+
+/* Include Posix prototypes unless -traditional. */
+
+#define CPP_SPEC \
+"%{mc1:-D__convex_c1__}%{!mc1:-D__convex_c2__}\
+ -D__NO_INLINE_MATH\
+ %{!traditional:-D__stdc__ -D_POSIX_SOURCE -D_CONVEX_SOURCE}"
+
+/* Search Posix or else backward-compatible libraries depending
+ on -traditional. */
+
+#define LIB_SPEC \
+"%{mc1:-lC1}%{!mc1:-lC2}\
+ %{!p:%{!pg:%{traditional:-lc_old}%{!traditional:-lc}}}\
+%{p:%{traditional:-lc_old_p}%{!traditional:-lc_p}}\
+%{pg:%{traditional:-lc_old_p}%{!traditional:-lc_p}}"
diff --git a/gcc-1.40/config/tm-decstatn.h b/gcc-1.40/config/tm-decstatn.h
new file mode 100644
index 0000000..93fb270
--- /dev/null
+++ b/gcc-1.40/config/tm-decstatn.h
@@ -0,0 +1,27 @@
+/* Definitions of target machine for GNU compiler. DECstation (ultrix) version.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define DECSTATION
+
+#include "tm-mips.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__ANSI_COMPAT \
+-D__LANGUAGE_C -D__MIPSEL -D__R3000 -D__SYSTYPE_BSD -D__bsd4_2 -D__host_mips -D__mips -D__ultrix -D__unix \
+-DLANGUAGE_C -DMIPSEL -DR3000 -DSYSTYPE_BSD -Dbsd4_2 -Dhost_mips -Dmips -Dultrix -Dunix"
diff --git a/gcc-1.40/config/tm-delta68k.h b/gcc-1.40/config/tm-delta68k.h
new file mode 100644
index 0000000..71c45de
--- /dev/null
+++ b/gcc-1.40/config/tm-delta68k.h
@@ -0,0 +1,486 @@
+/* Definitions of target machine for GNU compiler.
+ Motorola Delta version of 680x0 for x>1
+ copied and modified from 3b1 version by
+ Daniel R. Bidwell (bidwell@andrews.edu).
+
+ AT&T UNIX PC version (pc7300, 3b1)
+
+ Written by Alex Crain
+ bug reports to alex@umbc3.umd.edu
+
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define SGS_3B1
+
+#include "tm-hp9k320.h"
+
+/* See tm-m68k.h. 0 means 680[01]0 with no 68881. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+
+/* -m68020 requires special flags to the assembler. */
+
+#undef ASM_SPEC
+#define ASM_SPEC "%{m68020:-68020}"
+
+/* we use /lib/libp/lib* when profiling */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shlib:%{p:-L/lib/libp} %{pg:-L/lib/libp} -lc}"
+
+/* shared libraries need to use crt0s.o */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} "
+
+/* cpp has to support a #sccs directive for the /usr/include files */
+
+#define SCCS_DIRECTIVE
+
+/* Make output for SDB. */
+
+#define SDB_DEBUGGING_INFO
+
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) sdbout_filename ((FILE), main_input_filename)
+
+/* Don't try to define `gcc_compiled.' since the assembler might not
+ accept symbols with periods and GDB doesn't run on this machine anyway. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* ihnp4!lmayk!lgm@eddie.mit.edu says mc68000 and m68k should not be here. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dm68k -Dmc68k -Dunix -Dunixpc"
+
+/* Specify how to pad function arguments.
+ Value should be `upward', `downward' or `none'.
+ Same as the default, except no padding for large or variable-size args. */
+
+#define FUNCTION_ARG_PADDING(mode, size) \
+ (((mode) == BLKmode \
+ ? (GET_CODE (size) == CONST_INT \
+ && INTVAL (size) < PARM_BOUNDARY / BITS_PER_UNIT) \
+ : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY) \
+ ? downward : none)
+
+/* Override part of the obstack macros. */
+
+#define __PTR_TO_INT(P) ((int)(P))
+#define __INT_TO_PTR(P) ((char *)(P))
+
+/* Override parts of tm-m68k.h to fit the SGS-3b1 assembler. */
+
+#undef TARGET_VERSION
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SOURCE_FILENAME
+#undef ASM_OUTPUT_SOURCE_LINE
+#undef PRINT_OPERAND_ADDRESS
+#undef ASM_GENERATE_INTERNAL_LABEL
+#undef FUNCTION_PROFILER
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef ASM_OUTPUT_OPCODE
+#undef ASM_OUTPUT_LOCAL
+#undef ASM_OUTPUT_LABELREF
+#undef ASM_OUTPUT_ASCII
+#undef LEGITIMATE_CONSTANT_P
+#undef ASM_RETURN_CASE_JUMP
+
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
+
+/* The unixpc doesn't know about double's and float's */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { union { double d; long l[2]; } tem; \
+ tem.d = (VALUE); \
+ fprintf(FILE, "\tlong 0x%x,0x%x\n", tem.l[0], tem.l[1]); \
+ } while (0)
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fprintf (FILE, "\tlong 0x%x\n", tem.l); \
+ } while (0)
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ fprintf (FILE, "#0x%.8x", (VALUE))
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\teven\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+/* The `space' pseudo in the text segment outputs nop insns rather than 0s,
+ so we must output 0s explicitly in the text segment. */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ if (in_text_section ()) \
+ { \
+ int i; \
+ for (i = 0; i < (SIZE) - 20; i += 20) \
+ fprintf (FILE, "\tbyte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n"); \
+ if (i < (SIZE)) \
+ { \
+ fprintf (FILE, "\tbyte 0"); \
+ i++; \
+ for (; i < (SIZE); i++) \
+ fprintf (FILE, ",0"); \
+ fprintf (FILE, "\n"); \
+ } \
+ } \
+ else \
+ fprintf (FILE, "\tspace %d\n", (SIZE))
+
+/* The beginnings of sdb support... */
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ fprintf (FILE, "\tfile\t\"%s\"\n", FILENAME)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+/* Yet another null terminated string format. */
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ { register int sp = 0, lp = 0; \
+ fprintf (FILE, "\tbyte\t"); \
+ loop: \
+ if (PTR[sp] > ' ' && ! (PTR[sp] & 0x80) && PTR[sp] != '\\') \
+ { lp += 3; \
+ fprintf (FILE, "'%c", PTR[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf (FILE, "0x%x", PTR[sp]); } \
+ if (++sp < LEN) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf (FILE, "\n%s ", ASCII_DATA_ASM_OP); } \
+ else \
+ putc (',', FILE); \
+ goto loop; } \
+ putc ('\n', FILE); }
+
+/* Note that in the case of the movhi which fetches an element of
+ an ADDR_DIFF_VEC the offset output is too large by 2.
+ This is because the 3b1 assembler refuses to subtract 2.
+ ASM_OUTPUT_CASE_LABEL, below, compensates for this. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "(L%%%d,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "(L%%%d,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ fprintf (FILE, ")"); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%%%d,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "L%%%d(%%pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%%%d:\n", PREFIX, NUM)
+
+/* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+
+/* ihnp4!lmayk!lgm says that `short 0' triggers assembler bug;
+ `short L%nn-L%nn' supposedly works. */
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM));
+
+/* At end of a switch table, define LD%n iff the symbol LI%n was defined. */
+#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
+ if (RTX_INTEGRATED_P (TABLE)) \
+ fprintf (FILE, "\tset LD%%%d,L%%%d-LI%%%d\n", (NUM), (NUM), (NUM))
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbne", 4)) \
+ { fprintf ((FILE), "fbgl"); (PTR) += 4; } \
+ else if (!strncmp ((PTR), "fbeq", 4)) \
+ { fprintf ((FILE), "fbngl"); (PTR) += 4; } \
+ } \
+/* MOVE, MOVEA, MOVEQ, MOVEC ==> MOV */ \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'a' || \
+ (PTR)[0] == 'c') (PTR)++; } \
+/* SUB, SUBQ, SUBA, SUBI ==> SUB */ \
+ else if ((PTR)[0] == 's' && (PTR)[1] == 'u' \
+ && (PTR)[2] == 'b') \
+ { fprintf ((FILE), "sub"); (PTR) += 3; \
+ if ((PTR)[0] == 'q' || (PTR)[0] == 'i' || \
+ (PTR)[0] == 'a') (PTR)++; } \
+/* CMP, CMPA, CMPI, CMPM ==> CMP */ \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p') \
+ { fprintf ((FILE), "cmp"); (PTR) += 3; \
+ if ((PTR)[0] == 'a' || (PTR)[0] == 'i' || \
+ (PTR)[0] == 'm') (PTR)++; } \
+}
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%d\n", (ROUNDED)))
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
+
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_DIM(a) fprintf(asm_out_file, "\tdim\t%d;", a)
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
+
+#define LEGITIMATE_CONSTANT_P(X) (GET_CODE(X)==CONST_DOUBLE?0:1)
+
+#define ASM_RETURN_CASE_JUMP return "jmp (%0.w,%a1)"
+
diff --git a/gcc-1.40/config/tm-encore.h b/gcc-1.40/config/tm-encore.h
new file mode 100644
index 0000000..cdf326c
--- /dev/null
+++ b/gcc-1.40/config/tm-encore.h
@@ -0,0 +1,202 @@
+/* Definitions of target machine for GNU compiler. ENCORE NS32000 version.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+ Adapted by Robert Brown (brown@harvard.harvard.edu) from the Sequent
+ version by Michael Tiemann (tiemann@mcc.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ * Looks like all multiprocessors have this bug!
+ */
+
+#define SEQUENT_ADDRESS_BUG 1
+
+#include "tm-ns32k.h"
+
+#define SDB_DEBUGGING_INFO
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* Cause long-jump assembler to be used,
+ since otherwise some files fail to be assembled right. */
+#define ASM_SPEC "-j"
+
+#undef ASM_FILE_START
+#undef ASM_GENERATE_INTERNAL_LABEL
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_ASCII
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_INT
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#undef ASM_OUTPUT_LOCAL
+#undef CPP_PREDEFINES
+#undef FUNCTION_BOUNDARY
+#undef PRINT_OPERAND
+#undef PRINT_OPERAND_ADDRESS
+#undef TARGET_VERSION
+#undef FUNCTION_PROFILER
+
+
+#define TARGET_DEFAULT 1
+#define TARGET_VERSION fprintf (stderr, " (32000, Encore syntax)");
+/* Note Encore does not standardly do -Dencore. */
+/* budd: should have a -ns32332 (or -apc) switch! but no harm for now */
+#define CPP_PREDEFINES "-Dns32000 -Dn16 -Dns16000 -Dns32332 -Dunix"
+
+/* Ignore certain cpp directives used in header files on sysV. */
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+/* The .file command should always begin the output. */
+#define ASM_FILE_START(FILE) sdbout_filename ((FILE), main_input_filename)
+
+#define FUNCTION_BOUNDARY 128 /* speed optimization */
+
+/*
+ * The Encore assembler uses ".align 2" to align on 2-byte boundaries.
+ */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", 1 << (LOG))
+
+/*
+ * Internal labels are prefixed with a period.
+ */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*.%s%d", PREFIX, NUM)
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word .L%d-.LI%d\n", VALUE, REL)
+
+/*
+ * Different syntax for integer constants, double constants, and
+ * uninitialized locals.
+ */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.double "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.long 0f%.20e\n", (VALUE))
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.bss ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), (ROUNDED)))
+
+ /*
+ * Encore assembler can't handle huge string constants like the one in
+ * gcc.c. If the default routine in varasm.c were more conservative, this
+ * code could be eliminated. It starts a new .ascii directive every 40
+ * characters.
+ */
+
+#define ASM_OUTPUT_ASCII(file, p, size) \
+{ \
+ for (i = 0; i < size; i++) \
+ { \
+ register int c = p[i]; \
+ if ((i / 40) * 40 == i) \
+ if (i == 0) \
+ fprintf (file, "\t.ascii \""); \
+ else \
+ fprintf (file, "\"\n\t.ascii \""); \
+ if (c == '\"' || c == '\\') \
+ putc ('\\', file); \
+ if (c >= ' ' && c < 0177) \
+ putc (c, file); \
+ else \
+ { \
+ fprintf (file, "\\%o", c); \
+ if (i < size - 1 \
+ && p[i + 1] >= '0' && p[i + 1] <= '9') \
+ fprintf (file, "\"\n\t.ascii \""); \
+ } \
+ } \
+ fprintf (file, "\"\n"); \
+}
+
+ /*
+ * Dollar signs are required before immediate operands, double
+ * floating point constants use $0f syntax, and external addresses
+ * should be prefixed with a question mark to avoid assembler warnings
+ * about undefined symbols.
+ */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '$') putc ('$', FILE); \
+ else if (CODE == '?') fputc ('?', FILE); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ rtx xfoo; \
+ xfoo = XEXP (X, 0); \
+ switch (GET_CODE (xfoo)) \
+ { \
+ case MEM: \
+ if (GET_CODE (XEXP (xfoo, 0)) == REG) \
+ if (REGNO (XEXP (xfoo, 0)) == STACK_POINTER_REGNUM) \
+ fprintf (FILE, "0(0(sp))"); \
+ else fprintf (FILE, "0(0(%s))", \
+ reg_names[REGNO (XEXP (xfoo, 0))]); \
+ else \
+ { \
+ fprintf (FILE, "0("); \
+ output_address (xfoo); \
+ putc (')', FILE); \
+ } \
+ break; \
+ case REG: \
+ fprintf (FILE, "0(%s)", reg_names[REGNO (xfoo)]); \
+ break; \
+ case PRE_DEC: \
+ case POST_INC: \
+ fprintf (FILE, "tos"); \
+ break; \
+ case CONST_INT: \
+ fprintf (FILE, "@%d", INTVAL (xfoo)); \
+ break; \
+ default: \
+ output_address (xfoo); \
+ break; \
+ } \
+ } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ if (GET_MODE (X) == DFmode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0f%.20e", u.d); } \
+ else { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0f%.20e", u.d); } \
+ else if (GET_CODE (X) == CONST) \
+ output_addr_const (FILE, X); \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address(FILE, ADDR)
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\taddr .LP%d,r0\n\tjsr mcount\n", (LABELNO))
diff --git a/gcc-1.40/config/tm-genix.h b/gcc-1.40/config/tm-genix.h
new file mode 100644
index 0000000..db4682e
--- /dev/null
+++ b/gcc-1.40/config/tm-genix.h
@@ -0,0 +1,163 @@
+/* Definitions of target machine for GNU compiler. Genix ns32000 version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-encore.h"
+
+/* We don't want the one Encore needs. */
+#undef ASM_SPEC
+
+/* The following defines override ones in tm-ns32k.h and prevent any attempts
+ to explicitly or implicitly make references to the SB register in the GCC
+ generated code. It is necessary to avoid such references under Genix V.3.1
+ because this OS doesn't even save/restore the SB on context switches! */
+
+#define IS_OK_REG_FOR_BASE_P(X) \
+ ( (GET_CODE (X) == REG) && REG_OK_FOR_BASE_P (X) )
+
+#undef INDIRECTABLE_1_ADDRESS_P
+#define INDIRECTABLE_1_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_NO_LABEL_P (X) \
+ || IS_OK_REG_FOR_BASE_P (X) \
+ || (GET_CODE (X) == PLUS \
+ && IS_OK_REG_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1)) ) )
+
+/* Note that for double indirects, only FP, SP, and SB are allowed
+ as the inner-most base register. But we are avoiding use of SB. */
+
+#undef MEM_REG
+#define MEM_REG(X) \
+ ( (GET_CODE (X) == REG) \
+ && ( (REGNO (X) == FRAME_POINTER_REGNUM) \
+ || (REGNO (X) == STACK_POINTER_REGNUM) ) )
+
+#undef INDIRECTABLE_2_ADDRESS_P
+#define INDIRECTABLE_2_ADDRESS_P(X) \
+ (GET_CODE (X) == MEM \
+ && (((xfoo0 = XEXP (X, 0), MEM_REG (xfoo0)) \
+ || (GET_CODE (xfoo0) == PLUS \
+ && MEM_REG (XEXP (xfoo0, 0)) \
+ && CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfoo0, 1)))) \
+ || CONSTANT_ADDRESS_NO_LABEL_P (xfoo0)))
+
+/* Go to ADDR if X is a valid address not using indexing.
+ (This much is the easy part.) */
+#undef GO_IF_NONINDEXED_ADDRESS
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ register rtx xfoob = (X); \
+ if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (INDIRECTABLE_1_ADDRESS_P(X)) goto ADDR; \
+ if (CONSTANT_P(X)) goto ADDR; \
+ if (INDIRECTABLE_2_ADDRESS_P (X)) goto ADDR; \
+ if (GET_CODE (X) == PLUS) \
+ if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1))) \
+ if (INDIRECTABLE_2_ADDRESS_P (XEXP (X, 0))) \
+ goto ADDR; \
+}
+
+/* A bug in the GNX 3.X assembler causes references to external symbols to
+ be mishandled if the symbol is also used as the name of a function-local
+ variable or as the name of a struct or union field. The problem only
+ appears when you are also using the -g option so that SDB debugging
+ directives are also being produced by GCC. In such cases, the assembler
+ gets the external entity confused with the local entity and addressing
+ havoc ensues. The solution is to get GCC to produce .global directives
+ for all external entities which are actually referenced within the current
+ source file. The following macro does this. */
+
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+ ASM_GLOBALIZE_LABEL(FILE,NAME);
+
+/* Genix wants 0l instead of 0f. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.long 0l%.20e\n", (VALUE))
+
+/* A bug in the GNX 3.X linker prevents symbol-table entries with a storage-
+ class field of C_EFCN (-1) from being accepted. */
+
+#ifdef PUT_SDB_EPILOGUE_END
+#undef PUT_SDB_EPILOGUE_END
+#endif
+#define PUT_SDB_EPILOGUE_END(NAME)
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (32000, National syntax)");
+
+/* Same as the tm-encore definition except
+ * Different syntax for double constants.
+ * Don't output `?' before external regs.
+ * Output `(sb)' in certain indirect refs. */
+
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '$') putc ('$', FILE); \
+ else if (CODE == '?'); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ rtx xfoo; \
+ xfoo = XEXP (X, 0); \
+ switch (GET_CODE (xfoo)) \
+ { \
+ case MEM: \
+ if (GET_CODE (XEXP (xfoo, 0)) == REG) \
+ if (REGNO (XEXP (xfoo, 0)) == STACK_POINTER_REGNUM) \
+ fprintf (FILE, "0(0(sp))"); \
+ else fprintf (FILE, "0(0(%s))", \
+ reg_names[REGNO (XEXP (xfoo, 0))]); \
+ else \
+ { \
+ extern int paren_base_reg_printed; \
+ fprintf (FILE, "0("); \
+ paren_base_reg_printed = 0; \
+ output_address (xfoo); \
+ if (!paren_base_reg_printed) \
+ fprintf (FILE, "(sb)"); \
+ putc (')', FILE); \
+ } \
+ break; \
+ case REG: \
+ fprintf (FILE, "0(%s)", reg_names[REGNO (xfoo)]); \
+ break; \
+ case PRE_DEC: \
+ case POST_INC: \
+ fprintf (FILE, "tos"); \
+ break; \
+ case CONST_INT: \
+ fprintf (FILE, "@%d", INTVAL (xfoo)); \
+ break; \
+ default: \
+ output_address (xfoo); \
+ break; \
+ } \
+ } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ if (GET_MODE (X) == DFmode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0l%.20e", u.d); } \
+ else { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0f%.20e", u.d); } \
+ else if (GET_CODE (X) == CONST) \
+ output_addr_const (FILE, X); \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
diff --git a/gcc-1.40/config/tm-harris.h b/gcc-1.40/config/tm-harris.h
new file mode 100644
index 0000000..a06f001
--- /dev/null
+++ b/gcc-1.40/config/tm-harris.h
@@ -0,0 +1,96 @@
+/* Definitions of target machine for GNU compiler. Harris tahoe version.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-tahoe.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dtahoe -Dunix -Dhcx"
+
+#undef DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 1
+
+/* urem and udiv don't exist on this system. */
+#undef UDIVSI3_LIBCALL
+#undef UMODSI3_LIBCALL
+
+/* start the assembly by turning off APP. For the Harris (if not,
+ apparently, for the Tahoe) we want a .file directive as well. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { \
+ int len = strlen (dump_base_name); \
+ char *na = dump_base_name + len; \
+ /* NA gets DUMP_BASE_NAME sans directory names. */ \
+ while (na > dump_base_name) \
+ { \
+ if (na[-1] == '/') \
+ break; \
+ na--; \
+ } \
+ fprintf (FILE, "#NO_APP\n\n"); \
+ fprintf (FILE, "\t.file\t\"%s\"\n", na); \
+ } while (0)
+
+/* Operand of .align is not logarithmic. */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ LOG ? fprintf (FILE, "\t.align %d\n", 1 << (LOG)) : 0
+
+/* For the same reason, we need .align 2 after casesi. */
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '@') \
+ putc ('2', FILE); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".bss ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,4\n", (ROUNDED)))
+
+#define ASM_OUTPUT_ASCII(FILE, PTR, SIZE) \
+{ \
+ unsigned char *_p = (PTR); \
+ int _thissize = (SIZE); \
+ fprintf ((FILE), "\t.ascii \""); \
+ for (i = 0; i < _thissize; i++) \
+ { \
+ register int c = _p[i]; \
+ if (c >= ' ' && c < 0177 && c != '\"' && c != '\\') \
+ putc (c, (FILE)); \
+ else \
+ { \
+ fprintf ((FILE), "\\%o", c); \
+ if (i < _thissize - 1 \
+ && _p[i + 1] >= '0' && _p[i + 1] <= '9') \
+ fprintf ((FILE), "\"\n\t.ascii \""); \
+ } \
+ } \
+ fprintf ((FILE), "\"\n"); \
+}
diff --git a/gcc-1.40/config/tm-hp9k2bsd.h b/gcc-1.40/config/tm-hp9k2bsd.h
new file mode 100644
index 0000000..3793e52
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k2bsd.h
@@ -0,0 +1,53 @@
+/* Definitions of target machine for GNU compiler. HP 9000/200 68000 version.
+ Copyright (C) 1987 - 1991 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 0 means 68000 with no 68881. */
+
+#define TARGET_DEFAULT -0102
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68010 -Dhp200 -Dunix"
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
diff --git a/gcc-1.40/config/tm-hp9k310.h b/gcc-1.40/config/tm-hp9k310.h
new file mode 100644
index 0000000..806aed5
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k310.h
@@ -0,0 +1,32 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68010 version. */
+
+/* See tm-m68k.h. 0 means 68000 without 68881 and no bitfields. */
+#define TARGET_DEFAULT 0
+
+#include "tm-hp9k320.h"
+
+#undef CPP_SPEC
+#undef ASM_SPEC
+
+/* HP does not support a 68020 without a 68881 or a 68010 with a 68881.
+ However, -m68020 does not imply -m68881. You must specify both
+ if you want both. */
+
+#ifdef HPUX_ASM
+
+#define CPP_SPEC "-D__HPUX_ASM__ %{m68881: -D__HAVE_68881__}\
+%{m68020: -Dmc68020}%{mc68020: -Dmc68020}\
+%{!traditional:-D_INCLUDE__STDC__}"
+
+#define ASM_SPEC "%{!m68020:%{!mc68020:+X}}"
+
+#else /* not HPUX_ASM */
+
+#define CPP_SPEC "%{m68881: -D__HAVE_68881__}\
+%{m68020: -Dmc68020}%{mc68020: -Dmc68020}\
+%{!traditional:-D_INCLUDE__STDC__}"
+
+#define ASM_SPEC \
+ "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+
+#endif /* not HPUX_ASM */
diff --git a/gcc-1.40/config/tm-hp9k310g.h b/gcc-1.40/config/tm-hp9k310g.h
new file mode 100644
index 0000000..d1e982b
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k310g.h
@@ -0,0 +1,12 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
+ Use this file if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.) */
+
+/* This wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+#define USE_GAS
+
+#include "tm-hp9k310.h"
diff --git a/gcc-1.40/config/tm-hp9k320.h b/gcc-1.40/config/tm-hp9k320.h
new file mode 100644
index 0000000..4991007
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k320.h
@@ -0,0 +1,598 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Define USE_GAS if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.)
+ Undefine USE_GAS if you want GCC to feed the HP assembler. */
+
+/* #define USE_GAS */ /* Use tm-hp9k320g.h if you want this. */
+
+/* Control assembler-syntax conditionals in m68k.md. */
+
+#ifndef USE_GAS
+#define MOTOROLA
+#define SGS
+#define HPUX_ASM
+#endif
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+#endif
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+/* For version 6.2 of HP-UX (or earlier), remove the "-V 3" from
+ ASM_SPEC below. */
+
+#ifdef HPUX_ASM
+
+/* "-V 3" says that setjmp and longjmp need to save the fpu regs. */
+
+#define ASM_SPEC "%{m68000:+X} -V 3"
+
+#if TARGET_DEFAULT & 02 /* -m68881 is the default */
+
+/* These definitions differ from those used for GAS by defining __HPUX_ASM__.
+ This is needed because some programs, particularly GDB, need to
+ know which assembler is being used so that the correct `asm'
+ instructions can be used. */
+
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}}} -D__HPUX_ASM__\
+ -D_HPUX_SOURCE -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix"
+
+#else /* default is -msoft-float */
+
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}}} -D__HPUX_ASM__\
+ -D_HPUX_SOURCE -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix"
+
+#endif /* default is -msoft-float */
+
+#else /* not HPUX_ASM */
+
+#if TARGET_DEFAULT & 02 /* -m68881 is the default */
+
+#define CPP_SPEC \
+"%{!msoft-float:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}}}\
+ -D_HPUX_SOURCE -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix"
+
+#else /* default is -msoft-float */
+
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }\
+%{!ansi:%{!mc68000:%{!m68000:-Dmc68020}}}\
+ -D_HPUX_SOURCE -D__hp9000s300 -D__hp9000s200 -D__PWB -D__hpux -D__unix"
+
+#endif /* default is -msoft-float */
+
+
+/* -m68000 requires special flags to the assembler. */
+#define ASM_SPEC \
+ "%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* special directory for gnu libs on hp-ux system */
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/gnu/"
+
+#endif /* Not HPUX_ASM */
+
+/* Names to predefine in the preprocessor for this target machine
+ (for non-strict-ANSI programs only). */
+/* These are the ones defined by HPUX cc, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#define CPP_PREDEFINES "-Dhp9000s200 -Dhp9000s300 -DPWB -Dhpux -Dunix"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* hpux doesn't use static area for struct returns. */
+#undef PCC_STATIC_STRUCT_RETURN
+
+/* Generate calls to memcpy, memcmp and memset. */
+#define TARGET_MEM_FUNCTIONS
+
+/* Function calls do save some fp registers on hpux version 7. */
+
+#undef CALL_USED_REGISTERS
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0}
+
+#ifdef HPUX_ASM
+
+/* Override parts of tm-m68k.h to fit the HPUX assembler. */
+
+#undef TARGET_VERSION
+#undef REGISTER_NAMES
+#undef FUNCTION_PROLOGUE
+#undef FUNCTION_EPILOGUE
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+#undef ASM_FILE_START
+#undef ASM_APP_ON
+#undef ASM_APP_OFF
+#undef TEXT_SECTION_ASM_OP
+#undef DATA_SECTION_ASM_OP
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_FLOAT
+#undef ASM_OUTPUT_INT
+#undef ASM_OUTPUT_SHORT
+#undef ASM_OUTPUT_CHAR
+#undef ASM_OUTPUT_BYTE
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#undef ASM_OUTPUT_ALIGN
+#undef ASM_OUTPUT_SKIP
+#undef ASM_OUTPUT_COMMON
+#undef ASM_OUTPUT_LOCAL
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef PRINT_OPERAND
+#undef PRINT_OPERAND_ADDRESS
+#undef FUNCTION_PROFILER
+#undef ASM_GLOBALIZE_LABEL
+#undef ASM_OUTPUT_INTERNAL_LABEL
+
+#define TARGET_VERSION fprintf (stderr, " (68k, SGS/hpux syntax)");
+
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = (SIZE); \
+ if (frame_pointer_needed) \
+ { if (fsize < 0x8000) \
+ fprintf (FILE, "\tlink.w %%a6,&%d\n", -fsize); \
+ else if (TARGET_68020) \
+ fprintf (FILE, "\tlink.l %%a6,&%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink.w %%a6,&0\n\tsub.l &%d,%%sp\n", fsize); } \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if (mask != 0) \
+ fprintf (FILE, "\tfmovem &0x%x,-(%%sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovm.l &0x%x,-(%%sp)\n", mask); }
+
+#define PROFILE_BEFORE_PROLOGUE
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%d,%%a0\n\tjsr mcount\n", (LABEL_NO));
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset; \
+ extern char call_used_regs[]; \
+ extern int current_function_pops_args; \
+ extern int current_function_args_size; \
+ int fsize = (SIZE); \
+ int big = 0; \
+ nregs = 0; fmask = 0; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 && frame_pointer_needed) \
+ { fprintf (FILE, "\tmov.l &%d,%%a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmov.l -%d(%%a6,%%a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmov.l -%d(%%a6),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovm.l -%d(%%a6,%%a0.l),&0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovm.l (%%sp)+,&0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovm.l -%d(%%a6),&0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem -%d(%%a6,%%a0.l),&0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem (%%sp)+,&0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem -%d(%%a6),&0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk %%a6\n"); \
+ if (current_function_pops_args && current_function_args_size) \
+ fprintf (FILE, "\trtd &%d\n", current_function_args_size); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+
+#define ASM_FILE_START(FILE)
+
+#define ASM_APP_ON ""
+
+#define ASM_APP_OFF ""
+
+#define TEXT_SECTION_ASM_OP "text"
+
+#define DATA_SECTION_ASM_OP "data"
+
+#define ASCII_DATA_ASM_OP "\tbyte"
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,2\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
+ sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs ("\tglobal ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+do{ if (PREFIX[0] == 'L' && PREFIX[1] == 'I') \
+ fprintf(FILE, "\tset %s%d,.+2\n", PREFIX, NUM); \
+ else \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM); \
+} while(0)
+
+#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \
+ fprintf (FILE, "\tdouble 0f%.20g\n", (VALUE))
+
+#define ASM_OUTPUT_FLOAT(FILE, VALUE) \
+ fprintf (FILE, "\tfloat 0f%.9g\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tlong "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tshort "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tbyte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%d\n", VALUE)
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tshort L%d-L%d\n", VALUE, REL)
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\tlalign 2\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tspace %u\n", (SIZE))
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME)
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "&"); \
+ else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
+ else if (CODE == '!') fprintf (FILE, "%%cc"); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "&0f%.9g", u1.f); \
+ else \
+ fprintf (FILE, "&0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "&0f%.20g", u.d); } \
+ else { putc ('&', FILE); output_addr_const (FILE, X); }}
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "L%d-LI%d(%%pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "L%d-LI%d(%%pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "L%d-LI%d(%%pc,%s.w)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#define ASM_OUTPUT_ASCII(f, p, size) \
+{ register int i; \
+ int inside; \
+ inside = FALSE; \
+ for (i = 0; i < size; i++) { \
+ if (i % 8 == 0) { \
+ if (i != 0) { \
+ if (inside) \
+ putc('"', f); \
+ putc('\n', f); \
+ inside = FALSE; \
+ } \
+ fprintf(f, "%s ", ASCII_DATA_ASM_OP); \
+ } \
+ if (p[i] < 32 || p[i] == '\\' || p[i] == '"' || p[i] == 127) { \
+ if (inside) { \
+ putc('"', f); \
+ inside = FALSE; \
+ } \
+ if (i % 8 != 0) \
+ putc(',', f); \
+ fprintf(f, "%d", p[i]); \
+ } else { \
+ if (!inside) { \
+ if (i % 8 != 0) \
+ putc(',', f); \
+ putc('"', f); \
+ inside = TRUE; \
+ } \
+ putc(p[i], f); \
+ } \
+ } \
+ if (inside) \
+ putc('"', f); \
+ putc('\n', f); \
+}
+
+/* Translate Motorola opcodes such as `jbeq'
+ into SGS opcodes such as `beq.w'.
+ Delete the `e' in `move...' and `fmove'.
+ Change `ftst' to `ftest'. */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'f') \
+ { \
+ if (!strncmp ((PTR), "fmove", 5)) \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+ else if (!strncmp ((PTR), "ftst", 4)) \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ } \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; } \
+}
+
+/* Prevent output of `gcc_compiled.:'. */
+
+#define ASM_IDENTIFY_GCC(FILE)
+
+#endif /* HPUX_ASM */
diff --git a/gcc-1.40/config/tm-hp9k320g.h b/gcc-1.40/config/tm-hp9k320g.h
new file mode 100644
index 0000000..32ac30a
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k320g.h
@@ -0,0 +1,12 @@
+/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
+ Use this file if GCC is supposed to work with the GNU assembler,
+ GNU linker and GNU debugger using DBX debugging information.
+ (In other words, much of HPUX has been cast aside.) */
+
+/* This wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+#define USE_GAS
+
+#include "tm-hp9k320.h"
diff --git a/gcc-1.40/config/tm-hp9k3bsd.h b/gcc-1.40/config/tm-hp9k3bsd.h
new file mode 100644
index 0000000..b4e5442
--- /dev/null
+++ b/gcc-1.40/config/tm-hp9k3bsd.h
@@ -0,0 +1,36 @@
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#define TARGET_DEFAULT 7
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_FPU__ -D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dmc68020 -Dhp300 -Dhp9000 -Dunix"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS
diff --git a/gcc-1.40/config/tm-i386.h b/gcc-1.40/config/tm-i386.h
new file mode 100644
index 0000000..34d6c2c
--- /dev/null
+++ b/gcc-1.40/config/tm-i386.h
@@ -0,0 +1,1088 @@
+/* Definitions of target machine for GNU compiler for Intel 80386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+/* the file tm-compaq.h includes this file */
+
+
+#define I386 1
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Compile 80387 insns for floating point (not library calls). */
+#define TARGET_80387 (target_flags & 1)
+/* Compile using ret insn that pops args.
+ This will not work unless you use prototypes at least
+ for all functions that can take varying numbers of args. */
+#define TARGET_RTD (target_flags & 8)
+/* Compile passing first two args in regs 0 and 1.
+ This exists only to test compiler features that will
+ be needed for RISC chips. It is not usable
+ and is not intended to be usable on this cpu. */
+#define TARGET_REGPARM (target_flags & 020)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { { "80387", 1}, \
+ { "soft-float", -1}, \
+ { "rtd", 8}, \
+ { "nortd", -8}, \
+ { "regparm", 020}, \
+ { "noregparm", -020}, \
+ { "", TARGET_DEFAULT}}
+
+/* TARGET_DEFAULT is defined in tm-compaq.h, etc. */
+
+/* target machine storage layout */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the 80386. */
+
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on the 80386. */
+/* #define BYTES_BIG_ENDIAN */
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* Not true for 80386 */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 80386, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* There is no point aligning anything to a rounder boundary than this. */
+/* Some structures in the ATT libraries are assumed to round up from 16 to 18
+ bytes, for example the _io_buf */
+#define BIGGEST_ALIGNMENT 32
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+/* #define STRICT_ALIGNMENT */
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+ In the 80387 we give the 8 general purpose registers the numbers 0-7,
+ we assign 6 numbers for floating point registers 8-13,
+ Note that registers 0-7 can be accessed as a short or int,
+ while only 0-3 may be used with mov byte instructions.
+*/
+#define FIRST_PSEUDO_REGISTER 10
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the 80386, only the stack pointer is such. */
+#define FIXED_REGISTERS \
+/*ax,ad,ac,ab,si,di,bp,sp,fval,fp0*/ \
+{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}
+
+/* ;;change-wfs */
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+
+#define CALL_USED_REGISTERS \
+/*ax,ad,ac,ab,si,di,bp,sp,*/ \
+{ 1, 1, 1, 0, 0, 0, 0, 1, \
+ 1, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ Actually there are no two word move instructions for consecutive
+ registers. And only registers 0-3 may have mov byte instructions
+ applied to them.
+ */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((REGNO) >= 8 ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the 80386, the first 4 cpu registers can hold any mode.
+ While the floating point registers may hold SFmode or DFmode only.
+ */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ hard_regno_mode_ok(REGNO,MODE)
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+
+#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) == (MODE2))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* on the 386 the pc register is %eip, and is not usable as a general
+ register. The ordinary mov instructions won't work */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 7
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 6
+
+/* First floating point reg */
+#define FIRST_FLOAT_REG 8
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 6
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 2
+
+/* Register in which address to store a structure value
+ arrives in the function. On the 386, the prologue
+ copies this from the stack to register %eax. */
+#define STRUCT_VALUE_INCOMING \
+ gen_rtx (MEM, Pmode, gen_rtx (PLUS, Pmode, frame_pointer_rtx, \
+ gen_rtx (CONST_INT, VOIDmode, 8)))
+
+/* Place in which caller passes the structure value address.
+ Actually, all that matters about this value is it its rtx_code:
+ MEM means push the value on the stack like an argument. */
+#define STRUCT_VALUE \
+ gen_rtx (MEM, Pmode, gen_rtx (PRE_DEC, Pmode, stack_pointer_rtx))
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+
+enum reg_class {
+ NO_REGS, AREG, DREG, ADREG, CREG, BREG, Q_REGS, SIREG, DIREG,
+ INDEX_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+{ "NO_REGS", "AREG", "DREG", "ADREG", "CREG", "BREG","Q_REGS", \
+ "SIREG", "DIREG", \
+ "INDEX_REGS", "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS"}
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+
+
+#define REG_CLASS_CONTENTS {0, 0x1, 0x2, 0x3, 0x4, 0x8, 0xf,\
+ 0x10, 0x20, 0x7f, 0xff, 0x300, 0x3ff}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) == 0 ? AREG : \
+ (REGNO) == 1 ? DREG : \
+ (REGNO) == 2 ? CREG : \
+ (REGNO) == 3 ? BREG : \
+ (REGNO) == 4 ? SIREG : \
+ (REGNO) == 5 ? DIREG : \
+ (REGNO) == 7 ? GENERAL_REGS : \
+ (REGNO) < 8 ? INDEX_REGS : \
+ FLOAT_REGS)
+
+#define NON_QI_REG_P(X) \
+ (REG_P (X) && REGNO (X) >= 4 && REGNO (X) < FIRST_PSEUDO_REGISTER)
+
+#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
+#define FP_REGNO_P(n) ((n) >= FIRST_FLOAT_REG && (n) < FIRST_PSEUDO_REGISTER)
+
+/* This definition indicates that some register classes are very small,
+ which requires extra care in certain optimizations. */
+
+#define SMALL_REGISTER_CLASSES
+
+/* Try to maintain the accuracy of the death notes for regs satisfying the
+ following. Important for stack like regs, to know when to pop. */
+
+#define PRESERVE_DEATH_INFO_REGNO_P(x) FP_REGNO_P(x)
+
+/* 1 if register REGNO can magically overlap other regs.
+ Note that nonzero values work only in very special circumstances.
+ We return 1 for an FP reg because "both" our FP regs
+ are really the same reg. */
+
+#define OVERLAPPING_REGNO_P(REGNO) FP_REGNO_P (REGNO)
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS INDEX_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'r' ? GENERAL_REGS : \
+ (C) == 'q' ? Q_REGS : \
+ (C) == 'f' ? FLOAT_REGS : \
+ (C) == 'a' ? AREG : (C) == 'b' ? BREG : \
+ (C) == 'c' ? CREG : (C) == 'd' ? DREG : \
+ (C) == 'A' ? ADREG : \
+ (C) == 'S' ? SIREG : \
+ (C) == 'D' ? DIREG : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ I is for the maximum shifts.
+ */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 31 :0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? ! (TARGET_80387 && standard_80387_constant_p (VALUE)) : 1)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class.
+ On the 80386 series, we prevent floating constants from being
+ reloaded into floating registers (since no move-insn can do that)
+ and we ensure that QImodes aren't reloaded into the esi or edi reg. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ (GET_CODE (X) == CONST_DOUBLE \
+ ? ((CLASS) == GENERAL_REGS || (CLASS) == ALL_REGS \
+ ? GENERAL_REGS : NO_REGS) \
+ : GET_MODE (X) == QImode \
+ ? ((CLASS) == GENERAL_REGS || (CLASS) == ALL_REGS \
+ ? Q_REGS \
+ : (CLASS) == INDEX_REGS ? (abort (), INDEX_REGS) \
+ : (CLASS)) \
+ : (CLASS))
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the 80386, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FLOAT_REGS ? 1 : \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On 386 pushw decrements by exactly 2 no matter what the position was.
+ On the 386 there is no pushb; we use pushw instead, and this
+ has the effect of rounding up to 2. */
+
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & (-2))
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 8
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ On the 80386, the RTD insn may be used to pop them if the number
+ of args is fixed, but if the number is variable then the caller
+ must pop them all. RTD can't be used for library calls now
+ because the library is compiled with the Unix compiler.
+ Use of RTD is a selectable option, since it is incompatible with
+ standard Unix calling sequences. If the option is not selected,
+ the caller must always pop the args. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) \
+ (TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \
+ || TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) == void_type_node))
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), \
+ VALUE_REGNO(TYPE_MODE(VALTYPE)))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, VALUE_REGNO(MODE))
+
+/* 1 if N is a possible register number for function argument passing.
+ On the 80386, no registers are used in this way.
+ *NOTE* -mregparm does not work.
+ It exists only to test register calling conventions. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the 80386, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the 80386, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+
+/* On the 80386 all args are pushed, except if -mregparm is specified
+ then the first two words of arguments are passed in EAX, EDX.
+ *NOTE* -mregparm does not work.
+ It exists only to test register calling conventions. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8) ? gen_rtx (REG, (MODE), (CUM) / 4) : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8 \
+ && 8 < ((CUM) + ((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) \
+ : GET_MODE_SIZE (MODE)))) \
+ ? 2 - (CUM) / 4 : 0)
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+ function_prologue (FILE, SIZE)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tmovl $%sP%d,%%edx\n\tcall _mcount\n", LPREFIX, (LABELNO));
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+/* Note on the 386 it might be more efficient not to define this since
+ we have to restore it ourselves from the frame pointer, in order to
+ use pop */
+
+#define EXIT_IGNORE_STACK 1
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+ function_epilogue (FILE, SIZE)
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ rtx regs = stack_pointer_rtx; \
+ if (ADDR == frame_pointer_rtx) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 1); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 0); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 1); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 1) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 0); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = FIRST_FLOAT_REG; regno < FIRST_PSEUDO_REGISTER; regno++)\
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 8; \
+ for (regno=0 ; regno <FIRST_FLOAT_REG ; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (regs, offset + (DEPTH)); } } \
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ ((REGNO) < STACK_POINTER_REGNUM || (unsigned) reg_renumber[REGNO] < STACK_POINTER_REGNUM)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ ((REGNO) <= STACK_POINTER_REGNUM || (unsigned) reg_renumber[REGNO] <= STACK_POINTER_REGNUM)
+
+#define REGNO_OK_FOR_SIREG_P(REGNO) ((REGNO) == 4 || reg_renumber[REGNO] == 4)
+#define REGNO_OK_FOR_DIREG_P(REGNO) ((REGNO) == 5 || reg_renumber[REGNO] == 5)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index or if
+ it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (REGNO (X) < STACK_POINTER_REGNUM || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ of if it is a pseudo reg. */
+ /* ?wfs */
+#define REG_OK_FOR_BASE_P(X) (REGNO (X) <= STACK_POINTER_REGNUM || REGNO(X) >= FIRST_PSEUDO_REGISTER)
+#define REG_OK_FOR_STRREG_P(X) \
+ (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+#define REG_OK_FOR_STRREG_P(X) \
+ (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X)))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is usually machine-independent. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+#define GO_IF_INDEXABLE_BASE(X, ADDR) \
+ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR
+
+#define LEGITIMATE_INDEX_REG_P(X) \
+ (GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
+
+/* Return 1 if X is an index or an index times a scale. */
+
+#define LEGITIMATE_INDEX_P(X) \
+ (LEGITIMATE_INDEX_REG_P (X) \
+ || (GET_CODE (X) == MULT \
+ && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (INTVAL (XEXP (X, 1)) == 2 \
+ || INTVAL (XEXP (X, 1)) == 4 \
+ || INTVAL (XEXP (X, 1)) == 8)))
+
+/* Go to ADDR if X is an index term, a base reg, or a sum of those. */
+
+#define GO_IF_INDEXING(X, ADDR) \
+{ if (LEGITIMATE_INDEX_P (X)) goto ADDR; \
+ GO_IF_INDEXABLE_BASE (X, ADDR); \
+ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
+ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
+
+/* We used to allow this, but it isn't ever used.
+ || ((GET_CODE (X) == POST_DEC || GET_CODE (X) == POST_INC) \
+ && REG_P (XEXP (X, 0)) \
+ && REG_OK_FOR_STRREG_P (XEXP (X, 0))) \
+*/
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (CONSTANT_ADDRESS_P (X)) goto ADDR; \
+ GO_IF_INDEXING (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ GO_IF_INDEXING (XEXP (X, 0), ADDR); \
+ if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ GO_IF_INDEXING (XEXP (X, 1), ADDR); } }
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the 80386, we handle X+REG by loading X into a register R and
+ using R+REG. R will go in a general reg and indexing will be used.
+ However, if REG is a broken-out memory address or multiplication,
+ nothing needs to be done because REG can certainly go in a general reg. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ register int ch = (X) != (OLDX); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 0)) == MULT) \
+ ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \
+ if (GET_CODE (XEXP (X, 1)) == MULT) \
+ ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \
+ if (ch && GET_CODE (XEXP (X, 1)) == REG \
+ && GET_CODE (XEXP (X, 0)) == REG) \
+ return X; \
+ if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 1), temp); \
+ if (val != temp) emit_move_insn (temp, val, 0); \
+ XEXP (X, 1) = temp; \
+ return X; } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 0), temp); \
+ if (val != temp) emit_move_insn (temp, val, 0); \
+ XEXP (X, 0) = temp; \
+ return X; }}}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the 80386, only postdecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand). */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == POST_DEC) goto LABEL
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE Pmode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers.
+ This should be changed to take advantage of fist --wfs ??
+ */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE 1
+
+/* When a prototype says `char' or `short', really pass an `int'.
+ (The 386 can't easily push less than an int.) */
+
+#define PROMOTE_PROTOTYPES
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Define this if addresses of constant functions
+ shouldn't be put through pseudo regs where they can be cse'd.
+ Desirable on the 386 because a CALL with a constant address is
+ not much slower than one with a register address. */
+#define NO_FUNCTION_CSE
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (RTX == const0_rtx) return 0; \
+ if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5; \
+ case PLUS: \
+ if (GET_CODE (XEXP (RTX, 0)) == REG \
+ && GET_CODE (XEXP (RTX, 1)) == CONST_INT) \
+ return 2;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* ??? Find a better place to put this. */
+#if 0
+#define FINAL_PRESCAN_INSN(INSN, OPERANDS, NOPERANDS) \
+ fp_hook (INSN, OPERANDS, NOPERANDS)
+#endif
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* Set if the cc value is actually in the 80387, so a floating point
+ conditional branch must be output. */
+#define CC_IN_80387 04000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+ notice_update_cc((EXP))
+
+/* Output a signed jump insn. Use template NORMAL ordinarily, or
+ FLOAT following a floating point comparison.
+ Use NO_OV following an arithmetic insn that set the cc's
+ before a test insn that was deleted.
+ NO_OV may be zero, meaning final should reinsert the test insn
+ because the jump cannot be handled properly without it. */
+
+#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
+{ \
+ if (cc_status.flags & CC_IN_80387) \
+ return FLOAT; \
+ if (cc_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; \
+}
+
+/* Control the assembler format that we output. */
+
+#ifdef ATT
+#include <syms.h>
+#else
+#define FILNMLEN 14
+#endif
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+/* In order to refer to the first 8 regs as 32 bit regs prefix an "e"
+ For non floating point regs, the following are the HImode names.
+ */
+
+
+#define HI_REGISTER_NAMES \
+{"ax","dx","cx","bx","si","di","bp","sp", \
+ "st","st(1)"}
+/* ,"st(2)","st(3)","st(4)","st(5)" } */
+#define REGISTER_NAMES HI_REGISTER_NAMES
+
+/* Note we are omitting these since currently I don't know how
+to get gcc to use these, since they want the same but different
+number as al, and ax.
+*/
+
+/* note the last four are not really qi_registsers, but
+ the md will have to never output movb into one of them
+ only a movw . There is no movb into the hardware reg
+ esi that I can find */
+
+#define QI_REGISTER_NAMES \
+{"al", "dl", "cl", "bl", "si", "di", "bp", "sp",}
+
+/*
+ Don't know how to use these, yet. They overlap with ax,dx,cx,bx
+ and so would clobber al,dl,cl,bl
+#define QI_REGISTER_NAMES_TOP \
+{"ah", \
+ "dh", \
+ "ch", \
+ "bh", }
+*/
+
+/* How to renumber registers for dbxand gdb. */
+
+/* {0,2,1,3,6,7,4,5,12,13,14,15,16,17} */
+#define DBX_REGISTER_NUMBER(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?3 :(n)==4?6 :(n)==5?7 :(n)==6?4 :(n)==7?5 :(n)==8?12 :(n)==9?12 :(n))
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ (assemble_name (FILE, NAME), fputs (":\n", FILE))
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "%s%.22e\n",ASM_DOUBLE, (VALUE))
+
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fputs(ASM_LONG,FILE); \
+ fprintf((FILE), "0x%x\n", tem.l); \
+ } while (0)
+
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE,ASM_LONG), \
+ output_addr_const (FILE,(VALUE)), \
+ putc('\n',FILE))
+
+/* Likewise for `char' and `short' constants. */
+/* is this supposed to do align too?? */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE,ASM_SHORT), \
+ output_addr_const (FILE,(VALUE)), \
+ putc('\n',FILE))
+
+/*
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fputs (ASM_BYTE,FILE), \
+ output_addr_const (FILE,(VALUE)), \
+ fputs ( ",",FILE), \
+ output_addr_const (FILE,(VALUE)), \
+ fputs (" >> 8\n",FILE))
+*/
+
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, ASM_BYTE), \
+ output_addr_const (FILE,(VALUE)), \
+ putc('\n',FILE))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf ((FILE), "%s0x%x\n", ASM_BYTE, (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tpushl e%s\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tpopl e%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "%s%s%d\n",ASM_LONG,LPREFIX, VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ We don't use these on the 386 yet, because the ATT assembler can't do
+ forward reference the differences.
+ */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort(); \
+ fprintf (FILE, "\t.word %s%d-%s%d\n",LPREFIX, VALUE,LPREFIX, REL)
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN ""
+#define ASM_CLOSE_PAREN ""
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ The CODE z takes the size of operand from the following digit, and
+ outputs b,w,or l respectively.
+
+ On the 80386, we use several such letters:
+ f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
+ L,W,B,Q,S -- print the opcode suffix for specified size of operand.
+ R -- print the prefix for register names.
+ z -- print the opcode suffix for the size of the current operand.
+ * -- print a star (in certain assembler syntax)
+ w -- print the operand as if it's a "word" (HImode) even if it isn't.
+ w -- print the operand as if it's a byte (QImode) even if it isn't.
+ c -- don't print special prefixes before constant operands. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '*')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+ print_operand (FILE, X, CODE)
+
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+ print_operand_address (FILE, ADDR)
+
+/* Routines in gnulib that return floats must return them in an fp reg,
+ just as other functions do which return such values.
+ These macros make that happen. */
+
+#define SFVALUE float
+#define INTIFY(FLOATVAL) FLOATVAL
+
+/* Nonzero if INSN magically clobbers register REGNO. */
+
+#define INSN_CLOBBERS_REGNO_P(INSN, REGNO) \
+ (FP_REGNO_P (REGNO) \
+ && (GET_CODE (INSN) == JUMP_INSN || GET_CODE (INSN) == BARRIER))
+
+/* a letter which is not needed by the normal asm syntax, which
+ we can use for operand syntax in the extended asm */
+
+#define ASM_OPERAND_LETTER '#'
+
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/gcc-1.40/config/tm-i386esix.h b/gcc-1.40/config/tm-i386esix.h
new file mode 100644
index 0000000..33b349f
--- /dev/null
+++ b/gcc-1.40/config/tm-i386esix.h
@@ -0,0 +1,36 @@
+/* Definitions for Intel 386 running ESIX Unix System V. */
+/* Just like SCO support except don't use their special library and
+ predefined symbol. */
+
+/* Mostly it's like AT&T Unix System V. */
+
+#include "tm-i386v.h"
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
+
+#define ENDFILE_SPEC "crtn.o%s"
+
+/* Library spec. */
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lc"
+
+/* Specify predefined symbols in preprocessor. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+"-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
+
+/* SCO's assember doesn't grok '$' in labels (for g++) */
+
+#define NO_DOLLAR_IN_LABEL
+
+/* Unlike SCO, ESIX expects the called function to pop the structure
+ value address. So don't define STRUCT_RETURN_CALLER_POP. */
diff --git a/gcc-1.40/config/tm-i386gas.h b/gcc-1.40/config/tm-i386gas.h
new file mode 100644
index 0000000..fdb3c59
--- /dev/null
+++ b/gcc-1.40/config/tm-i386gas.h
@@ -0,0 +1,106 @@
+/* Definitions for Intel 386 running system V with gnu tools
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+/* Use the bsd assembler syntax. */
+/* we need to do this because gas is really a bsd style assembler,
+ * and so doesn't work well this these att-isms:
+ *
+ * ASM_OUTPUT_SKIP is .set .,.+N, which isn't implemented in gas
+ * ASM_OUTPUT_LOCAL is done with .set .,.+N, but that can't be
+ * used to define bss static space
+ *
+ * Next is the question of whether to uses underscores. RMS didn't
+ * like this idea at first, but since it is now obvious that we
+ * need this separate tm file for use with gas, at least to get
+ * dbx debugging info, I think we should also switch to underscores.
+ * We can keep tm-i386v for real att style output, and the few
+ * people who want both form will have to compile twice.
+ */
+
+#include "tm-bsd386.h"
+
+/* these come from tm-bsd386.h, but are specific to sequent */
+#undef DBX_NO_XREFS
+#undef DBX_CONTIN_LENGTH
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-Dunix -Di386"
+
+/* Allow #sccs in preprocessor. */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+/* We do not want to output SDB debugging information. */
+
+#undef SDB_DEBUGGING_INFO
+
+/* We want to output DBX debugging information. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+#if 0 /* People say gas uses the log as the arg to .align. */
+/* When using gas, .align N aligns to an N-byte boundary. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+#endif
+
+/* Align labels, etc. at 4-byte boundaries. */
+
+#define ASM_OUTPUT_ALIGN_CODE(FILE) \
+ fprintf ((FILE), "\t.align 2\n"); /* Use log of 4 as arg. */
+
+#if 0
+#define ASM_OUTPUT_ALIGN_CODE(FILE) \
+ fprintf ((FILE), "\t.align 4\n");
+#endif
+
+/* Machines that use the AT&T assembler syntax
+ also return floating point values in an FP register. */
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "\t.file\t\"%s\"\n", dump_base_name);
diff --git a/gcc-1.40/config/tm-i386isc.h b/gcc-1.40/config/tm-i386isc.h
new file mode 100644
index 0000000..6204193
--- /dev/null
+++ b/gcc-1.40/config/tm-i386isc.h
@@ -0,0 +1,24 @@
+/* Definitions for Intel 386 running Interactive Unix System V. */
+
+/* Mostly it's like AT&T Unix System V. */
+
+#include "tm-i386v.h"
+
+/* Use crt0.o or crt1.o as a startup file and crtn.o as a closing file. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shlib:%{posix:%{pg:mcrtp1.o%s}%{!pg:%{p:mcrtp1.o%s}%{!p:crtp0.o%s}}}\
+ %{!posix:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}\
+ %{p:-L/lib/libp} %{pg:-L/lib/libp}}}\
+ %{shlib:%{posix:crtp1.o%s}%{!posix:crt1.o%s}} "
+
+#define ENDFILE_SPEC "crtn.o%s"
+
+/* Library spec */
+#undef LIB_SPEC
+#define LIB_SPEC "%{posix:-lcposix} %{shlib:-lc_s} -lc"
+
+/* caller has to pop the extra argument passed to functions that return
+ structures. */
+
+#define STRUCT_RETURN_CALLER_POP
diff --git a/gcc-1.40/config/tm-i386sco.h b/gcc-1.40/config/tm-i386sco.h
new file mode 100644
index 0000000..f9ca635
--- /dev/null
+++ b/gcc-1.40/config/tm-i386sco.h
@@ -0,0 +1,39 @@
+/* Definitions for Intel 386 running SCO Unix System V. */
+
+
+/* Mostly it's like AT&T Unix System V. */
+
+#include "tm-i386v.h"
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
+
+#define ENDFILE_SPEC "crtn.o%s"
+
+/* Library spec, including SCO international language support. */
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} libintl.a%s -lc"
+
+/* Specify predefined symbols in preprocessor. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+"-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} -DM_INTERNAT"
+
+/* SCO's assember doesn't grok '$' in labels (for g++) */
+
+#define NO_DOLLAR_IN_LABEL
+
+/* SCO's libraries are compiled with Microsoft C, which requires the
+ caller to pop the extra argument passed to functions that return
+ structures. */
+
+#define STRUCT_RETURN_CALLER_POP
+
diff --git a/gcc-1.40/config/tm-i386v.h b/gcc-1.40/config/tm-i386v.h
new file mode 100644
index 0000000..573804b
--- /dev/null
+++ b/gcc-1.40/config/tm-i386v.h
@@ -0,0 +1,86 @@
+/* Definitions for Intel 386 running system V.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+
+/* Use the ATT assembler syntax. */
+
+#include "tm-att386.h"
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#define STARTFILE_SPEC \
+ "%{pg:gcrt1.o%s}%{!pg:%{posix:%{p:mcrtp1.o%s}%{!p:crtp1.o%s}}%{!posix:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}\
+ %{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp}"
+
+#define LIB_SPEC "%{posix:-lcposix} %{shlib:-lc_s} -lc crtn.o%s"
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-Dunix -Di386"
+
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
+
+/* Allow #sccs in preprocessor. */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+/* We want to output SDB debugging information. */
+
+#define SDB_DEBUGGING_INFO
+
+/* We don't want to output DBX debugging information. */
+
+#undef DBX_DEBUGGING_INFO
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Writing `int' for a bitfield forces int alignment for the structure. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Don't write a `.optim' pseudo; this assembler doesn't handle them. */
+
+#undef ASM_FILE_START_1
+#define ASM_FILE_START_1(FILE)
+
+/* Machines that use the AT&T assembler syntax
+ also return floating point values in an FP register. */
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
diff --git a/gcc-1.40/config/tm-i386v4.h b/gcc-1.40/config/tm-i386v4.h
new file mode 100644
index 0000000..e128b66
--- /dev/null
+++ b/gcc-1.40/config/tm-i386v4.h
@@ -0,0 +1,62 @@
+/* Definitions for Intel 386 running system Vr4.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by James Van Artsdalen, Dell Computer Corporation.
+ james@bigtex.cactus.org */
+
+#include "tm-i386v.h"
+
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/ccs/lib/"
+
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}} %{pg:gcrti.o%s}%{!pg:%{p:mcrti.o%s}%{!p:crti.o%s}} values-Xt.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -Y P,/usr/ccs/lib:/usr/lib -Qy -lc crtn.o%s"
+
+/* Brain-damaged v4 include files won't work right if __STDC__ != 0 */
+
+#define STDC_VALUE 0
+
+/* We do not want to output SDB debugging information. */
+
+#undef SDB_DEBUGGING_INFO
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { \
+ char *p = (char *) strrchr(main_input_filename, '/'); \
+ if (!p++) \
+ p = main_input_filename; \
+ fprintf ((FILE), "\t.file\t\"%s\"\n", p); \
+ } while (0)
+
+/* SysVr4 has a third "alignment" argument to .comm. It matters when
+ linking with PCC generated code when the object is less than word
+ length. */
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), (SIZE) < 3 ? (SIZE) : 4))
diff --git a/gcc-1.40/config/tm-i386vgas.h b/gcc-1.40/config/tm-i386vgas.h
new file mode 100644
index 0000000..d8e69ff
--- /dev/null
+++ b/gcc-1.40/config/tm-i386vgas.h
@@ -0,0 +1,121 @@
+/* Definitions for Intel 386 running system V with gnu tools
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+/* Use the bsd assembler syntax. */
+/* we need to do this because gas is really a bsd style assembler,
+ * and so doesn't work well this these att-isms:
+ *
+ * ASM_OUTPUT_SKIP is .set .,.+N, which isn't implemented in gas
+ * ASM_OUTPUT_LOCAL is done with .set .,.+N, but that can't be
+ * used to define bss static space
+ *
+ * Next is the question of whether to uses underscores. RMS didn't
+ * like this idea at first, but since it is now obvious that we
+ * need this separate tm file for use with gas, at least to get
+ * dbx debugging info. */
+
+#include "tm-bsd386.h"
+
+/* these come from tm-bsd386.h, but are specific to sequent */
+#undef DBX_NO_XREFS
+#undef DBX_CONTIN_LENGTH
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+#if 0 /* These aren't right for GNU ld. */
+/* Use crt1.o as a startup file and crtn.o as a closing file. */
+
+#define STARTFILE_SPEC \
+ "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
+
+#define LIB_SPEC "%{p:-L/usr/lib/libp}%{pg:-L/usr/lib/libp} -lc crtn.o%s"
+#endif
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-Dunix -Di386"
+
+/* Allow #sccs in preprocessor. */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+/* We do not want to output SDB debugging information. */
+
+#undef SDB_DEBUGGING_INFO
+
+/* We want to output DBX debugging information. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Writing `int' for a bitfield forces int alignment for the structure. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "\t.file\t\"%s\"\n", dump_base_name);
+
+/* This is how to output a reference to a user-level label named NAME. */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+#if 0 /* People say gas uses the log as the arg to .align. */
+/* When using gas, .align N aligns to an N-byte boundary. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+#endif
+
+/* Align labels, etc. at 4-byte boundaries. */
+
+#define ASM_OUTPUT_ALIGN_CODE(FILE) \
+ fprintf ((FILE), "\t.align 2\n"); /* Use log of 4 as arg. */
+
+#if 0
+#define ASM_OUTPUT_ALIGN_CODE(FILE) \
+ fprintf ((FILE), "\t.align 4\n");
+#endif
+
+/* Machines that use the AT&T assembler syntax
+ also return floating point values in an FP register. */
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
diff --git a/gcc-1.40/config/tm-i860.h b/gcc-1.40/config/tm-i860.h
new file mode 100644
index 0000000..ee0bacb
--- /dev/null
+++ b/gcc-1.40/config/tm-i860.h
@@ -0,0 +1,1228 @@
+/* Definitions of target machine for GNU compiler, for Intel 860.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Di860 -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+#define TARGET_VERSION fprintf (stderr, " (i860)");
+
+/* Run-time compilation parameters selecting different hardware subsets.
+
+ On the i860, we have one: TARGET_FPU. */
+
+extern int target_flags;
+
+/* Nonzero if we should generate code to use the fpu. */
+#define TARGET_FPU (target_flags & 1)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { {"fpu", 1}, \
+ {"soft-float", -1}, \
+ { "", TARGET_DEFAULT}}
+
+#define TARGET_DEFAULT 1
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is a moot question on the i860 due to the lack of bit-field insns. */
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on i860 in the mode we will use. */
+/* #define BYTES_BIG_ENDIAN */
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For the i860 this goes with BYTES_BIG_ENDIAN. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 128
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 64
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* If bit field type is int, dont let it cross an int,
+ and give entire struct the alignment of an int. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+
+ i860 has 32 fullword registers and 32 floating point registers. */
+
+#define FIRST_PSEUDO_REGISTER 64
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the i860, this includes the always-0 registers
+ and fp, sp, and the return address.
+ Also r31, used for special purposes for constant addresses. */
+#define FIXED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ On the i860, these are r0-r3, r16-r31, f0, f1, and f16-f31. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1}
+
+#define REG_ALLOC_ORDER \
+ {16, 17, 18, 19, 20, 21, 22, 23, \
+ 24, 25, 26, 27, 28, 29, 30, 31, \
+ 0, 1, 2, 3, 4, 5, 6, 7, \
+ 8, 9, 10, 11, 12, 13, 14, 15, \
+ 40, 41, 42, 43, 44, 45, 46, 47, \
+ 48, 49, 50, 51, 52, 53, 54, 55, \
+ 56, 57, 58, 59, 60, 61, 62, 63, \
+ 32, 33, 34, 35, 36, 37, 38, 39}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the i860, all registers hold 32 bits worth. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ (((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the i860, any register can hold anything, provided it is properly
+ aligned. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (((GET_MODE_SIZE ((MODE)) <= 4) || ((REGNO) & 1) == 0) \
+ && ((REGNO) < 32 || TARGET_FPU))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+/* I think that is not always true; alignment restrictions for doubles
+ should not prevent tying them with singles. So try allowing that.
+ On the other hand, don't let fixed and floating be tied;
+ this restriction is not necessary, but may make better code. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ ((GET_MODE_CLASS ((MODE1)) == MODE_FLOAT) \
+ == (GET_MODE_CLASS ((MODE2)) == MODE_FLOAT))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* i860 pc isn't overloaded on a register that the compiler knows about. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 2
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 3
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 28
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 29
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 16
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The i860 has two kinds of registers, hence four classes. */
+
+enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+ {{0, 0}, {0xffffffff, 0}, \
+ {0, 0xffffffff}, {0xffffffff, 0xffffffff}}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) >= 32 ? FP_REGS : GENERAL_REGS)
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'f' ? FP_REGS : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For the i860, `I' is used for the range of constants
+ an add/subtract insn can actually contain.
+ But not including -0x8000, since we need
+ to negate the constant sometimes.
+ `J' is used for the range which is just zero (since that is R0).
+ `K' is used for the range allowed in bte.
+ `L' is used for the range allowed in logical insns. */
+
+#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x7fff) < 0xffff)
+
+#define LOGIC_INT(X) ((unsigned) INTVAL (X) < 0x10000)
+
+#define SMALL_INTVAL(X) ((unsigned) ((X) + 0x7fff) < 0xffff)
+
+#define LOGIC_INTVAL(X) ((unsigned) (X) < 0x10000)
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? ((unsigned) (VALUE) + 0x7fff) < 0xffff \
+ : (C) == 'J' ? (VALUE) == 0 \
+ : (C) == 'K' ? (unsigned) (VALUE) < 0x20 \
+ : (C) == 'L' ? (unsigned) (VALUE) < 0x10000 \
+ : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' && CONST_DOUBLE_LOW ((VALUE)) == 0 \
+ && CONST_DOUBLE_HIGH ((VALUE)) == 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the i860, this is the size of MODE in words. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the i860, don't define this because there are no push insns. */
+/* #define PUSH_ROUNDING(BYTES) */
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 0
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the i860, the value register depends on the mode. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), \
+ (GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_FLOAT \
+ ? 40 : 16))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, \
+ (GET_MODE_CLASS ((MODE)) == MODE_FLOAT \
+ ? 40 : 16))
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 40 || (N) == 16)
+
+/* 1 if N is a possible register number for function argument passing.
+ On the i860, these are r16-r27 and f8-f15. */
+
+#define FUNCTION_ARG_REGNO_P(N) \
+ (((N) < 28 && (N) > 15) || ((N) < 48 && (N) >= 40))
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the i860, we must count separately the number of general registers used
+ and the number of float registers used. */
+
+#define CUMULATIVE_ARGS struct { int ints, floats; }
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the i860, the general-reg offset normally starts at 0,
+ but starts at 4 bytes
+ when the function gets a structure-value-address as an
+ invisible first argument. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM).ints = ((FNTYPE) != 0 && aggregate_value_p ((FNTYPE)) \
+ ? 4 : 0), \
+ (CUM).floats = 0)
+
+/* Machine-specific subroutines of the following macros. */
+#define CEILING(X,Y) (((X) + (Y) - 1) / (Y))
+#define ROUNDUP(X,Y) (CEILING ((X), (Y)) * (Y))
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.)
+ Floats, and doubleword ints, are returned in f regs;
+ other ints, in r regs.
+ Aggregates, even short ones, are passed in memory. */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((TYPE) != 0 && (TREE_CODE ((TYPE)) == RECORD_TYPE \
+ || TREE_CODE ((TYPE)) == UNION_TYPE) \
+ ? 0 \
+ : GET_MODE_CLASS ((MODE)) == MODE_FLOAT || (MODE) == DImode \
+ ? ((CUM).floats = (ROUNDUP ((CUM).floats, GET_MODE_SIZE ((MODE))) \
+ + ROUNDUP (GET_MODE_SIZE (MODE), 4))) \
+ : GET_MODE_CLASS ((MODE)) == MODE_INT \
+ ? ((CUM).ints = (ROUNDUP ((CUM).ints, GET_MODE_SIZE ((MODE))) \
+ + ROUNDUP (GET_MODE_SIZE (MODE), 4))) \
+ : 0)
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the i860, the first 12 words of integer arguments go in r16-r27,
+ and the first 8 words of floating arguments go in f8-f15.
+ DImode values are treated as floats. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ ((TYPE) != 0 && (TREE_CODE ((TYPE)) == RECORD_TYPE \
+ || TREE_CODE ((TYPE)) == UNION_TYPE) \
+ ? 0 \
+ : GET_MODE_CLASS ((MODE)) == MODE_FLOAT || (MODE) == DImode \
+ ? (ROUNDUP ((CUM).floats, GET_MODE_SIZE ((MODE))) < 32 \
+ ? gen_rtx (REG, (MODE), \
+ 40+(ROUNDUP ((CUM).floats, \
+ GET_MODE_SIZE ((MODE))) \
+ / 4)) \
+ : 0) \
+ : GET_MODE_CLASS ((MODE)) == MODE_INT \
+ ? (ROUNDUP ((CUM).ints, GET_MODE_SIZE ((MODE))) < 48 \
+ ? gen_rtx (REG, (MODE), \
+ 16+(ROUNDUP ((CUM).ints, \
+ GET_MODE_SIZE ((MODE))) \
+ / 4)) \
+ : 0) \
+ : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ int fsize = (SIZE); \
+ int nregs, i; \
+ for (i = 0, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ { \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ nregs++; \
+ } \
+ fsize += nregs * 4 + 8; \
+ fsize = (fsize + 15) & -16; \
+ if (fsize > 0x7fff) \
+ { \
+ fprintf (FILE, "\tadds -16,sp,sp\n"); \
+ fprintf (FILE, "\tst.l fp,8(sp)\n"); \
+ fprintf (FILE, "\tst.l r1,12(sp)\n"); \
+ fprintf (FILE, "\tadds 8,sp,fp\n"); \
+ fprintf (FILE, "\torh %d,r0,r31\n", (fsize - 16) >> 16); \
+ fprintf (FILE, "\tor %d,r31,r31\n", (fsize - 16) & 0xffff); \
+ fprintf (FILE, "\tsubs sp,r31,sp\n"); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tadds -%d,sp,sp\n", fsize); \
+ fprintf (FILE, "\tst.l fp,%d(sp)\n", fsize - 8); \
+ fprintf (FILE, "\tst.l r1,%d(sp)\n", fsize - 4); \
+ fprintf (FILE, "\tadds %d,sp,fp\n", fsize - 8); \
+ } \
+ for (i = 0, nregs = 0; i < 32; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tst.l %s,%d(sp)\n", \
+ reg_names[i], 4 * nregs++); \
+ for (i = 32; i < 64; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tfst.l %s,%d(sp)\n", \
+ reg_names[i], 4 * nregs++); \
+}
+/* ??? maybe save pairs or quads of fp registers. */
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ abort ();
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+/* #define EXIT_IGNORE_STACK 0 */
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ int fsize = (SIZE); \
+ int nregs, i; \
+ for (i = 0, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ { \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ nregs++; \
+ } \
+ fsize += nregs * 4 + 8; \
+ fsize = (fsize + 15) & -16; \
+ if (fsize < 0x7fff) \
+ { \
+ for (i = 0, nregs = 0; i < 32; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tld.l %d(fp),%s\n", \
+ 4 * nregs++ - (fsize - 8), reg_names[i]); \
+ for (i = 32; i < 64; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tfld.l %d(fp),%s\n", \
+ 4 * nregs++ - (fsize - 8), reg_names[i]); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\torh %d,r0,r31\n", (fsize - 8) >> 16); \
+ fprintf (FILE, "\tor %d,r31,r31\n", (fsize - 8) & 0xffff); \
+ fprintf (FILE, "\tsubs fp,r31,sp\n"); \
+ for (i = 0, nregs = 0; i < 32; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tld.l %d(sp),%s\n", \
+ 4 * nregs++, reg_names[i]); \
+ for (i = 32; i < 64; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ fprintf (FILE, "\tfld.l %d(sp),%s\n", \
+ 4 * nregs++, reg_names[i]); \
+ } \
+ if (fsize < 0x7fff) \
+ { \
+ fprintf (FILE, "\tld.l 4(fp),r1\n"); \
+ fprintf (FILE, "\tld.l 0(fp),fp\n"); \
+ fprintf (FILE, "\tbri r1\n\taddu %d,sp,sp\n", fsize); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tld.l 4(fp),r1\n"); \
+ fprintf (FILE, "\tadds 8,fp,r31\n"); \
+ fprintf (FILE, "\tld.l 0(fp),fp\n"); \
+ fprintf (FILE, "\tbri r1\n\tmov r31,sp\n"); \
+ } \
+}
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) abort ();
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 0x20) < 32 || (unsigned) (reg_renumber[REGNO] ^ 0x20) < 32)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the i860, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
+
+ On the Sparc, this is anything but a CONST_DOUBLE.
+ Let's try permitting CONST_DOUBLEs and see what happens. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (((unsigned) REGNO (X)) - 32 >= 14)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (((unsigned) REGNO (X)) - 32 >= 14)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ On the i860, the actual addresses must be REG+REG or REG+SMALLINT.
+ But we can treat a SYMBOL_REF as legitimate if it is part of this
+ function's constant-pool, because such addresses can actually
+ be output as REG+SMALLINT.
+
+ The displacement in an address must be a multiple of the alignment.
+
+ Try making SYMBOL_REF (and other things which are CONSTANT_ADDRESS_P)
+ a legitimate address, regardless. Because the only insns which can use
+ memory are load or store insns, the added hair in the machine description
+ is not that bad. It should also speed up the compiler by halving the number
+ of insns it must manage for each (MEM (SYMBOL_REF ...)) involved. */
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (GET_CODE (X) == REG) \
+ { if (REG_OK_FOR_BASE_P (X)) goto ADDR; } \
+ else if (GET_CODE (X) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ { \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && INTVAL (XEXP (X, 1)) >= -0x8000 \
+ && INTVAL (XEXP (X, 1)) < 0x8000 \
+ && INTVAL (XEXP (X, 1)) & (GET_MODE_SIZE (MODE) - 1) == 0) \
+ goto ADDR; \
+ } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ { \
+ if (GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && INTVAL (XEXP (X, 0)) >= -0x8000 \
+ && INTVAL (XEXP (X, 0)) < 0x8000 \
+ && INTVAL (XEXP (X, 0)) & (GET_MODE_SIZE (MODE) - 1) == 0) \
+ goto ADDR; \
+ } \
+ } \
+ else if (CONSTANT_ADDRESS_P (X)) \
+ goto ADDR; \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output. */
+
+/* On the i860, change COMPLICATED + CONSTANT to REG+CONSTANT.
+ Also change a symbolic constant to a REG,
+ though that may not be necessary. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ force_operand (XEXP (X, 0), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ force_operand (XEXP (X, 1), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ force_operand (XEXP (X, 0), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ force_operand (XEXP (X, 1), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) != REG \
+ && GET_CODE (XEXP (X, 0)) != CONST_INT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ copy_to_mode_reg (SImode, XEXP (X, 0))); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) != REG \
+ && GET_CODE (XEXP (X, 1)) != CONST_INT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ copy_to_mode_reg (SImode, XEXP (X, 1))); \
+ if (GET_CODE (x) == SYMBOL_REF) \
+ (X) = copy_to_reg (X); \
+ if (GET_CODE (x) == CONST) \
+ (X) = copy_to_reg (X); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; }
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the i860 this is never true.
+ There are some addresses that are invalid in wide modes
+ but valid for narrower modes, but they shouldn't cause trouble. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+
+/* On the 860, every legit address is offsettable,
+ but GCC would have trouble figuring this out. */
+
+#define OFFSETTABLE_ADDRESS_P(MODE, ADDR) (memory_address_p ((MODE), (ADDR)))
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Must pass floats to gnulib functions as doubles. */
+#define GNULIB_NEEDS_DOUBLE 1
+
+#define DIVSI3_LIBCALL "*.div"
+#define UDIVSI3_LIBCALL "*.udiv"
+#define REMSI3_LIBCALL "*.rem"
+#define UREMSI3_LIBCALL "*.urem"
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 16
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* This is System V, so it wants sdb format. */
+#define DBX_DEBUGGING_INFO
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE SImode
+
+/* Define this if addresses of constant functions
+ shouldn't be put through pseudo regs where they can be cse'd.
+ Desirable on machines where ordinary constants are expensive
+ but a CALL with constant address is cheap. */
+#define NO_FUNCTION_CSE
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (INTVAL (RTX) == 0) \
+ return 0; \
+ if (INTVAL (RTX) < 0x2000 && INTVAL (RTX) >= -0x2000) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 2; \
+ case CONST_DOUBLE: \
+ return 2 * GET_MODE_SIZE (GET_MODE (RTX)) / UNITS_PER_WORD;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* This holds the value sourcing h%r31. We keep this info
+ around so that mem/mem ops, such as increment and decrement,
+ etc, can be performed reasonably. */
+#define CC_STATUS_MDEP rtx
+
+#define CC_STATUS_MDEP_INIT (cc_status.mdep = 0)
+
+/* On the i860, each comparison tests just one condition,
+ so only that condition can be remembered.
+ We don't need GT, GE, GTU and GEU because CC_REVERSED can handle them. */
+#define CC_ONLY_EQ 0100
+#define CC_ONLY_LE 0200
+#define CC_ONLY_LT 0400
+#define CC_ONLY_LEU 02000
+#define CC_ONLY_LTU 04000
+#define CC_CONDITION_MASK 07700
+
+/* Non-zero to invert the sense of the condition code. */
+#define CC_NEGATED 010000
+
+/* Nonzero if we know the value of h%r31. */
+#define CC_KNOW_HI_R31 0100000
+
+/* Nonzero if h%r31 is actually ha%something, rather than h%something. */
+#define CC_HI_R31_ADJ 0200000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* On the i860, only compare insns set a useful condition code. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ cc_status.flags &= (CC_KNOW_HI_R31 | CC_HI_R31_ADJ); \
+ cc_status.value1 = 0; cc_status.value2 = 0; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+/* The .file command should always begin the output. */
+
+#define ASM_FILE_START(FILE)
+#if 0
+#define ASM_FILE_START(FILE) \
+ do { sdbout_filename ((FILE), main_input_filename); \
+ if (optimize) ASM_FILE_START_1 (FILE); \
+ } while (0)
+#endif
+
+#define ASM_FILE_START_1(FILE)
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ""
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ""
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7", "r8", "r9", \
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", \
+ "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+ "r30", "r31", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", \
+ "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", \
+ "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", \
+ "f30", "f31" }
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* Likewise, for function names. The difference is that we output a no-op
+ just before the beginning of the function, to ensure that there does not
+ appear to be a delayed branch there.
+ Such a thing would confuse interrupt recovery. */
+#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
+ do { fprintf (FILE, "\tnop\n"); ASM_OUTPUT_LABEL (FILE,NAME); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
+
+/* This is how to output an internal numbered label which
+ labels a jump table. */
+
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
+ fprintf (FILE, ".data\n\t.align 4\n.%s%d:\n", PREFIX, NUM)
+
+/* Output at the end of a jump table. */
+
+#define ASM_OUTPUT_CASE_END(FILE,NUM,INSN) \
+ fprintf (FILE, ".text\n")
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*.%s%d", PREFIX, NUM)
+
+#define ASCII_DATA_ASM_OP ".byte"
+#define ASM_OUTPUT_ASCII(f, p, size) \
+{ register int i; \
+ int inside; \
+ inside = FALSE; \
+ for (i = 0; i < size; i++) { \
+ if (i % 64 == 0) { \
+ if (i != 0) { \
+ if (inside) \
+ putc('"', f); \
+ putc('\n', f); \
+ inside = FALSE; \
+ } \
+ fprintf(f, "%s ", ASCII_DATA_ASM_OP); \
+ } \
+ if (p[i] < 32 || p[i] == '\\' || p[i] == '"' || p[i] == 127) { \
+ if (inside) { \
+ putc('"', f); \
+ inside = FALSE; \
+ } \
+ if (i % 64 != 0) \
+ putc(',', f); \
+ fprintf(f, "%d", p[i]); \
+ } else { \
+ if (!inside) { \
+ if (i % 64 != 0) \
+ putc(',', f); \
+ putc('"', f); \
+ inside = TRUE; \
+ } \
+ putc(p[i], f); \
+ } \
+ } \
+ if (inside) \
+ putc('"', f); \
+ putc('\n', f); \
+}
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double %.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.float %.12e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.short "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output code to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\taddu -16,r3,r3\n\t%sst.l %s,0(r3)\n", \
+ ((REGNO) < 32 ? "" : "f"), reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\t%sld.l 0(r3),%s\n\taddu 16,r3,r3\n", \
+ ((REGNO) < 32 ? "" : "f"), reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long .L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ (The i860 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %d\n", 1 << (LOG))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.blkb %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* This assumes the compiler is running on a little-endian machine.
+ The support for the other case is left for version 2,
+ since there is nothing in version 1 to indicate the sex of the host. */
+
+#define PRINT_OPERAND_EXTRACT_FLOAT(X) \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the i860, the CODE can be `r', meaning this is a register-only operand
+ and an immediate zero should be represented as `r0'.
+ It can also be `m', meaning this is a memory ref,
+ but print its address as a constant. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if ((CODE) == 'm') \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if ((CODE) == 'r' && (X) == const0_rtx) \
+ fprintf (FILE, "r0"); \
+ else if ((CODE) == 'r' && (X) == CONST0_RTX (GET_MODE (X))) \
+ fprintf (FILE, "f0"); \
+ else if (GET_CODE (X) == CONST_DOUBLE) \
+ { \
+ if (GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ PRINT_OPERAND_EXTRACT_FLOAT (X); \
+ u1.f = u.d; \
+ fprintf (FILE, "0x%x", u1.i); } \
+ else \
+ abort (); \
+ } \
+ else \
+ output_addr_const (FILE, X); }
+
+/* Print a memory address as an operand to reference that memory location. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx base, index = 0; \
+ int offset = 0; \
+ register rtx addr = ADDR; \
+ if (GET_CODE (addr) == REG) \
+ { \
+ fprintf (FILE, "0(%s)", reg_names[REGNO (addr)]); \
+ } \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);\
+ else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\
+ else \
+ base = XEXP (addr, 0), index = XEXP (addr, 1); \
+ if (index != 0) \
+ fprintf (FILE, "%s", reg_names[REGNO (index)]); \
+ else \
+ fprintf (FILE, "%d", offset); \
+ fprintf (FILE, "(%s)", reg_names[REGNO (base)]); \
+ } \
+ else \
+ { \
+/* ??? this may be wrong. */ \
+ output_addr_const (FILE, addr); \
+ } \
+}
diff --git a/gcc-1.40/config/tm-i860bsdg.h b/gcc-1.40/config/tm-i860bsdg.h
new file mode 100644
index 0000000..84c5ce5
--- /dev/null
+++ b/gcc-1.40/config/tm-i860bsdg.h
@@ -0,0 +1,4 @@
+#include "tm-i860bsd.h"
+
+#undef ASCII_DATA_ASM_OP
+#define ASCII_DATA_ASM_OP ".ascii"
diff --git a/gcc-1.40/config/tm-i860g.h b/gcc-1.40/config/tm-i860g.h
new file mode 100644
index 0000000..9bf8295
--- /dev/null
+++ b/gcc-1.40/config/tm-i860g.h
@@ -0,0 +1,4 @@
+#include "tm-i860.h"
+
+#undef ASCII_DATA_ASM_OP
+#define ASCII_DATA_ASM_OP ".ascii"
diff --git a/gcc-1.40/config/tm-iris.h b/gcc-1.40/config/tm-iris.h
new file mode 100644
index 0000000..66c7606
--- /dev/null
+++ b/gcc-1.40/config/tm-iris.h
@@ -0,0 +1,48 @@
+/* Definitions of target machine for GNU compiler. Iris version.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dmips -Dsgi -DSVR3 -Dhost_mips -DMIPSEB -DSYSTYPE_SYSV -DLANGUAGE_C"
+
+#define STARTFILE_SPEC \
+ "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
+
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} crtn.o%s"
+
+#define SGI_TARGET 1 /* inform other mips files this is SGI */
+
+/* Always use 1 for .file number. I [meissner@osf.org] wonder why
+ IRIS needs this. */
+
+#define SET_FILE_NUMBER() num_source_filenames = 1
+
+/* Put out a label after a .loc. I [meissner@osf.org] wonder why
+ IRIS needs this. */
+
+#define LABEL_AFTER_LOC(STREAM) fprintf (STREAM, "LM%d:\n", ++sym_lineno)
+
+#define STACK_ARGS_ADJUST(SIZE) \
+{ \
+ SIZE.constant += 4; \
+ if (SIZE.constant < 32) \
+ SIZE.constant = 32; \
+}
+
+#include "tm-mips.h"
diff --git a/gcc-1.40/config/tm-isi68-nfp.h b/gcc-1.40/config/tm-isi68-nfp.h
new file mode 100644
index 0000000..c51d5a8
--- /dev/null
+++ b/gcc-1.40/config/tm-isi68-nfp.h
@@ -0,0 +1,5 @@
+/* Define target machine as an ISI 68000/68020 with no 68881. */
+
+#define TARGET_DEFAULT 5
+
+#include "tm-isi68.h"
diff --git a/gcc-1.40/config/tm-isi68.h b/gcc-1.40/config/tm-isi68.h
new file mode 100644
index 0000000..5900e2b
--- /dev/null
+++ b/gcc-1.40/config/tm-isi68.h
@@ -0,0 +1,79 @@
+/* Definitions of target machine for GNU compiler. ISI 68000/68020 version.
+ Intended only for use with GAS, and not ISI's assembler, which is buggy
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+#endif
+
+#if TARGET_DEFAULT & 2
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+
+/* If the 68881 is used, link must load libmc.a instead of libc.a */
+
+#define LIB_SPEC "%{msoft-float:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}%{!msoft-float:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}}"
+
+#else
+/* Define __HAVE_68881__ in preprocessor if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
+
+/* If the 68881 is used, link must load libmc.a instead of libc.a */
+
+#define LIB_SPEC "%{!m68881:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}%{m68881:%{!p:%{!pg:-lmc}}%{p:-lmc_p}%{pg:-lmc_p}}"
+#endif
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dunix -Dmc68000 -Dis68k"
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Override parts of tm-m68000.h to fit the ISI 68k machine. */
+
+#undef FUNCTION_VALUE
+#undef LIBCALL_VALUE
+#undef FUNCTION_VALUE_REGNO_P
+#undef ASM_FILE_START
+
+/* If TARGET_68881, return SF and DF values in f0 instead of d0. */
+
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), ((TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0))
+
+/* 1 if N is a possible register number for a function value.
+ D0 may be used, and F0 as well if -m68881 is specified. */
+
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == 0 || (TARGET_68881 && (N) == 16))
+
+/* Also output something to cause the correct _doprnt to be loaded. */
+#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n%s\n", TARGET_68881 ? ".globl fltused" : "")
diff --git a/gcc-1.40/config/tm-m68k.h b/gcc-1.40/config/tm-m68k.h
new file mode 100644
index 0000000..256b06e
--- /dev/null
+++ b/gcc-1.40/config/tm-m68k.h
@@ -0,0 +1,1643 @@
+/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+/* See tm-sun3.h, tm-sun2.h, tm-isi68.h for different CPP_PREDEFINES. */
+
+/* Print subsidiary information on the compiler version in use. */
+#ifdef MOTOROLA
+#define TARGET_VERSION fprintf (stderr, " (68k, Motorola syntax)");
+#else
+#define TARGET_VERSION fprintf (stderr, " (68k, MIT syntax)");
+#endif
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Compile for a 68020 (not a 68000 or 68010). */
+#define TARGET_68020 (target_flags & 1)
+/* Compile 68881 insns for floating point (not library calls). */
+#define TARGET_68881 (target_flags & 2)
+/* Compile using 68020 bitfield insns. */
+#define TARGET_BITFIELD (target_flags & 4)
+/* Compile using rtd insn calling sequence.
+ This will not work unless you use prototypes at least
+ for all functions that can take varying numbers of args. */
+#define TARGET_RTD (target_flags & 8)
+/* Compile passing first two args in regs 0 and 1.
+ This exists only to test compiler features that will
+ be needed for RISC chips. It is not usable
+ and is not intended to be usable on this cpu. */
+#define TARGET_REGPARM (target_flags & 020)
+/* Compile with 16-bit `int'. */
+#define TARGET_SHORT (target_flags & 040)
+
+/* Compile with special insns for Sun FPA. */
+#define TARGET_FPA (target_flags & 0100)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { { "68020", 5}, \
+ { "c68020", 5}, \
+ { "68881", 2}, \
+ { "bitfield", 4}, \
+ { "68000", -5}, \
+ { "c68000", -5}, \
+ { "soft-float", -0102}, \
+ { "nobitfield", -4}, \
+ { "rtd", 8}, \
+ { "nortd", -8}, \
+ { "short", 040}, \
+ { "noshort", -040}, \
+ { "fpa", 0100}, \
+ { "nofpa", -0100}, \
+ { "", TARGET_DEFAULT}}
+/* TARGET_DEFAULT is defined in tm-sun*.h and tm-isi68.h, etc. */
+
+/* Blow away 68881 flag silently on TARGET_FPA (since we can't clear
+ any bits in TARGET_SWITCHES above) */
+#define OVERRIDE_OPTIONS \
+{ \
+ if (TARGET_FPA) target_flags &= ~2; \
+}
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is true for 68020 insns such as bfins and bfexts.
+ We make it true always by avoiding using the single-bit insns
+ except in special cases with constant bit numbers. */
+#define BITS_BIG_ENDIAN
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the 68000. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For 68000 we can decide arbitrarily
+ since there are no machine instructions for them. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY (TARGET_SHORT ? 16 : 32)
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 16
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Define number of bits in most basic integer type.
+ (If undefined, default is BITS_PER_WORD). */
+
+#define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32)
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+ For the 68000, we give the data registers numbers 0-7,
+ the address registers numbers 010-017,
+ and the 68881 floating point registers numbers 020-027. */
+#define FIRST_PSEUDO_REGISTER 56 /* 24 */
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the 68000, only the stack pointer is such. */
+/* fpa0 is also reserved so that it can be used to move shit back and
+ forth between high fpa regs and everything else. */
+#define FIXED_REGISTERS \
+ {0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* FPA registers. */ \
+ 1, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, }
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ /* FPA registers. */ \
+ 1, 1, 1, 1, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, }
+
+/* Make sure everything's fine if we *don't* have a given processor.
+ This assumes that putting a register in fixed_regs will keep the
+ compilers mitt's completely off it. We don't bother to zero it out
+ of register classes. If neither TARGET_FPA or TARGET_68881 is set,
+ the compiler won't touch since no instructions that use these
+ registers will be valid. */
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ int i; \
+ HARD_REG_SET x; \
+ if (!TARGET_FPA) \
+ { \
+ COPY_HARD_REG_SET (x, reg_class_contents[(int)FPA_REGS]); \
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
+ if (TEST_HARD_REG_BIT (x, i)) \
+ fixed_regs[i] = call_used_regs[i] = 1; \
+ } \
+ if (TARGET_FPA) \
+ { \
+ COPY_HARD_REG_SET (x, reg_class_contents[(int)FP_REGS]); \
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
+ if (TEST_HARD_REG_BIT (x, i)) \
+ fixed_regs[i] = call_used_regs[i] = 1; \
+ } \
+}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the 68000, ordinary registers hold 32 bits worth;
+ for the 68881 registers, a single register is always enough for
+ anything that can be stored in them at all. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((REGNO) >= 16 ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the 68000, the cpu registers can hold any mode but the 68881 registers
+ can hold only SFmode or DFmode. And the 68881 registers can't hold anything
+ if 68881 use is disabled. However, the Sun FPA register can
+ (apparently) hold whatever you feel like putting in them. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (((REGNO) < 16 && \
+ (!TARGET_FPA || (MODE) != DFmode || (REGNO) != 7)) \
+ || ((REGNO) < 24 \
+ ? TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode) \
+ : ((REGNO) < 56 \
+ ? TARGET_FPA : 0)))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (! TARGET_68881 \
+ || (((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode)))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* m68000 pc isn't overloaded on a register. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 15
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 14
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 14
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 8
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 9
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The 68000 has three kinds of registers, so eight classes would be
+ a complete set. One of them is not needed. */
+
+/*
+ * Notes on final choices:
+ *
+ * 1) Didn't feel any need to union-ize LOW_FPA_REGS with anything
+ * else.
+ * 2) Removed all unions that involve address registers with
+ * floating point registers (left in unions of address and data with
+ * floating point).
+ * 3) Defined GENERAL_REGS as ADDR_OR_DATA_REGS.
+ * 4) Defined ALL_REGS as FPA_OR_FP_OR_GENERAL_REGS.
+ * 4) Left in everything else.
+ */
+enum reg_class { NO_REGS, LO_FPA_REGS, FPA_REGS, FP_REGS,
+ FP_OR_FPA_REGS, DATA_REGS, DATA_OR_FPA_REGS, DATA_OR_FP_REGS,
+ DATA_OR_FP_OR_FPA_REGS, ADDR_REGS, GENERAL_REGS,
+ GENERAL_OR_FPA_REGS, GENERAL_OR_FP_REGS, ALL_REGS,
+ LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ { "NO_REGS", "LO_FPA_REGS", "FPA_REGS", "FP_REGS", \
+ "FP_OR_FPA_REGS", "DATA_REGS", "DATA_OR_FPA_REGS", "DATA_OR_FP_REGS", \
+ "DATA_OR_FP_OR_FPA_REGS", "ADDR_REGS", "GENERAL_REGS", \
+ "GENERAL_OR_FPA_REGS", "GENERAL_OR_FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ {0, 0}, /* NO_REGS */ \
+ {0xff000000, 0x000000ff}, /* LO_FPA_REGS */ \
+ {0xff000000, 0x00ffffff}, /* FPA_REGS */ \
+ {0x00ff0000, 0x00000000}, /* FP_REGS */ \
+ {0xffff0000, 0x00ffffff}, /* FP_OR_FPA_REGS */ \
+ {0x000000ff, 0x00000000}, /* DATA_REGS */ \
+ {0xff0000ff, 0x00ffffff}, /* DATA_OR_FPA_REGS */ \
+ {0x00ff00ff, 0x00000000}, /* DATA_OR_FP_REGS */ \
+ {0xffff00ff, 0x00ffffff}, /* DATA_OR_FP_OR_FPA_REGS */\
+ {0x0000ff00, 0x00000000}, /* ADDR_REGS */ \
+ {0x0000ffff, 0x00000000}, /* GENERAL_REGS */ \
+ {0xff00ffff, 0x00ffffff}, /* GENERAL_OR_FPA_REGS */\
+ {0x00ffffff, 0x00000000}, /* GENERAL_OR_FP_REGS */\
+ {0xffffffff, 0x00ffffff}, /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+extern enum reg_class regno_reg_class[];
+#define REGNO_REG_CLASS(REGNO) (regno_reg_class[(REGNO)>>3])
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS ADDR_REGS
+
+/* Get reg_class from a letter such as appears in the machine description.
+ We do a trick here to modify the effective constraints on the
+ machine description; we zorch the constraint letters that aren't
+ appropriate for a specific target. This allows us to guarantee
+ that a specific kind of register will not be used for a given target
+ without fiddling with the register classes above. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'a' ? ADDR_REGS : \
+ ((C) == 'd' ? DATA_REGS : \
+ ((C) == 'f' ? (TARGET_68881 ? FP_REGS : \
+ NO_REGS) : \
+ ((C) == 'x' ? (TARGET_FPA ? FPA_REGS : \
+ NO_REGS) : \
+ ((C) == 'y' ? (TARGET_FPA ? LO_FPA_REGS : \
+ NO_REGS) : \
+ NO_REGS)))))
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For the 68000, `I' is used for the range 1 to 8
+ allowed as immediate shift counts and in addq.
+ `J' is used for the range of signed numbers that fit in 16 bits.
+ `K' is for numbers that moveq can't handle.
+ `L' is for range -8 to -1, range of values that can be added with subq. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (VALUE) > 0 && (VALUE) <= 8 : \
+ (C) == 'J' ? (VALUE) >= -0x8000 && (VALUE) <= 0x7FFF : \
+ (C) == 'K' ? (VALUE) < -0x80 || (VALUE) >= 0x80 : \
+ (C) == 'L' ? (VALUE) < 0 && (VALUE) >= -8 : 0)
+
+/*
+ * A small bit of explanation:
+ * "G" defines all of the floating constants that are *NOT* 68881
+ * constants. this is so 68881 constants get reloaded and the
+ * fpmovecr is used. "H" defines *only* the class of constants that
+ * the fpa can use, because these can be gotten at in any fpa
+ * instruction and there is no need to force reloads.
+ */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? ! (TARGET_68881 && standard_68881_constant_p (VALUE)) : \
+ (C) == 'H' ? (TARGET_FPA && standard_sun_fpa_constant_p (VALUE)) : 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class.
+ On the 68000 series, use a data reg if possible when the
+ value is a constant in the range where moveq could be used
+ and we ensure that QImodes are reloaded into data regs. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ ((GET_CODE (X) == CONST_INT \
+ && (unsigned) (INTVAL (X) + 0x80) < 0x100 \
+ && (CLASS) != ADDR_REGS) \
+ ? DATA_REGS \
+ : GET_MODE (X) == QImode \
+ ? DATA_REGS \
+ : (CLASS))
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the 68000, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS || (CLASS) == FPA_REGS || (CLASS) == LO_FPA_REGS ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the 68000, sp@- in a byte insn really pushes a word. */
+#define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 8
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ On the 68000, the RTS insn cannot pop anything.
+ On the 68010, the RTD insn may be used to pop them if the number
+ of args is fixed, but if the number is variable then the caller
+ must pop them all. RTD can't be used for library calls now
+ because the library is compiled with the Unix compiler.
+ Use of RTD is a selectable option, since it is incompatible with
+ standard Unix calling sequences. If the option is not selected,
+ the caller must always pop the args. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) \
+ (TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \
+ || TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) == void_type_node))
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the 68000 the return value is in D0 regardless. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On the 68000 the return value is in D0 regardless. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0)
+
+/* 1 if N is a possible register number for a function value.
+ On the 68000, d0 is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for function argument passing.
+ On the 68000, no registers are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the m68k, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the m68k, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the 68000 all args are pushed, except if -mregparm is specified
+ then the first two words of arguments are passed in d0, d1.
+ *NOTE* -mregparm does not work.
+ It exists only to test register calling conventions. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8) ? gen_rtx (REG, (MODE), (CUM) / 4) : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8 \
+ && 8 < ((CUM) + ((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) \
+ : GET_MODE_SIZE (MODE)))) \
+ ? 2 - (CUM) / 4 : 0)
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* Note that the order of the bit mask for fmovem is the opposite
+ of the order for movem! */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ if (frame_pointer_needed) \
+ { if (TARGET_68020 || fsize < 0x8000) \
+ fprintf (FILE, "\tlink a6,#%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink a6,#0\n\tsubl #%d,sp\n", fsize); } \
+ for (regno = 24; regno < 56; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ fprintf(FILE, "\tfpmoved %s, sp@-\n", \
+ reg_names[regno]); \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if ((mask & 0xff) != 0) \
+ fprintf (FILE, "\tfmovem #0x%x,sp@-\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmovel %s,sp@-\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmoveml #0x%x,sp@-\n", mask); }
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tlea LP%d,a0\n\tjsr mcount\n", (LABELNO))
+
+/* Output assembler code to FILE to initialize this source file's
+ basic block profiling info, if that has not already been done. */
+
+#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\ttstl LPBX0\n\tbne LPI%d\n\tpea LPBX0\n\tjsr ___bb_init_func\n\taddql #4,sp\nLPI%d:\n", \
+ LABELNO, LABELNO);
+
+/* Output assembler code to FILE to increment the entry-count for
+ the BLOCKNO'th basic block in this source file. */
+
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+ fprintf (FILE, "\taddql #1,LPBX2+%d\n", 4 * BLOCKNO)
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset, fpoffset; \
+ extern char call_used_regs[]; \
+ extern int current_function_pops_args; \
+ extern int current_function_args_size; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ FUNCTION_EXTRA_EPILOGUE (FILE, SIZE); \
+ nregs = 0; fmask = 0; fpoffset = 0; \
+ for (regno = 24 ; regno < 56 ; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ nregs++; \
+ fpoffset = nregs*8; \
+ nregs = 0; \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = fpoffset + nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask || fpoffset)) \
+ { fprintf (FILE, "\tmovel #%d,a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmovel a6@(-%d,a0:l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovel sp@+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmovel a6@(-%d),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmoveml a6@(-%d,a0:l),#0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmoveml sp@+,#0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmoveml a6@(-%d),#0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem a6@(-%d,a0:l),#0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem sp@+,#0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem a6@(-%d),#0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (fpoffset != 0) \
+ for (regno = 55; regno >= 24; regno--) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
+ if (big) \
+ fprintf(FILE, "\tfpmoved a6@(-%d,a0:l), %s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ else if (! frame_pointer_needed) \
+ fprintf(FILE, "\tfpmoved sp@+, %s\n", \
+ reg_names[regno]); \
+ else \
+ fprintf(FILE, "\tfpmoved a6@(-%d), %s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ fpoffset -= 8; \
+ } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk a6\n"); \
+ if (current_function_pops_args && current_function_args_size) \
+ fprintf (FILE, "\trtd #%d\n", current_function_args_size); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* This is a hook for other tm files to change. */
+#define FUNCTION_EXTRA_EPILOGUE(FILE, SIZE)
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ rtx regs = stack_pointer_rtx; \
+ if (ADDR == frame_pointer_rtx) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 1); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 0); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 1); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS \
+ && GET_CODE (XEXP (ADDR, 0)) == PLUS \
+ && XEXP (XEXP (ADDR, 0), 1) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ { rtx other_reg = XEXP (XEXP (ADDR, 0), 0); \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 12; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (regs, offset + (DEPTH)); } } \
+
+/* Addressing modes, and classification of registers for them. */
+
+#define HAVE_POST_INCREMENT
+/* #define HAVE_POST_DECREMENT */
+
+#define HAVE_PRE_DECREMENT
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+(((REGNO) ^ 010) < 8 || (unsigned) (reg_renumber[REGNO] ^ 010) < 8)
+#define REGNO_OK_FOR_DATA_P(REGNO) \
+((REGNO) < 8 || (unsigned) reg_renumber[REGNO] < 8)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 020) < 8 || (unsigned) (reg_renumber[REGNO] ^ 020) < 8)
+#define REGNO_OK_FOR_FPA_P(REGNO) \
+(((REGNO) >= 24 && (REGNO) < 56) || (reg_renumber[REGNO] >= 24 && reg_renumber[REGNO] < 56))
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the 68000, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is a data register. */
+
+#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* 1 if X is an address register */
+
+#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
+
+/* 1 if X is a register in the Sun FPA. */
+#define FPA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FPA_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) ((REGNO (X) ^ 020) >= 8)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) ((REGNO (X) & ~027) != 0)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
+
+#define INDIRECTABLE_1_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
+ && REG_P (XEXP (X, 0)) \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ || (GET_CODE (X) == PLUS \
+ && REG_P (XEXP (X, 0)) && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))
+
+#if 0
+/* This should replace the last two lines
+ except that Sun's assembler does not seem to handle such operands. */
+ && (TARGET_68020 ? CONSTANT_ADDRESS_P (XEXP (X, 1)) \
+ : (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))))
+#endif
+
+
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }
+
+#define GO_IF_INDEXABLE_BASE(X, ADDR) \
+{ if (GET_CODE (X) == LABEL_REF) goto ADDR; \
+ if (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) goto ADDR; }
+
+#define GO_IF_INDEXING(X, ADDR) \
+{ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \
+ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \
+ { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
+
+#define GO_IF_INDEXED_ADDRESS(X, ADDR) \
+{ GO_IF_INDEXING (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100) \
+ { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); } \
+ if (GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100) \
+ { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } }
+
+#define LEGITIMATE_INDEX_REG_P(X) \
+ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
+ || (GET_CODE (X) == SIGN_EXTEND \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && GET_MODE (XEXP (X, 0)) == HImode \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 0))))
+
+#define LEGITIMATE_INDEX_P(X) \
+ (LEGITIMATE_INDEX_REG_P (X) \
+ || (TARGET_68020 && GET_CODE (X) == MULT \
+ && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (INTVAL (XEXP (X, 1)) == 2 \
+ || INTVAL (XEXP (X, 1)) == 4 \
+ || INTVAL (XEXP (X, 1)) == 8)))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
+ GO_IF_INDEXED_ADDRESS (X, ADDR); }
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the 68000, we handle X+REG by loading X into a register R and
+ using R+REG. R will go in an address reg and indexing will be used.
+ However, if REG is a broken-out memory address or multiplication,
+ nothing needs to be done because REG can certainly go in an address reg. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ register int ch = (X) != (OLDX); \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 0)) == MULT) \
+ ch = 1, XEXP (X, 0) = force_operand (XEXP (X, 0), 0); \
+ if (GET_CODE (XEXP (X, 1)) == MULT) \
+ ch = 1, XEXP (X, 1) = force_operand (XEXP (X, 1), 0); \
+ if (ch && GET_CODE (XEXP (X, 1)) == REG \
+ && GET_CODE (XEXP (X, 0)) == REG) \
+ return X; \
+ if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); } \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 1), 0); \
+ emit_move_insn (temp, val); \
+ XEXP (X, 1) = temp; \
+ return X; } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND \
+ && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG \
+ && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode)) \
+ { register rtx temp = gen_reg_rtx (Pmode); \
+ register rtx val = force_operand (XEXP (X, 0), 0); \
+ emit_move_insn (temp, val); \
+ XEXP (X, 0) = temp; \
+ return X; }}}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the 68000, only predecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand). */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) goto LABEL
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE HImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+#define SLOW_ZERO_EXTEND
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE -1
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ /* Constant zero is super cheap due to clr instruction. */ \
+ if (RTX == const0_rtx) return 0; \
+ if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* Set if the cc value is actually in the 68881, so a floating point
+ conditional branch must be output. */
+#define CC_IN_68881 04000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* On the 68000, all the insns to store in an address register
+ fail to set the cc's. However, in some cases these instructions
+ can make it possibly invalid to use the saved cc's. In those
+ cases we clear out some or all of the saved cc's so they won't be used. */
+
+/* It was claimed recently that addq, subq to an address register
+ do update the cc's, but the 68000 and 68020 manuals say otherwise. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ \
+ /* If the cc is being set from the fpa and the
+ expression is not an explicit floating point
+ test instruction (which has code to deal with
+ this), reinit the CC */ \
+ if (((cc_status.value1 && FPA_REG_P (cc_status.value1)) \
+ || (cc_status.value2 && FPA_REG_P (cc_status.value2))) \
+ && !(GET_CODE(EXP) == PARALLEL \
+ && GET_CODE (XVECEXP(EXP, 0, 0)) == SET \
+ && XEXP (XVECEXP (EXP, 0, 0), 0) == cc0_rtx)) \
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (EXP) == SET) \
+ { if (ADDRESS_REG_P (SET_DEST (EXP))) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2)) \
+ cc_status.value2 = 0; } \
+ else if (!FP_REG_P (SET_DEST (EXP)) \
+ && SET_DEST (EXP) != cc0_rtx \
+ && (FP_REG_P (SET_SRC (EXP)) \
+ || GET_CODE (SET_SRC (EXP)) == FIX \
+ || GET_CODE (SET_SRC (EXP)) == FLOAT_TRUNCATE \
+ || GET_CODE (SET_SRC (EXP)) == FLOAT_EXTEND)) \
+ { CC_STATUS_INIT; } \
+ /* A pair of move insns doesn't produce a useful overall cc. */ \
+ else if (!FP_REG_P (SET_DEST (EXP)) \
+ && !FP_REG_P (SET_SRC (EXP)) \
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (EXP))) > 4 \
+ && (GET_CODE (SET_SRC (EXP)) == REG \
+ || GET_CODE (SET_SRC (EXP)) == MEM \
+ || GET_CODE (SET_SRC (EXP)) == CONST_DOUBLE))\
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (SET_SRC (EXP)) == CALL) \
+ { CC_STATUS_INIT; } \
+ else if (XEXP (EXP, 0) != pc_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = XEXP (EXP, 0); \
+ cc_status.value2 = XEXP (EXP, 1); } } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \
+ { \
+ if (ADDRESS_REG_P (XEXP (XVECEXP (EXP, 0, 0), 0))) \
+ CC_STATUS_INIT; \
+ else if (XEXP (XVECEXP (EXP, 0, 0), 0) != pc_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = XEXP (XVECEXP (EXP, 0, 0), 0); \
+ cc_status.value2 = XEXP (XVECEXP (EXP, 0, 0), 1); } } \
+ else CC_STATUS_INIT; \
+ if (cc_status.value2 != 0 \
+ && ADDRESS_REG_P (cc_status.value2) \
+ && GET_MODE (cc_status.value2) == QImode) \
+ CC_STATUS_INIT; \
+ if (cc_status.value2 != 0 \
+ && !(cc_status.value1 && FPA_REG_P (cc_status.value1))) \
+ switch (GET_CODE (cc_status.value2)) \
+ { case PLUS: case MINUS: case MULT: case UMULT: \
+ case DIV: case UDIV: case MOD: case UMOD: case NEG: \
+ case ASHIFT: case LSHIFT: case ASHIFTRT: case LSHIFTRT: \
+ case ROTATE: case ROTATERT: \
+ if (GET_MODE (cc_status.value2) != VOIDmode) \
+ cc_status.flags |= CC_NO_OVERFLOW; \
+ break; \
+ case ZERO_EXTEND: \
+ case ZERO_EXTRACT: \
+ /* (SET r1 (ZERO_EXTEND r2)) on this machine
+ ends with a move insn moving r2 in r2's mode.
+ Thus, the cc's are set for r2.
+ This can set N bit spuriously. */ \
+ cc_status.flags |= CC_NOT_NEGATIVE; } \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \
+ && cc_status.value2 \
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \
+ cc_status.value2 = 0; \
+ if (((cc_status.value1 && FP_REG_P (cc_status.value1)) \
+ || (cc_status.value2 && FP_REG_P (cc_status.value2))) \
+ && !((cc_status.value1 && FPA_REG_P (cc_status.value1)) \
+ || (cc_status.value2 && FPA_REG_P (cc_status.value2)))) \
+ cc_status.flags = CC_IN_68881; }
+
+#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
+do { if (cc_prev_status.flags & CC_IN_68881) \
+ return FLOAT; \
+ if (cc_prev_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; } while (0)
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, "#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fpa0", "fpa1", "fpa2", "fpa3", "fpa4", "fpa5", "fpa6", "fpa7", \
+ "fpa8", "fpa9", "fpa10", "fpa11", "fpa12", "fpa13", "fpa14", "fpa15", \
+ "fpa16", "fpa17", "fpa18", "fpa19", "fpa20", "fpa21", "fpa22", "fpa23", \
+ "fpa24", "fpa25", "fpa26", "fpa27", "fpa28", "fpa29", "fpa30", "fpa31", }
+
+/* How to renumber registers for dbx and gdb.
+ On the Sun-3, the floating point registers have numbers
+ 18 to 25, not 16 to 23 as they do in the compiler. */
+
+#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2)
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0r%.20g\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+/* Sun's assembler can't handle floating constants written as floating.
+ However, when cross-compiling, always use that in case format differs. */
+
+#ifdef CROSS_COMPILER
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.float 0r%.10g\n", (VALUE))
+
+#else
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fprintf (FILE, "\t.long 0x%x\n", tem.l); \
+ } while (0)
+
+#endif /* not CROSS_COMPILER */
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmovel %s,sp@-\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovel sp@+,%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\t.even\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.skip %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ fprintf (FILE, "#0r%.9g", (VALUE))
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ fprintf (FILE, "#0r%.20g", (VALUE))
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the 68000, we use several CODE characters:
+ '.' for dot needed in Motorola-style opcode names.
+ '-' for an operand pushing on the stack:
+ sp@-, -(sp) or -(%sp) depending on the style of syntax.
+ '+' for an operand pushing on the stack:
+ sp@+, (sp)+ or (%sp)+ depending on the style of syntax.
+ '@' for a reference to the top word on the stack:
+ sp@, (sp) or (%sp) depending on the style of syntax.
+ '#' for an immediate operand prefix (# in MIT and Motorola syntax
+ but & in SGS syntax).
+ '!' for the cc register (used in an `and to cc' insn).
+
+ 'b' for byte insn (no effect, on the Sun; this is for the ISI).
+ 'd' to force memory addressing to be absolute, not relative.
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather
+ than directly). Second part of 'y' below.
+ 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex),
+ or print pair of registers as rx:ry.
+ 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs
+ CONST_DOUBLE's as SunFPA constant RAM registers if
+ possible, so it should not be used except for the SunFPA. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \
+ || (CODE) == '+' || (CODE) == '@' || (CODE) == '!')
+
+/* This assumes the compiler is running on a big-endian machine.
+ The support for the other case is left for version 2. */
+#define PRINT_OPERAND_EXTRACT_FLOAT(X) \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);
+
+#ifdef CROSS_COMPILER
+#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE) \
+ ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f);
+#else
+#define PRINT_OPERAND_PRINT_FLOAT(CODE, FILE) \
+{ if (CODE == 'f') \
+ ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); \
+ else \
+ fprintf (FILE, "#0x%x", u1.i); }
+#endif
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ int i; \
+ if (CODE == '.') ; \
+ else if (CODE == '#') fprintf (FILE, "#"); \
+ else if (CODE == '-') fprintf (FILE, "sp@-"); \
+ else if (CODE == '+') fprintf (FILE, "sp@+"); \
+ else if (CODE == '@') fprintf (FILE, "sp@"); \
+ else if (CODE == '!') fprintf (FILE, "cc"); \
+ else if (GET_CODE (X) == REG) \
+ { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \
+ fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \
+ else \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ } \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ output_address (XEXP (X, 0)); \
+ if (CODE == 'd' && ! TARGET_68020 \
+ && CONSTANT_ADDRESS_P (XEXP (X, 0)) \
+ && !(GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && INTVAL (XEXP (X, 0)) < 0x8000 \
+ && INTVAL (XEXP (X, 0)) >= -0x8000)) \
+ fprintf (FILE, ":l"); \
+ } \
+ else if ((CODE == 'y' || CODE == 'w') \
+ && GET_CODE(X) == CONST_DOUBLE \
+ && (i = standard_sun_fpa_constant_p (X))) \
+ fprintf (FILE, "%%%d", i & 0x1ff); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ PRINT_OPERAND_EXTRACT_FLOAT (X); \
+ u1.f = u.d; \
+ PRINT_OPERAND_PRINT_FLOAT (CODE, FILE); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ PRINT_OPERAND_EXTRACT_FLOAT (X); \
+ ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+
+/* Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...))
+ is in the insn before a tablejump, and we know that m68k.md
+ generates a label LInnn: on such an insn. */
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "%s@", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "%s@-", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "%s@+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "pc@(L%d-LI%d-2:b,%s:w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "pc@(L%d-LI%d-2:b,%s:l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "pc@(L%d-LI%d-2:b,%s:l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ fprintf (FILE, "%s@(", reg_names[REGNO (breg)]); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ if (addr != 0 && ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s:w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s:l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, ":%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "pc@(L%d-LI%d-2:b,%s:l)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d:w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/gcc-1.40/config/tm-m88k.h b/gcc-1.40/config/tm-m88k.h
new file mode 100644
index 0000000..1725c68
--- /dev/null
+++ b/gcc-1.40/config/tm-m88k.h
@@ -0,0 +1,1128 @@
+/* Definitions of target machine for GNU compiler, for the Motorola 88000 chip.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dm88000 -Dm88k"
+
+/* Print subsidiary information on the compiler version in use. */
+#define TARGET_VERSION fprintf (stderr, " (88k)");
+
+/* Run-time compilation parameters selecting different hardware subsets.
+
+ On the the m88000, we don't yet need any. */
+
+extern int target_flags;
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ {{ "", TARGET_DEFAULT}}
+
+#define TARGET_DEFAULT 1
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields. */
+#define BITS_BIG_ENDIAN
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the m88000. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For the m88000 we can decide arbitrarily
+ since there are no machine instructions for them. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 64
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+
+ the m88000 has 32 fullword registers. */
+
+#define FIRST_PSEUDO_REGISTER 32
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+
+ On the 88000, these are:
+ Reg 0 = 0 (hardware).
+ Reg 1 = Subroutine return pointer (hardware).
+ [Reg 2-9 = Parameter registers (Motorola convention).]
+ Reg 25 = condition code register (Gnu).
+ Reg 26-29 = reserved by Motorola.
+ Reg 30 = frame pointer (software).
+ Reg 31 = stack pointer (software). */
+#define FIXED_REGISTERS \
+ {1, 1, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 1, 1, 1, 1, 1, 0, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 1, 1, 1, 1, 1, 0, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the m88000, ordinary registers hold 32 bits worth;
+ a single floating point register is always enough for
+ anything that can be stored in them at all. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the m88000, the cpu registers can hold any mode, but doubles
+ (and larger) must start and an even register number boundary. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (GET_MODE_SIZE (MODE) <= 4 || ((REGNO) & 1) == 0)
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == DFmode || (MODE1) == DImode) \
+ == ((MODE2) == DFmode || (MODE2) == DImode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* the m88000 pc isn't overloaded on a register that the compiler knows about. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 31
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 30
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 30
+
+/* Register in which static-chain is passed to a function. */
+/* ??? */
+#define STATIC_CHAIN_REGNUM 10
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 2
+#define STRUCT_VALUE_STACK_PROTECT_REGNUM 3
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The 88000 has one kind of registers, hence two classes. */
+
+enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Since GENERAL_REGS is the same class as ALL_REGS,
+ don't give it a different class number; just make it an alias. */
+
+#define GENERAL_REGS ALL_REGS
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES {"NO_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {0, -1}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) ALL_REGS
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS ALL_REGS
+#define BASE_REG_CLASS ALL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) NO_REGS
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For the m88000, `I' is used for the range of constants an insn
+ can actually contain.
+ `J' is used for the range which is just zero (since that is R0).
+ `K' is used for the 5-bit operand of a compare insns. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (unsigned) (VALUE) < 0x10000 \
+ : (C) == 'J' ? (VALUE) == 0 \
+ : (C) == 'K' ? (unsigned) (VALUE) < 0x20 \
+ : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' && XINT (VALUE, 0) == 0 && XINT (VALUE, 1) == 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame.
+
+ Do not define this for the Motorola 88000. There are no
+ negative literals! */
+/* #define FRAME_GROWS_DOWNWARD */
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the m88000, don't define this because there are no push insns. */
+/* #define PUSH_ROUNDING(BYTES) */
+
+/* If BYTES is the size of arguments for a function call,
+ return the size of the argument block (which is BYTES suitably rounded).
+ Define this only on machines where the entire call block is allocated
+ before the args are stored into it. */
+
+#define ROUND_CALL_BLOCK_SIZE(BYTES) \
+ (((BYTES) + 7) & ~7)
+
+/* Offset of first parameter from the argument pointer register value. */
+/* For the 88000, this must be non-zero so that addresses of the parms
+ can always be distinguished. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 0
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* ?? On the m88000 the value is found in the second "output" register. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 2)
+
+/* ?? But the called function leaves it in the second "input" register. */
+
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 2)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 2)
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller.
+ On the m88000, the first "output" reg is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2)
+
+/* 1 if N is a possible register number for function argument passing.
+ On the m88000, these are the "output" registers. */
+
+#define FUNCTION_ARG_REGNO_P(N) ((N) <= 9 && (N) >= 2)
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the m88000, this is a single integer, which is a number of words
+ of arguments scanned so far (including the invisible argument,
+ if any, which holds the structure-value-address).
+ Thus 8 or more means all following args should go on the stack. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the m88000, the offset normally starts at 0, but starts at 4 bytes
+ when the function gets a structure-value-address as an
+ invisible first argument. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = ((FNTYPE) != 0 && aggregate_value_p ((FNTYPE))))
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) / 4 \
+ : (int_size_in_bytes (TYPE) + 3) / 4))
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the m88000 the first eight words of args are normally in registers
+ and the rest are pushed. But any arg that won't entirely fit in regs
+ is pushed. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+(8 >= ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) \
+ ? gen_rtx (REG, (MODE), 2 + (CUM)) \
+ : 0)
+
+/* Define where a function finds its arguments.
+ This would be different from FUNCTION_ARG if we had register windows. */
+
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+ FUNCTION_ARG (CUM, MODE, TYPE, NAMED)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int current_function_pretend_args_size; \
+ extern int frame_pointer_needed; \
+ int fsize = ((SIZE) + current_function_pretend_args_size + 7) & ~7; \
+ int regno, nregs, i; \
+ int offset = 0; \
+ for (regno = 2, nregs = 0; regno < FRAME_POINTER_REGNUM; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ nregs++; \
+ nregs = (nregs + 1) & ~1; \
+ if (regs_ever_live[1] + frame_pointer_needed + nregs) \
+ { \
+ if (fsize + 8 + nregs*4 < 0x10000) \
+ offset = fsize; \
+ fprintf (FILE, "\tsub r31,r31,%d\n", 8 + nregs*4 + offset); \
+ } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tst r30,r31,%d\n", offset); \
+ if (regs_ever_live[1]) \
+ fprintf (FILE, "\tst r1,r31,%d\n", 4 + offset); \
+ if (nregs) \
+ for (regno = 2, nregs = 2; regno < FRAME_POINTER_REGNUM; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ if (regno & 1 || !regs_ever_live[regno+1] || call_used_regs[regno+1])\
+ fprintf (FILE, "\tst r%d,r31,%d\n", regno, offset + nregs++ * 4);\
+ else \
+ { \
+ fprintf (FILE, "\tst.d r%d,r31,%d\n", regno, offset + nregs * 4);\
+ regno += 1; nregs += 2; \
+ } \
+ if (offset || fsize == 0) /* do nothing. */ ; \
+ else if ((unsigned) fsize < 0x10000) \
+ fprintf (FILE, "\tsub r31,r31,%d\n", fsize); \
+ else fprintf (FILE, "\tor.u r25,r0,hi16(%d)\n\tor r25,r0,lo16(%d)\n\tsub r31,r31,r25\n", fsize, fsize); \
+ if (frame_pointer_needed) fprintf (FILE, "\tor r30,r0,r31\n"); \
+}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ abort ();
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+extern int may_call_alloca;
+extern int current_function_pretend_args_size;
+
+#define EXIT_IGNORE_STACK \
+ (get_frame_size () != 0 \
+ || may_call_alloca || current_function_pretend_args_size)
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int may_call_alloca; \
+ int fsize = ((SIZE) + current_function_pretend_args_size + 7) & ~7; \
+ int nregs, regno, i; \
+ for (regno = 2, nregs = 0; regno < FRAME_POINTER_REGNUM; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ nregs++; \
+ if (frame_pointer_needed) \
+ { \
+ if ((unsigned) fsize < 0x10000) \
+ fprintf (FILE, "\tadd r31,r30,%d\n", fsize); \
+ else fprintf (FILE, "\tor.u r25,r0,hi16(%d)\n\tor r25,r0,lo16(%d)\n\tadd r31,r30,r25\n", fsize, fsize); \
+ } \
+ else if (fsize) fprintf (FILE, "\tadd r31,r31,%d\n", fsize); \
+ if (nregs) \
+ for (regno = 2, nregs = 2; regno < FRAME_POINTER_REGNUM; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ if (regno & 1 || !regs_ever_live[regno+1] || call_used_regs[regno+1])\
+ fprintf (FILE, "\tld r%d,r31,%d\n", regno, nregs++ * 4);\
+ else \
+ { \
+ fprintf (FILE, "\tld.d r%d,r31,%d\n", regno, nregs * 4);\
+ regno += 1; nregs += 2; \
+ } \
+ if (regs_ever_live[1]) \
+ fprintf (FILE, "\tld r1,r31,4\n"); \
+ else \
+ fprintf (FILE, ";; r1 is set to go!\n"); \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tld r30,r31,0\n"); \
+ nregs = (nregs + 1) & ~1; \
+ if (regs_ever_live[1] + frame_pointer_needed + (nregs > 2)) \
+ fprintf (FILE, "\tjmp.n r1\n\taddu r31,r31,%d\n", nregs * 4); \
+ else fprintf (FILE, "\tjmp r1\n"); \
+ /* let insn reorganizer know that we are at the end of a function. */ \
+ fprintf (FILE, "\tdata\n"); \
+}
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ rtx regs = stack_pointer_rtx; \
+ if (ADDR == frame_pointer_rtx) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 1); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 0); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (regs, offset + (DEPTH)); } }
+
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ ((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the the m88000, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) (1)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (1)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (1)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ On the m88000, the actual legitimate addresses must be REG+REG or REG+SMALLINT.
+ But we can treat a SYMBOL_REF as legitimate if it is part of this
+ function's constant-pool, because such addresses can actually
+ be output as REG+SMALLINT. */
+
+#define INT_FITS_16_BITS(I) ((unsigned) (I) < 0x10000)
+
+#define FITS_16_BITS(X) \
+ (GET_CODE (X) == CONST_INT && INT_FITS_16_BITS (INTVAL (X)))
+
+#define LEGITIMATE_INDEX_P(X, MODE) \
+ (FITS_16_BITS (X) \
+ || (REG_P (X) \
+ && REG_OK_FOR_INDEX_P (X)) \
+ || (GET_CODE (X) == MULT \
+ && REG_P (XEXP (X, 0)) \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (INTVAL (XEXP (X, 1)) == GET_MODE_SIZE (MODE))) \
+ || (GET_CODE (X) == MULT \
+ && REG_P (XEXP (X, 1)) \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 1)) \
+ && GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && (INTVAL (XEXP (X, 0)) == GET_MODE_SIZE (MODE)) \
+ && (warning ("MULT backwards"), 1)))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (GET_CODE (X) == CONST_INT) \
+ { \
+ if (FITS_16_BITS (X)) \
+ goto ADDR; \
+ } \
+ else if (CONSTANT_ADDRESS_P (X)) \
+ goto ADDR; \
+ else if (REG_P (X)) \
+ { \
+ if (REG_OK_FOR_BASE_P (X)) \
+ goto ADDR; \
+ } \
+ else if (GET_CODE (X) == PLUS) \
+ if (REG_P (XEXP (X, 0)) \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ { \
+ if (LEGITIMATE_INDEX_P (XEXP (X, 1), MODE)) \
+ goto ADDR; \
+ } \
+ else if (REG_P (XEXP (X, 1)) \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ { \
+ if (LEGITIMATE_INDEX_P (XEXP (X, 0), MODE)) \
+ goto ADDR; \
+ } \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output. */
+
+/* On the m88000, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ copy_to_mode_reg (SImode, XEXP (X, 1))); \
+ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ copy_to_mode_reg (SImode, XEXP (X, 0))); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ force_operand (XEXP (X, 0), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ force_operand (XEXP (X, 1), 0)); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; }
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the the m88000 this is never true. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if a raw index is all that is needed for a
+ `tablejump' insn. */
+#define CASE_TAKES_INDEX_RAW
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Do not break .stabs pseudos into continuations. */
+#define DBX_CONTIN_LENGTH 0
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE SImode
+
+/* Define this if addresses of constant functions
+ shouldn't be put through pseudo regs where they can be cse'd.
+ Desirable on machines where ordinary constants are expensive
+ but a CALL with constant address is cheap. */
+#define NO_FUNCTION_CSE
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if ((unsigned) INTVAL (RTX) < 0x10000) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 2; \
+ case CONST_DOUBLE: \
+ return 4;
+
+/* Tell emit-rtl.c how to initialize special values on a per-function bass. */
+extern int optimize;
+extern struct rtx_def *cc0_reg_rtx;
+
+typedef struct { struct rtx_def *ccr; } cc_status_mdep;
+#define CC_STATUS_MDEP cc_status_mdep
+
+#define INIT_EMIT_MDEP \
+{ \
+ cc0_reg_rtx = gen_rtx (REG, SImode, 25); \
+}
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+#define CC_IN_FCCR 04000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (GET_CODE (EXP) == SET) \
+ { if (GET_CODE (SET_DEST (EXP)) == CC0) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (EXP); \
+ cc_status.value2 = SET_SRC (EXP); \
+ } \
+ else if (GET_CODE (SET_DEST (EXP)) == REG) \
+ { if ((cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1))) \
+ cc_status.value1 = 0; \
+ if ((cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2))) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (EXP)) == MEM) \
+ { CC_STATUS_INIT; } \
+ } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \
+ { if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == CC0) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \
+ cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); \
+ } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == REG) \
+ { if ((cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value1))) \
+ cc_status.value1 = 0; \
+ if ((cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value2))) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == MEM) \
+ { CC_STATUS_INIT; } \
+ } \
+ else if (GET_CODE (EXP) == CALL) \
+ { /* all bets are off */ CC_STATUS_INIT; } \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \
+ && cc_status.value2 \
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \
+ printf ("here!\n", cc_status.value2 = 0); \
+}
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE)
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ""
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ""
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\ttext"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\tdata"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", \
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", \
+ "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+ "r30", "r31"}
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs ("\tglobal\t", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "@%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*@%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\tdouble %.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\tfloat %.12e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tword "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `short' and `char' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\thalf "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tbyte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+
+#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
+ output_ascii (FILE, P, SIZE)
+
+#define ASM_OUTPUT_ADDR_VEC_PROLOGUE(FILE, MODE, LEN) \
+ fprintf (FILE, "\tjmp r1\n");
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t@L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ (the m88000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tword @L%d-@L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\talign %d\n", 1<<(LOG))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tzero %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fprintf ((FILE), "\talign %d\n", (SIZE) <= 4 ? 4 : 8), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ":\n\tzero %u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On the m88000, the CODE can be `r', meaning this is a register-only operand
+ and an immediate zero should be represented as `r0'. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "0r%.9g", u1.f); \
+ else \
+ fprintf (FILE, "0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "0r%.20g", u.d); } \
+ else if ((CODE) == 'r' && (X) == const0_rtx) \
+ fprintf (FILE, "r0"); \
+ else { output_addr_const (FILE, X); }}
+
+/* Print a memory address as an operand to reference that memory location. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx base, index = 0; \
+ register rtx addr = ADDR; \
+ register rtx reg0, reg1; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "r0,%s", reg_names[REGNO (addr)]); \
+ break; \
+ case PLUS: \
+ reg0 = XEXP (addr, 0); \
+ reg1 = XEXP (addr, 1); \
+ if (GET_CODE (reg0) == MULT) \
+ { rtx tmp = reg0; reg0 = reg1; reg1 = tmp; } \
+ if (REG_P (reg0)) \
+ if (REG_P (reg1)) \
+ fprintf (FILE, "%s,%s", \
+ reg_names[REGNO (reg0)], \
+ reg_names[REGNO (reg1)]); \
+ else if (GET_CODE (reg1) == CONST_INT) \
+ { \
+ int offset = INTVAL (reg1); \
+ fprintf (FILE, "%s,%d", reg_names[REGNO (reg0)], offset); \
+ } \
+ else if (GET_CODE (reg1) == MULT) \
+ fprintf (FILE, "%s[%s]", \
+ reg_names[REGNO (reg0)], \
+ reg_names[REGNO (XEXP (reg1, 0))]); \
+ else fatal ("bad XEXP (1) to PRINT_OPERAND_ADDRESS"); \
+ else fatal ("unknown PLUS case in PRINT_OPERAND_ADDRESS"); \
+ break; \
+ case MULT: \
+ fprintf (FILE, "r0[%s]", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ default: \
+ fprintf (FILE, "r0,"); \
+ output_addr_const (FILE, addr); \
+ }}
+
diff --git a/gcc-1.40/config/tm-mips-bsd.h b/gcc-1.40/config/tm-mips-bsd.h
new file mode 100644
index 0000000..0659703
--- /dev/null
+++ b/gcc-1.40/config/tm-mips-bsd.h
@@ -0,0 +1,3 @@
+#define MIPS_BSD43
+
+#include "tm-mips.h"
diff --git a/gcc-1.40/config/tm-mips-news.h b/gcc-1.40/config/tm-mips-news.h
new file mode 100644
index 0000000..c42e055
--- /dev/null
+++ b/gcc-1.40/config/tm-mips-news.h
@@ -0,0 +1,19 @@
+/* like pmax except BIG ENDIAN instead of LITTLE ENDIAN */
+
+#define MIPS_NEWS
+#include "tm-mips.h"
+
+#undef CPP_SPEC
+ /* default RISC NEWS environment */
+#define CPP_SPEC "-Dr3000 -DLANGUAGE_C -DMIPSEB -DSYSTYPE_BSD -Dsony_news -Dunix -I/usr/include2.11"
+
+#undef MACHINE_TYPE
+#define MACHINE_TYPE "Sony NEWS (RISC NEWS)"
+
+/* Define this if most significant byte of a word is the lowest numbered.
+*/
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered.
+*/
+#define WORDS_BIG_ENDIAN
diff --git a/gcc-1.40/config/tm-mips-sysv.h b/gcc-1.40/config/tm-mips-sysv.h
new file mode 100644
index 0000000..d3fa7d1
--- /dev/null
+++ b/gcc-1.40/config/tm-mips-sysv.h
@@ -0,0 +1,5 @@
+#define MIPS_SYSV
+
+#include "tm-mips.h"
+
+#define TARGET_MEM_FUNCTIONS
diff --git a/gcc-1.40/config/tm-mips.h b/gcc-1.40/config/tm-mips.h
new file mode 100644
index 0000000..8a044a4
--- /dev/null
+++ b/gcc-1.40/config/tm-mips.h
@@ -0,0 +1,2309 @@
+/* Definitions of target machine for GNU compiler. MIPS version.
+ Contributed by A. Lichnewsky, lich@inria.inria.fr
+ Changes by Michael Meissner, meissner@osf.org
+ Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* ??? This file needs to be reformatted so that it looks like the
+ rest of GCC. ??? */
+
+/*----------------------------------------------------------------------
+
+SWITCHES:
+
+ -O optimization. Implies -mgpOPT
+ -O1 Same as -O, mips compatibility
+ -O2 Implies -O -fomit-frame-pointer -fstrength-reduce
+ -O3 Implies -O2 + -finline-functions
+
+ -mG0 -mG1 -mG2
+ Construct a size to be passed to GCC for Data / Sdata selection.
+
+ Value is ( (i=G0 + 2 G1 + 4 G2) , (i < 6) ? ( 1<<i) :(1 <<(i+3)))
+ Same value should be passed to as + ld using -G. Use -G instead
+ since it is now supported.
+
+ Default = -mG1 -mG0 (Value = 8).
+
+ -G32 Implies -G 32 -mG2 -mnG1 -mG0.
+
+
+ -bestGnum
+ Pass -bestGnum flag to ld. This helps setting best value for
+ the -G parameter.
+
+ -ZSYSV for RISC-OS: use the System V environment
+ -ZBSD43 for RISC-OS: use the BSD 4.3 environment
+----------------------------------------------------------------------*/
+
+
+
+/* Suppression of libg.a when debugging */
+#define NO_LIBG
+
+
+/* Switch Recognition by gcc.c */
+
+#ifdef SWITCH_TAKES_ARG
+#undef SWITCH_TAKES_ARG
+#endif
+
+#define SWITCH_TAKES_ARG(CHAR) \
+ ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+ || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+ || (CHAR) == 'I' || (CHAR) == 'Y' || (CHAR) == 'm' \
+ || (CHAR) == 'L' || (CHAR) == 'i' || (CHAR) == 'A' \
+ || (CHAR) == 'G')
+
+/* Process -mGxx switches */
+
+extern void overide_options ();
+
+#define OVERRIDE_OPTIONS overide_options ()
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#ifndef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DLANGUAGE_C"
+#endif
+
+/* Extra switches sometimes passed to the assembler. */
+
+#ifndef ASM_SPEC
+#ifndef OSF_OS /* normal MIPS system */
+#ifndef DECSTATION /* big endian MIPS (MIPS, SGI) */
+#ifndef SGI_TARGET /* not Silicon Graphics (ie, MIPSco) */
+
+#define ASM_SPEC "%{!mrnames:-nocpp} \
+ %{!mgas: \
+ %{pipe: %e-pipe is not supported.} \
+ %{EB} %{!EB:-EB} \
+ %{EL: %e-EL not supported} \
+ %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \
+ %{g} %{g1} %{g2} %{g3} %{g0}} \
+ %{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32: -G 32}} \
+ %{v} %{K}"
+
+#else /* Silicon Graphics */
+#define ASM_SPEC "%{!mrnames:-nocpp} \
+ %{!mgas: \
+ %{pipe: %e-pipe is not supported.} \
+ %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \
+ %{g} %{g1} %{g2} %{g3} %{g0}} \
+ %{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32: -G 32}} \
+ %{v} %{K}"
+
+#endif /* Silicon Graphics */
+#else /* Ultrix Decstation (little endian) */
+#define ASM_SPEC "%{!mrnames:-nocpp} \
+ %{!mgas: \
+ %{pipe:%e:-pipe not supported} \
+ %{EL} %{!EL:-EL} \
+ %{EB: %e-EB not supported} \
+ %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \
+ %{g} %{g1} %{g2} %{g3} %{g0}} \
+ %{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32: -G 32}} \
+ %{v} %{K}"
+#endif /* DECstation running Ultrix */
+#else /* OSF/1 of some sort */
+#ifndef DECSTATION
+ /* Big endian MIPS running OSF/1 */
+#define ASM_SPEC "%{mmips-as: \
+ %{pipe:%e:-pipe not supported} \
+ %{EB} %{!EB:-EB} \
+ %{EL: %e-EL not supported} \
+ %{!mrnames:-nocpp} \
+ %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \
+ %{g} %{g1} %{g2} %{g3} %{g0} \
+ %{v} %{K}} \
+ %{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{!mmips-as:-G 0} \
+ %{!pic:%{!mpic:%{mmips-as:-G 8}}}} \
+ %{G32: -G 32}}"
+#else
+ /* Little endian OSF/1 Decstation */
+#define ASM_SPEC "%{mmips-as: \
+ %{pipe:%e:-pipe not supported} \
+ %{EL} %{!EL:-EL} \
+ %{EB: %e-EB not supported} \
+ %{!mrnames:-nocpp} \
+ %{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3} \
+ %{g} %{g1} %{g2} %{g3} %{g0} \
+ %{v} %{K}} \
+ %{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{!mmips-as:-G 0} \
+ %{!pic:%{!mpic:%{mmips-as:-G 8}}}} \
+ %{G32: -G 32}}"
+
+#endif /* little endian OSF/1 DECstation */
+#endif /* OSF/1 */
+#endif /* ASM_SPEC */
+
+/* Redefinition of libraries used. Mips doesn't support normal
+ UNIX style profiling via calling _mcount. It does offer
+ profiling that samples the PC, so do what we can... */
+
+#ifndef LIB_SPEC
+#define LIB_SPEC "%{pg:%e-pg is not supported on the MIPS}%{p:-lprof1} -lc"
+#endif
+
+/* Inhibit use of -lg. */
+#define LIBG_SPEC ""
+
+/* Extra switches sometimes passed to the loader. */
+
+
+#ifndef LINK_SPEC
+#ifdef MIPS_SYSV /* RISC-OS SYSTEM V */
+
+#ifndef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt1.o%s crtn.o%s}}"
+#endif
+
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{bestGnum} \
+ %{!ZBSD43:-systype /sysv/}%{ZBSD43:-systype /bsd43/} \
+ %{EB} %{!EB:-EB} %{EL:%e-EL not supported}"
+
+#else /* RISC-OS SYSTEM V */
+#ifdef MIPS_BSD43 /* RISC-OS BSD */
+
+#ifndef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt1.o%s crtn.o%s}}"
+#endif
+
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{bestGnum} \
+ %{!ZSYSV:-systype /bsd43/}%{ZSYSV:-systype /sysv/} \
+ %{EB} %{!EB:-EB} %{EL:%e-EL not supported}"
+
+#else
+
+#ifndef DECSTATION /* Big endian BSD or OSF/1 system */
+#ifndef OSF_OS /* Big endian BSD system */
+#ifndef SGI_TARGET /* Big endian non Silicon Graphics system */
+
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{!mgas: %{EB} %{!EB:-EB} %{EL:%e-EL not supported} \
+ %{bestGnum}}"
+
+#else /* Silicon graphics system */
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{!mgas: %{bestGnum}}"
+
+#endif /* Silicon Graphics system */
+#else /* Big endian OSF/1 system */
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{!mmips-as:-G 0} \
+ %{!pic:%{!mpic:%{mmips-as:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{mmips-as: %{EB} %{!EB:-EB} %{EL:%e-EL not supported} \
+ %{bestGnum}} \
+ %{nostdlib}"
+#endif /* Big endian BSD or OSF/1 system */
+
+#else /* Little endian Ultrix or OSF/1 */
+#ifndef OSF_OS /* Little endian Ultrix system */
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{mgas:-G 0} \
+ %{!pic:%{!mpic:%{!mgas:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{!mgas: %{EL} %{!EL:-EL} %{EB:%e-EB not supported} \
+ %{bestGnum}}"
+
+#else /* Little endian OSF/1 system */
+#define LINK_SPEC "%{G*} \
+ %{!G:%{!G32: %{mpic:-G 0} %{pic:-G 0} \
+ %{!mmips-as:-G 0} \
+ %{!pic:%{!mpic:%{mmips-as:-G 8}}}} \
+ %{G32:-G 32}} \
+ %{!G:%{!G32: \
+ %{mG0:%eYou should include ld/as option -G} \
+ %{mG1:%eYou should include ld/as option -G} \
+ %{mG2:%eYou should include ld/as option -G}}} \
+ %{mmips-as: %{EL} %{!EL:-EL} %{EB:%e-EB not supported} \
+ %{bestGnum}} \
+ %{nostdlib}"
+
+#endif /* Little endian OSF/1 system */
+#endif /* Little endian BSD or OSF/1 system */
+#endif /* RISC-OS BSD */
+#endif /* RISC-OS SYSTEM V */
+#endif /* LINK_SPEC defined */
+
+/* CC1 SPECS */
+
+#define CC1_SPEC "%{O: %{!mngpOPT:-mgpOPT}} \
+ %{O1:-O %{!mngpOPT:-mgpOPT}} \
+ %{O2:-O %{!fnostrength-reduce:-fstrength-reduce} \
+ %{!fnoomit-frame-pointer:-fomit-frame-pointer} \
+ %{!mngpOPT:-mgpOPT}} \
+ %{O3:-O %{!fnostrength-reduce:-fstrength-reduce} \
+ %{!fnoomit-frame-pointer:-fomit-frame-pointer} \
+ %{!fnoinline-functions:-finline-functions} \
+ %{!mngpOPT:-mgpOPT}} \
+ %{O4:%eGCC does not support -O4} \
+ %{!g: %{g1:-g} %{g2:-g} %{g3:-g}} \
+ %{G32: -mG2 -mnG1 }"
+
+/* CPP SPECS */
+
+#ifndef DECSTATION
+
+#ifdef SGI_TARGET /* Silicon Graphics */
+#define CPP_SPEC " %{!ansi:-D__EXTENSIONS__} \
+ -D_MIPSEB -D_SYSTYPE_SYSV -D_LANGUAGE_C \
+ %{O1:-D__OPTIMIZE__} \
+ %{O2:-D__OPTIMIZE__} \
+ %{O3:-D__OPTIMIZE__}"
+
+#else
+#if defined(MIPS_SYSV) || defined(MIPS_BSD43)
+ /* MIPS RISC-OS environments */
+
+#ifdef MIPS_SYSV
+#define CPP_SPEC " %{!ansi:%{!ZBSD43:-DSYSTYPE_SYSV}%{ZBSD43:-DSYSTYPE_BSD43}}\
+ %{!ZBSD43:-D__SYSTYPE_SYSV__}%{ZBSD43:-D__SYSTYPE_BSD43__} \
+ %{O1:-D__OPTIMIZE__} \
+ %{O2:-D__OPTIMIZE__} \
+ %{O3:-D__OPTIMIZE__}"
+#else /* not MIPS_SYSV */
+
+/* Use this instead of a conditional -I in CPP_SPEC
+ because -I adds the dir in the wrongplace in the search path. */
+#define CC_INCLUDE_DIR "/bsd43/usr/include"
+
+#define CPP_SPEC " %{!ansi:%{!ZSYSV:-DSYSTYPE_BSD43}%{ZSYSV:-DSYSTYPE_SYSV}}\
+ %{!ZSYSV:-D__SYSTYPE_BSD43__}%{ZSYSV:-D__SYSTYPE_SYSV__}\
+ %{O1:-D__OPTIMIZE__} \
+ %{O2:-D__OPTIMIZE__} \
+ %{O3:-D__OPTIMIZE__}"
+
+#endif /* not MIPS_SYSV */
+
+#else /* not MIPS_SYSV and not MIPS_BSD43 */
+ /* default MIPS Bsd environment */
+#define CPP_SPEC "%{!ansi:-DSYSTYPE_BSD} -D__SYSTYPE_BSD__ \
+ %{O1:-D__OPTIMIZE__} \
+ %{O2:-D__OPTIMIZE__} \
+ %{O3:-D__OPTIMIZE__}"
+
+#endif /* not MIPS_SYSV and not MIPS_BSD43 */
+#endif /* not Silicon Graphics */
+
+#else /* DECSTATION */
+#define CPP_SPEC "%{O1:-D__OPTIMIZE__} \
+ %{O2:-D__OPTIMIZE__} \
+ %{O3:-D__OPTIMIZE__}"
+
+#endif /* not DECSTATION */
+
+/* Print subsidiary information on the compiler version in use. */
+
+#ifndef __DATE__
+#define __DATE__ "[unknown date]"
+#endif
+
+#define MIPS_VERSION "AL-MIPS 1.1"
+
+#ifdef DECSTATION
+#ifdef OSF_OS
+#define MACHINE_TYPE "OSF/1 Dec Mips"
+#else
+#define MACHINE_TYPE "Ultrix Dec Mips"
+#endif
+
+#else
+#ifdef SGI_TARGET
+#define MACHINE_TYPE "Sgi Mips"
+
+#else
+#if defined(MIPS_SYSV) || defined(MIPS_BSD43)
+ /* MIPS RISC-OS environments */
+#ifdef MIPS_SYSV
+#define MACHINE_TYPE "RISC-OS System V Mips"
+
+#else /* not MIPS_SYSV */
+#define MACHINE_TYPE "RISC-OS BSD Mips"
+
+#endif /* not MIPS_SYSV */
+#else /* not MIPS_SYSV and not MIPS_BSD43 */
+ /* default MIPS Bsd environment */
+#define MACHINE_TYPE "BSD Mips"
+#endif /* not SGI iris */
+#endif /* not MIPS_SYSV and not MIPS_BSD43 */
+#endif /* not DECSTATION */
+
+#define TARGET_VERSION \
+{ \
+ fprintf (stderr, " %s %s %s", MIPS_VERSION, MACHINE_TYPE, __DATE__); \
+}
+
+
+#define SDB_DEBUGGING_INFO /* generate debug info inside of comments */
+#define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */
+
+/* On Sun 4, this limit is 2048. We use 1500 to be safe,
+ since the length can run past this up to a continuation point. */
+#define DBX_CONTIN_LENGTH 1500
+
+
+/* How to renumber registers for dbx and gdb.
+ MIPS needs no change in the numeration. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+
+/* Overides for the COFF debug format. */
+#define PUT_SDB_SCL(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.scl\t%d;", (a)); \
+} while (0)
+
+#define PUT_SDB_INT_VAL(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.val\t%d;", (a)); \
+} while (0)
+
+#define PUT_SDB_VAL(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fputs ("\t.val\t", asm_out_text_file); \
+ output_addr_const (asm_out_text_file, (a)); \
+ fputc (';', asm_out_text_file); \
+} while (0)
+
+#define PUT_SDB_DEF(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t#.def\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_text_file, a); \
+ fputc (';', asm_out_text_file); \
+} while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t#.def\t.%s;", (a)); \
+} while (0)
+
+#define PUT_SDB_ENDEF \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.endef\n"); \
+} while (0)
+
+#define PUT_SDB_TYPE(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.type\t0x%x;", (a)); \
+} while (0)
+
+#define PUT_SDB_SIZE(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.size\t%d;", (a)); \
+} while (0)
+
+#define PUT_SDB_DIM(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.dim\t%d;", (a)); \
+} while (0)
+
+#ifndef PUT_SDB_START_DIM
+#define PUT_SDB_START_DIM \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.dim\t"); \
+} while (0)
+#endif
+
+#ifndef PUT_SDB_NEXT_DIM
+#define PUT_SDB_NEXT_DIM(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "%d,", a); \
+} while (0)
+#endif
+
+#ifndef PUT_SDB_LAST_DIM
+#define PUT_SDB_LAST_DIM(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "%d;", a); \
+} while (0)
+#endif
+
+#define PUT_SDB_TAG(a) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.tag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_text_file, a); \
+ fputc (';', asm_out_text_file); \
+} while (0)
+
+/* For block start and end, we create labels, so that
+ later we can figure out where the correct offset is.
+ The normal .ent/.end serve well enough for functions,
+ so those are just commented out. */
+
+#define PUT_SDB_BLOCK_START(LINE) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, \
+ "$Lb%d:\n\t#.begin\t$Lb%d\t%d\n", \
+ sdb_label_count, \
+ sdb_label_count, \
+ (LINE)); \
+ sdb_label_count++; \
+} while (0)
+
+#define PUT_SDB_BLOCK_END(LINE) \
+do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, \
+ "$Le%d:\n\t#.bend\t$Le%d\t%d\n", \
+ sdb_label_count, \
+ sdb_label_count, \
+ (LINE)); \
+ sdb_label_count++; \
+} while (0)
+
+#define PUT_SDB_FUNCTION_START(LINE)
+
+#define PUT_SDB_FUNCTION_END(LINE)
+
+#define PUT_SDB_EPILOGUE_END(NAME)
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), ".%dfake", (NUMBER));
+
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+ /* Mips vs. GNU assembler */
+#define TARGET_UNIX_ASM (target_flags & 0x00000001)
+#define TARGET_MIPS_AS TARGET_UNIX_ASM
+#define TARGET_GAS (TARGET_UNIX_ASM == 0)
+
+ /* Debug Mode */
+#define TARGET_DEBUG_MODE (target_flags & 0x00000002)
+#define TARGET_DEBUGA_MODE (target_flags & 0x00000004)
+#define TARGET_DEBUGB_MODE (target_flags & 0x00000010)
+#define TARGET_DEBUGC_MODE (target_flags & 0x00000020)
+#define TARGET_DEBUGD_MODE (target_flags & 0x00000040)
+#define TARGET_DEBUGE_MODE (target_flags & 0x00008000)
+
+ /* Reg. Naming in .s ($21 vs. $a0) */
+#define TARGET_NAME_REGS (target_flags & 0x00000008)
+
+ /* addu/subbu vs. add/sub */
+#define TARGET_NOFIXED_OVFL (target_flags & 0x00000080)
+
+ /* Optimize for Sdata/Sbss */
+#define TARGET_GP_OPT (target_flags & 0x00001000)
+#define TARGET_GVALUE_MASK (target_flags & 0x00000f00)
+#define TARGET_GVALUE (TARGET_GVALUE_MASK >> 8)
+
+ /* Position independent code */
+#define TARGET_PIC (target_flags & 0x00002000)
+#define TARGET_PIC_LARGE_OBJECT (target_flags & 0x00004000)
+
+
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+{ {"mips-as", 0x00000001}, /* MIPS assembler */ \
+ {"gas", -0x00000001}, /* GNU assembler */ \
+ {"debug", 0x00000002}, /* Eliminate version in output*/ \
+ {"nodebug", -0x00000002}, \
+ {"debuga", 0x00000004}, /* don't fold SP pushes into frame */ \
+ {"nodebuga", -0x00000004}, \
+ {"debugb", 0x00000010}, /* GO_IF_LEGITIMATE_ADDRESS debug */ \
+ {"nodebugb", -0x00000010}, \
+ {"debugc", 0x00000020}, /* fix frame ptr debug */ \
+ {"nodebugc", -0x00000020}, \
+ {"debugd", 0x00000040}, /* branch/cc0 debug */ \
+ {"nodebugd", -0x00000040}, \
+ {"rnames", 0x00000008}, /* Register names like $a0 */ \
+ {"nornames", -0x00000008}, /* Register names like $21 */ \
+ {"nofixed-ovfl", 0x00000080}, /* Use addu and subu */ \
+ {"fixed-ovfl", -0x00000080}, /* Use add and sub */ \
+ {"G0", 0x00000100}, /* Bit 1 of sdata size */ \
+ {"nG0", -0x00000100}, \
+ {"noG0", -0x00000100}, \
+ {"G1", 0x00000200}, /* Bit 2 of sdata size */ \
+ {"nG1", -0x00000200}, \
+ {"noG1", -0x00000200}, \
+ {"G2", 0x00000400}, /* Bit 3 of sdata size */ \
+ {"nG2", -0x00000400}, \
+ {"noG2", -0x00000400}, \
+ {"gpOPT", 0x00001000}, /* Optimize for global ptr */ \
+ {"ngpOPT", -0x00001000}, \
+ {"nogpOPT", -0x00001000}, \
+ {"pic", 0x00002000}, /* Position independent code */ \
+ {"npic", -0x00002000}, \
+ {"nopic", -0x00002000}, \
+ {"pic-large-object", 0x00004000}, /* Don't opt pic local funcs */ \
+ {"nopic-large-object", -0x00004000}, \
+ {"debuge", 0x00008000}, /* FUNCTION_ARG debug */ \
+ {"nodebuge", -0x00008000}, \
+ {"", TARGET_DEFAULT}}
+
+/* Default target_flags if no switches specified (-mmips-as, -mnofixed-ovfl,
+ -G0, -G1 [same as -G 8]). OSF/1 does not set -mmips-as, and sets -G 0. */
+
+#ifndef OSF_OS
+#define TARGET_DEFAULT 0x00000381
+#else
+#define TARGET_DEFAULT 0x00000080
+#endif
+
+/* Default GVALUE (data item size threshold for selection of Sdata/data)
+ is computed : GVALUE == ( ((i=G0+2*G1+4*G2) < 6)
+ ? 1<<i
+ : 1<< (i+3))
+*/
+
+/* Target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+*/
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+#ifndef DECSTATION
+#define BYTES_BIG_ENDIAN
+#endif
+
+/* Define this if most significant word of a multiword number is numbered. */
+#ifndef DECSTATION
+#define WORDS_BIG_ENDIAN
+#endif
+
+/* Define macros to easily access the most and least significant words
+ without a lot of #ifdef's. */
+
+#ifdef WORDS_BIG_ENDIAN
+#define MOST_SIGNIFICANT_WORD 0
+#define LEAST_SIGNIFICANT_WORD 1
+
+#else
+#define MOST_SIGNIFICANT_WORD 1
+#define LEAST_SIGNIFICANT_WORD 0
+#endif
+
+/* Number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Give parms extra alignment, up to this much, if their types want it. */
+#define MAX_PARM_BOUNDARY 64
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* There is no point aligning anything to a rounder boundary than this. */
+#define BIGGEST_ALIGNMENT 64
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Define this macro if an argument declared as `char' or `short' in a
+ prototype should actually be passed as an `int'. In addition to
+ avoiding errors in certain cases of mismatch, it also makes for
+ better code on certain machines. */
+#define PROMOTE_PROTOTYPES
+
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+#define FIRST_PSEUDO_REGISTER 64
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+
+ On the MIPS, see conventions, page D-2
+
+ I have chosen not to take Multiply/Divide HI,LO or PC into
+ account. */
+
+#define FIXED_REGISTERS {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1,\
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
+}
+
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1,\
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\
+}
+
+
+/* Internal macros to classify a register number as to whether it's a
+ general purpose register or a floating point register. The macro
+ FP_CALL_REG_P also allows registers $4 and $6 as floating point
+ registers to pass floating point as per MIPS spec. */
+
+#define GP_REG_FIRST 0
+#define GP_REG_LAST 31
+#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
+
+#define FP_REG_FIRST 32
+#define FP_REG_LAST 63
+#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1)
+
+#define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
+#define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
+
+#define FP_CALL_REG_P(REGNO) \
+ (FP_REG_P (REGNO) \
+ || (REGNO) == (4 + GP_REG_FIRST) \
+ || (REGNO) == (6 + GP_REG_FIRST))
+
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On the MIPS, all general registers are one word long. I have chosen to
+ use Floating point register pairs. */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((MODE == SFmode) ? 2 : \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the MIPS, all general registers can hold all modes, except
+ FLOATING POINT. */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((GET_MODE_CLASS (MODE) == MODE_INT || MODE == VOIDmode) \
+ ? (GP_REG_P (REGNO)) \
+ : (GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ ? (((REGNO) & 1) == 0 && FP_CALL_REG_P (REGNO)) \
+ : 0) \
+
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ ( ((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode))
+
+/* MIPS pc is apparently not overloaded on a register. */
+/* #define PC_REGNUM 15 */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 29
+
+/* Offset from the stack pointer to the first available location. */
+#define STACK_POINTER_OFFSET 0
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 30
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c.
+
+ At present this is required if we are not a leaf procedure. This
+ is because the .frame directive requires a register that does not
+ change throughout the procedure call, and until stack pushes are
+ folded into the initial stack allocation, we need an unvarying fp. */
+#define FRAME_POINTER_REQUIRED (stack_args_pushed > 0)
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 2
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 4
+
+/* Mips registers used in prologue/epilogue code when the stack frame
+ is larger than 32K bytes. These registers must come from the
+ scratch register set, and not used for passing and returning
+ arguments and any other information used in the calling sequence
+ (such as pic). */
+#define MIPS_TEMP1_REGNUM 8
+#define MIPS_TEMP2_REGNUM 9
+
+/* Define NO_FUNCTION_CSE if it is as good or better to call a constant
+ function address than to call an address kept in a register. */
+#define NO_FUNCTION_CSE
+
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The MIPS has general and floating point registers. */
+
+
+enum reg_class { NO_REGS, GR_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES } ;
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define GENERAL_REGS GR_REGS
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "GR_REGS", "FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {{0x00000000, 0x00000000}, \
+ {0xffffffff, 0x00000000}, \
+ {0x00000000, 0xffffffff}, \
+ {0xffffffff, 0xffffffff}}
+
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) ((FP_REG_P (REGNO)) ? FP_REGS : GR_REGS)
+
+/* Define a table that lets us find quickly all the reg classes
+ containing a given one. This is the initializer for an
+ N_REG_CLASSES x N_REG_CLASSES array of reg class codes.
+ Row N is a sequence containing all the class codes for
+ classes that contain all the regs in class N. Each row
+ contains no duplicates, and is terminated by LIM_REG_CLASSES. */
+
+/* We give just a dummy for the first element, which is for NO_REGS. */
+/* #define REG_CLASS_SUPERCLASSES {{LIM_REG_CLASSES}, \
+ {GR_REGS,ALL_REGS,LIM_REG_CLASSES}, \
+ {FP_REGS,ALL_REGS,LIM_REG_CLASSES}, \
+ {ALL_REGS,LIM_REG_CLASSES} \
+}
+*/
+/* We give just a dummy for the first element, which is for NO_REGS. */
+#define REG_CLASS_SUPERCLASSES {{LIM_REG_CLASSES}, \
+ {ALL_REGS,LIM_REG_CLASSES}, \
+ {ALL_REGS,LIM_REG_CLASSES}, \
+ {LIM_REG_CLASSES} \
+}
+
+/* The inverse relationship:
+ for each class, a list of all reg classes contained in it. */
+#define REG_CLASS_SUBCLASSES \
+{{LIM_REG_CLASSES}, \
+ {GR_REGS,LIM_REG_CLASSES}, \
+ {FP_REGS,LIM_REG_CLASSES},\
+ {GR_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES}\
+}
+
+/* Define a table that lets us find quickly the class
+ for the subunion of any two classes.
+
+ We say "subunion" because the result need not be exactly
+ the union; it may instead be a subclass of the union
+ (though the closer to the union, the better).
+ But if it contains anything beyond union of the two classes,
+ you will lose!
+
+ This is an initializer for an N_REG_CLASSES x N_REG_CLASSES
+ array of reg class codes. The subunion of classes C1 and C2
+ is just element [C1, C2]. */
+
+#define REG_CLASS_SUBUNION \
+{{NO_REGS, GR_REGS, FP_REGS, ALL_REGS}, \
+ {GR_REGS, GR_REGS, ALL_REGS, ALL_REGS}, \
+ {FP_REGS, ALL_REGS, FP_REGS, ALL_REGS}, \
+ {ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS}}
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS GR_REGS
+#define BASE_REG_CLASS GR_REGS
+
+
+ /* REGISTER AND CONSTANT CLASSES
+ */
+
+/* Get reg_class from a letter such as appears in the machine
+description. */
+ /* DEFINED REGISTER CLASSES:
+ **
+ ** 'f' : Floating point registers
+ ** 'y' : General register when used to
+ ** transfer chunks of Floating point
+ ** with mfc1 mtc1 insn
+ */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'f' ? FP_REGS: \
+ (C) == 'y' ? GR_REGS:NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C. */
+
+/* For MIPS, `I' is used for the range of constants an arithmetic insn
+ can actually contain (16 bits signed integers).
+ `J' is used for the range which is just zero (since that is
+ available as $R0).
+ `K' is used for the range of constants a logical insn
+ can actually contain (16 bit zero-extended integers).
+*/
+
+#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x8000) < 0x10000)
+#define SMALL_INT_UNSIGNED(X) ((unsigned) (INTVAL (X)) < 0x10000)
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (unsigned) ((VALUE) + 0x8000) < 0x10000 \
+ : (C) == 'J' ? (VALUE) == 0 \
+ : (C) == 'K' ? (unsigned) (VALUE) < 0x10000 \
+ : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+ /* DEFINED FLOATING CONSTANT CLASSES:
+ **
+ ** 'G' : Floating point 0
+ */
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' && CONST_DOUBLE_LOW ((VALUE)) == 0 \
+ && CONST_DOUBLE_HIGH ((VALUE)) == 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ (((GET_MODE(X) == SFmode) || (GET_MODE(X) == DFmode))? FP_REGS : \
+ ((GET_MODE(X) == VOIDmode) ? GR_REGS :(CLASS)))
+
+/* Same but Mode has been extracted already
+*/
+
+#define PREFERRED_RELOAD_CLASS_FM(X,CLASS) \
+ ((((X) == SFmode) || ((X) == DFmode))? FP_REGS : \
+ (((X) == VOIDmode) ? GR_REGS :(CLASS)))
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((((MODE) == DFmode) || ((MODE) == SFmode)) ? 2 \
+ : ((MODE) == VOIDmode)? ((CLASS) == FP_REGS ? 2 :1) \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET -8
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the vax, sp@- in a byte insn really pushes a word. */
+
+/* #define PUSH_ROUNDING(BYTES) 0 */
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Offset from top-of-stack address to location to store the
+ function parameter if it can't go in a register.
+ Addresses for following parameters are computed relative to this one.
+
+ It also has the effect of counting register arguments in the total
+ argument size. */
+#define FIRST_PARM_CALLER_OFFSET(FNDECL) 0
+
+/* When a parameter is passed in a register, stack space is still
+ allocated for it. For the MIPS, stack space must be allocated, cf
+ Asm Lang Prog Guide page 7-8.
+
+ BEWARE that some space is also allocated for non existing arguments
+ in register. In case an argument list is of form GF used registers
+ are a0 (a2,a3), but we should push over a1... */
+#define REG_PARM_STACK_SPACE
+
+/* Align stack frames on 64 bits (Double Word ). */
+#define STACK_BOUNDARY 64
+
+
+/* Standard GCC stack related variables that we reference. */
+
+extern int optimize;
+extern int may_call_alloca;
+extern int current_function_calls_alloca;
+extern int frame_pointer_needed;
+extern int flag_omit_frame_pointer;
+
+/* MIPS external variables defined in out-mips.c. */
+
+extern char *reg_numchar[]; /* register names as $r2, etc. */
+extern char *current_function_name; /* current function being compiled */
+extern int num_source_filenames; /* current .file # */
+extern int inside_function; /* != 0 if inside of a function */
+extern int stack_args_pushed; /* max bytes pushed for calls */
+extern int stack_args_preallocated; /* # bytes for args preallocated */
+extern int sdb_label_count; /* block start/end next label # */
+extern int mips_section_threshold; /* # bytes of data/sdata cutoff */
+extern int sym_lineno; /* sgi next label # for each stmt */
+
+
+/* Make sure 16 bytes are always allocated on the stack. */
+#ifndef STACK_ARGS_ADJUST
+#define STACK_ARGS_ADJUST(SIZE) \
+{ \
+ if (SIZE.constant < 16) \
+ SIZE.constant = 16; \
+}
+#endif
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 0
+
+
+/* Symbolic macros for the registers used to return integer and floating
+ point values. */
+
+#define GP_RETURN 2
+#define FP_RETURN 32
+
+/* Symbolic macros for the first/last argument registers. */
+
+#define GP_ARG_FIRST 4
+#define GP_ARG_LAST 7
+#define FP_ARG_FIRST 44
+#define FP_ARG_LAST 47
+
+#define MAX_ARGS_IN_REGISTERS 4
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, \
+ (GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ ? FP_RETURN \
+ : GP_RETURN)
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+
+/* 1 if N is a possible register number for a function value.
+ On the MIPS, R2 R3 and F0 F2 are the only register thus used.
+ Currently, R2 and F0 are only implemented here (C has no complex type) */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
+
+/* 1 if N is a possible register number for function argument passing. */
+
+#define FUNCTION_ARG_REGNO_P(N) (((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST) \
+ || ((N) >= FP_ARG_FIRST && (N) <= FP_ARG_LAST \
+ && (0 == (N) % 2)))
+
+/* A C expression which can inhibit the returning of certain function
+ values in registers, based on the type of value. A nonzero value says
+ to return the function value in memory, just as large structures are
+ always returned. Here TYPE will be a C expression of type
+ `tree', representing the data type of the value.
+
+ Note that values of mode `BLKmode' are returned in memory
+ regardless of this macro. Also, the option `-fpcc-struct-return'
+ takes effect regardless of this macro. On most systems, it is
+ possible to leave the macro undefined; this causes a default
+ definition to be used, whose value is the constant 0.
+
+ GCC normally converts 1 byte structures into chars, 2 byte
+ structs into shorts, and 4 byte structs into ints, and returns
+ them this way. Defining the following macro overides this,
+ to give us MIPS cc compatibility. */
+
+#define RETURN_IN_MEMORY(TYPE) \
+ ((TREE_CODE (TYPE) == RECORD_TYPE) || (TREE_CODE (TYPE) == UNION_TYPE))
+
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+*/
+
+typedef struct mips_args {
+ int gp_reg_found;
+ int arg_number;
+ int arg_words;
+} *CUMULATIVE_ARGS;
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+*/
+
+extern void init_cumulative_args ();
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+do { \
+ CUM = (CUMULATIVE_ARGS) alloca (sizeof (*CUM)); \
+ init_cumulative_args (CUM, FNTYPE); \
+} while (0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ (function_arg_advance(CUM, MODE, TYPE, NAMED))
+
+extern void function_arg_advance();
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+extern struct rtx_def *function_arg ();
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ (function_arg(CUM, MODE, TYPE, NAMED))
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero.
+*/
+
+extern int function_arg_partial_nregs ();
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+ (function_arg_partial_nregs (CUM, MODE, TYPE, NAMED))
+
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+extern void function_prologue ();
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue(FILE, SIZE)
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE. */
+
+extern void function_epilogue ();
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
+
+/* Tell prologue and epilogue if Register containing return
+ address should be saved / restored. */
+
+#define MUST_SAVE_REGISTER(regno) \
+ ((regs_ever_live[regno] && !call_used_regs[regno]) || \
+ (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) || \
+ (regno == 31 && regs_ever_live[31]))
+
+/* ALIGN FRAMES on double word boundaries */
+
+#define AL_ADJUST_ALIGN(LOC) (((LOC)+7) & 0xfffffff8)
+
+
+/* If the memory Address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer. This is for
+ when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ ADDR = mips_fix_frame_pointer(ADDR, DEPTH); }
+
+extern struct rtx_def *mips_fix_frame_pointer ();
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+{ \
+ register char **reg_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; \
+ \
+ fprintf (FILE, "\t.set\tnoreorder\n"); \
+ fprintf (FILE, "\t.set\tnoat\n"); \
+ fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
+ reg_ptr[1], reg_ptr[31]); \
+ fprintf (FILE, "\tjal\t_mcount\n"); \
+ fprintf (FILE, "\tsubu\t%s,%s,8\t\t# _mcount pops 2 words from stack\n", \
+ reg_ptr[STACK_POINTER_REGNUM], reg_ptr[STACK_POINTER_REGNUM]); \
+ fprintf (FILE, "\t.set\treorder\n"); \
+ fprintf (FILE, "\t.set\tat\n"); \
+}
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ These definitions are NOT overridden anywhere. */
+
+#define REGNO_OK_FOR_INDEX_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+
+#define REGNO_OK_FOR_BASE_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects them all.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Some source files that are used after register allocation
+ need to be strict. */
+
+#ifndef REG_OK_STRICT
+
+#define REG_OK_FOR_INDEX_P(X) 1 /* ok if index or pseudo reg */
+#define REG_OK_FOR_BASE_P(X) 1 /* ok if base reg. of pseudo reg */
+
+#else
+
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 1
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is actually machine-independent. */
+
+/* 1 if X is an address that we could indirect through. */
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && ((xplus0 = XEXP (X, 0)), \
+ (xplus1 = XEXP (X, 1)), \
+ ((GET_CODE (xplus0) != REG && GET_CODE (xplus1) == REG) \
+ ? ((xplus0 = XEXP (X, 1)), (xplus1 = XEXP (X, 0))) \
+ : 0), \
+ GET_CODE (xplus0) == REG) \
+ && REG_OK_FOR_BASE_P (xplus0) \
+ && ((GET_CODE (xplus1) == CONST_INT && SMALL_INT (xplus1)) \
+ || (GET_CODE (xplus1) == LABEL_REF) \
+ || (GET_CODE (xplus1) == SYMBOL_REF) \
+ || (GET_CODE (xplus1) == CONST) \
+ || (xplus0 == stack_pointer_rtx \
+ && (GET_CODE (xplus1) == CONST || (GET_CODE (xplus1) == SYMBOL_REF))))))
+
+
+#if 1
+extern void trace ();
+#define GO_PRINTF(x) trace(x)
+#define GO_DEBUG_RTX(x) debug_rtx(x)
+
+#else
+#define GO_PRINTF(x)
+#define GO_DEBUG_RTX(x)
+#endif
+
+/* Go to ADDR if X is a valid address not using indexing.
+ (This much is the easy part.) */
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ register rtx xinsn = (X); \
+ register rtx xplus0, xplus1; \
+ \
+ if (TARGET_DEBUGB_MODE) \
+ { \
+ GO_PRINTF ("\n==================== GO_IF_LEGITIMATE_ADDRESS\n"); \
+ GO_DEBUG_RTX (xinsn); \
+ } \
+ \
+ if (GET_CODE (xinsn) == REG) goto ADDR; \
+ if (INDIRECTABLE_ADDRESS_P (xinsn)) goto ADDR; \
+ \
+ if (TARGET_DEBUGB_MODE) \
+ GO_PRINTF ("Not a legitimate address\n"); \
+}
+
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
+
+ At present, GAS doesn't understand li.[sd], so don't allow it
+ to be generated at present. Also, the MIPS assembler does not
+ grok li.d Infinity. */
+
+#define LEGITIMATE_CONSTANT_P(X) (GET_CODE (X) != CONST_DOUBLE)
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the MIPS (so far ..), nothing needs to be done.
+
+ ACHTUNG this is actually used by the FLOW analysis to get rid
+ of statements....
+
+*/
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
+
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE 1
+
+/* Declarations for condition code stuff. */
+extern void compare_collect ();
+extern void compare_restore ();
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+#define SLOW_ZERO_EXTEND
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count.
+
+ Only 5 bits are used in SLLV and SRLV
+*/
+#define SHIFT_COUNT_TRUNCATED
+
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a word address (for indexing purposes)
+ so give the MEM rtx a words's mode. */
+
+#define FUNCTION_MODE SImode
+
+/* Define TARGET_MEM_FUNCTIONS if we want to use calls to memcpy and
+ memset, instead of the BSD functions bcopy and bzero. */
+
+#if defined(MIPS_SYSV) || defined(OSF_OS)
+#define TARGET_MEM_FUNCTIONS
+#endif
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ /* Constant zero is super cheap due to register 0. */ \
+ if (RTX == const0_rtx) return 0; \
+ if ((INTVAL (RTX) < 0x7fff) && (- INTVAL(RTX) < 0x7fff)) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/* Used in by the peephole code. */
+#define additive_op(op,mode) (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
+
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for the vax. */
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for the vax. */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+ CC_STATUS_INIT;
+
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file.
+ If we are optimizing to use the global pointer, create a temporary
+ file to hold all of the text stuff, and write it out to the end.
+ This is needed because the MIPS assembler is evidently one pass,
+ and if it hasn't seen the relevant .comm/.lcomm/.extern/.sdata
+ declaration when the code is processed, it generates a two
+ instruction sequence. */
+
+extern void mips_asm_file_start ();
+
+#define ASM_FILE_START(STREAM) mips_asm_file_start (STREAM)
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON " #APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF " #NO_APP\n"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"$0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", \
+ "t1", "t2", "t3", "t4", "t5", "t6", "t7","s0", \
+ "s1","s2","s3","s4","s5","s6","s7","t8","t9", \
+ "k0","k1","gp","sp","fp","ra", \
+ "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9", \
+"$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19", \
+"$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28","$f29", \
+"$f30","$f31" \
+}
+#define REGISTER_NUMCHAR \
+{ \
+"$0","$1","$2","$3","$4","$5","$6","$7","$8","$9", \
+"$10","$11","$12","$13","$14","$15","$16","$17","$18","$19", \
+"$20","$21","$22","$23","$24","$25","$26","$27","$28","$sp", \
+"$fp","$31", \
+"$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9", \
+"$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19", \
+"$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28","$f29", \
+"$f30","$f31" \
+}
+
+#define REG_NAME(reg) (TARGET_NAME_REGS ? reg_names[reg] : reg_numchar[reg])
+
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+
+/* Print an instruction operand X on file FILE.
+ CODE is the code from the %-spec that requested printing this operand;
+ if `%z3' was used to print operand 3, then CODE is 'z'.
+ CODE is used as follows:
+
+ LIST OF PRINT OPERAND CODES:
+
+ 'x' X is CONST_INT, prints 16 bits in hex format.
+ 'd' output integer constant in decimal,
+ ':' Prints an 'u' if flag -mnofixed-ovfl (for addu vs. add) */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == ':')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ \
+ if ((CODE) == ':') \
+ { \
+ if (TARGET_NOFIXED_OVFL) \
+ fprintf(FILE,"u"); \
+ } \
+ \
+ else if (GET_CODE (X) == REG) \
+ { \
+ int regnum = REGNO (X); \
+ \
+ if (CODE == 'M') \
+ regnum += MOST_SIGNIFICANT_WORD; \
+ else if (CODE == 'L') \
+ regnum += LEAST_SIGNIFICANT_WORD; \
+ else if (CODE == 'D') \
+ regnum++; \
+ \
+ fprintf (FILE, "%s", \
+ ((TARGET_NAME_REGS) ? reg_names : reg_numchar)[regnum]); \
+ } \
+ \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ \
+ else if (GET_CODE (X) == CONST_DOUBLE) \
+ { \
+ union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); \
+ u.i[1] = CONST_DOUBLE_HIGH (X); \
+ if (GET_MODE (X) == SFmode) \
+ { \
+ float f; \
+ f = u.d; \
+ u.d = f; \
+ } \
+ fprintf (FILE, "%.20e", u.d); \
+ } \
+ \
+ else if ((CODE == 'x') && (GET_CODE(X) == CONST_INT)) \
+ fprintf(FILE,"0x%x", 0xffff & (INTVAL(X))); \
+ \
+ else if ((CODE == 'd') && (GET_CODE(X) == CONST_INT)) \
+ fprintf(FILE,"%d", (INTVAL(X))); \
+ \
+ else if ((CODE) == 'd') \
+ fatal ("Code d was found & insn was not CONST_INT"); \
+ \
+ else \
+ output_addr_const (FILE, X); \
+}
+
+
+/* Print a memory operand whose address is X, on file FILE. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ \
+ register rtx addr = ADDR; \
+ register char **reg_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; \
+ \
+ switch (GET_CODE (addr)) \
+ { \
+ default: \
+ abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #1"); \
+ break; \
+ \
+ case REG: \
+ fprintf (FILE, "0(%s)", reg_ptr [REGNO (addr)]); \
+ break; \
+ \
+ case PLUS: \
+ { \
+ register rtx reg = (rtx)0; \
+ register rtx offset = (rtx)0; \
+ register rtx arg0 = XEXP (addr, 0); \
+ register rtx arg1 = XEXP (addr, 1); \
+ \
+ if (GET_CODE (arg0) == REG) \
+ { \
+ reg = arg0; \
+ offset = arg1; \
+ if (GET_CODE (offset) == REG) \
+ abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs"); \
+ } \
+ else if (GET_CODE (arg1) == REG) \
+ { \
+ reg = arg1; \
+ offset = arg0; \
+ } \
+ else if (CONSTANT_P (arg0) && CONSTANT_P (arg1)) \
+ { \
+ output_addr_const (FILE, addr); \
+ break; \
+ } \
+ else \
+ abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs"); \
+ \
+ if (!CONSTANT_P (offset)) \
+ abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #2"); \
+ \
+ output_addr_const (FILE, offset); \
+ fprintf (FILE, "(%s)", reg_ptr [REGNO (reg)]); \
+ } \
+ break; \
+ \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ case CONST_INT: \
+ case CONST: \
+ output_addr_const (FILE, addr); \
+ break; \
+ } \
+}
+
+
+/* How to tell the debugger about changes of source files. Note, the
+ mips ECOFF format cannot deal with changes of files inside of
+ functions, which means the output of parser generators like bison
+ is generally not debuggable without using the -l switch. Lose,
+ lose, lose. Silicon graphics seems to want all .file's hardwired
+ to 1. */
+
+#ifndef SET_FILE_NUMBER
+#define SET_FILE_NUMBER() ++num_source_filenames
+#endif
+
+#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \
+{ \
+ SET_FILE_NUMBER (); \
+ fprintf (STREAM, "\t%s.file\t%d \"%s\"\n", \
+ (TARGET_GAS || !inside_function) ? "" : "#", \
+ num_source_filenames, NAME); \
+}
+
+/* This is how to output a note the debugger telling it the line number
+ to which the following sequence of instructions corresponds.
+ Silicon graphics puts a label after each .loc. */
+
+#ifndef LABEL_AFTER_LOC
+#define LABEL_AFTER_LOC(STREAM)
+#endif
+
+#define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \
+{ \
+ fprintf (STREAM, "\n\t.loc\t%d %d\n", num_source_filenames, LINE); \
+ LABEL_AFTER_LOC (STREAM); \
+}
+
+/* The MIPS implementation uses some labels for it's own purposed. The
+ following lists what labels are created, and are all formed by the
+ pattern $L[a-z].*. The machine independent portion of GCC creates
+ labels matching: $L[A-Z][0-9]+ and $L[0-9]+.
+
+ LM[0-9]+ Sillicon graphics label before each stmt.
+ $Lb[0-9]+ Begin blocks for MIPS debug support
+ $Ldtable Beginning of the PIC data table
+ $Le[0-9]+ End blocks for MIPS debug support
+ $Ls[0-9]+ FP-SP difference if -fomit-frame-pointer */
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME.
+
+ If we are optimizing the gp, remember that this label has been put
+ out, so we know not to emit an .extern for it in mips_asm_file_end.
+ We use one of the common bits in the IDENTIFIER tree node for this,
+ since those bits seem to be unused, and we don't have any method
+ of getting the decl nodes from the name. */
+
+#ifndef COLLECT
+#define ASM_OUTPUT_LABEL(STREAM,NAME) \
+do { \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+ \
+ if (TARGET_GP_OPT && mips_section_threshold != 0) \
+ { \
+ tree name_tree = get_identifier (NAME); \
+ TREE_ADDRESSABLE (name_tree) = 1; \
+ } \
+} while (0)
+
+#else
+#define ASM_OUTPUT_LABEL(STREAM,NAME) \
+do { \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+} while (0)
+#endif
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
+ do { \
+ fputs ("\t.globl\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs ("\n", STREAM); \
+ } while (0)
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
+do { \
+ fputs ("\n\t.comm\t", (STREAM)); \
+ assemble_name ((STREAM), (NAME)); \
+ fprintf ((STREAM), ",%u\n", (ROUNDED)); \
+ \
+ if (TARGET_GP_OPT && mips_section_threshold != 0) \
+ { \
+ tree name_tree = get_identifier (NAME); \
+ TREE_ADDRESSABLE (name_tree) = 1; \
+ } \
+} while (0)
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
+do { \
+ fputs ("\n\t.lcomm\t", (STREAM)); \
+ assemble_name ((STREAM), (NAME)); \
+ fprintf ((STREAM), ",%u\n", (ROUNDED)); \
+ \
+ if (TARGET_GP_OPT && mips_section_threshold != 0) \
+ { \
+ tree name_tree = get_identifier (NAME); \
+ TREE_ADDRESSABLE (name_tree) = 1; \
+ } \
+} while (0)
+
+
+/* This says how to output an external. It would be possible not to
+ output anything and let undefined symbol become external. However
+ the assembler uses length information on externals to allocate in
+ data/sdata bss/sbss, thereby saving exec time. */
+
+#define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \
+ mips_output_external(STREAM,DECL,NAME)
+
+/* This says what to print at the end of the assembly file */
+#define ASM_FILE_END(STREAM) mips_asm_file_end(STREAM)
+
+
+/* This is how to declare a function name. The actual work of
+ emitting the label is moved to function_prologue, so that we can
+ get the line number correctly emitted before the .ent directive,
+ and after any .file directives.
+
+ Also, switch files if we are optimizing the global pointer. */
+
+#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
+{ \
+ extern FILE *asm_out_text_file; \
+ if (TARGET_GP_OPT) \
+ STREAM = asm_out_text_file; \
+ \
+ current_function_name = NAME; \
+}
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
+ fprintf (STREAM, "%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
+ fprintf (STREAM, "$%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*$%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(STREAM,VALUE) \
+{ \
+ union { double d; long l[2]; } u2; \
+ u2.d = VALUE; \
+ fprintf (STREAM, "\t.word\t0x%08lx\t\t# %.20g\n\t.word\t0x%08lx\n", \
+ u2.l[0], u2.d, u2.l[1]); \
+}
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(STREAM,VALUE) \
+{ \
+ union { float f; long l; } u2; \
+ u2.f = VALUE; \
+ fprintf (STREAM, "\t.word\t0x%08lx\t\t# %.12g\n", u2.l, u2.f); \
+}
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(STREAM,VALUE) \
+{ \
+ fprintf (STREAM, "\t.word\t"); \
+ output_addr_const (STREAM, (VALUE)); \
+ fprintf (STREAM, "\n"); \
+}
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
+{ \
+ fprintf (STREAM, "\t.half\t"); \
+ output_addr_const (STREAM, (VALUE)); \
+ fprintf (STREAM, "\n"); \
+}
+
+#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
+{ \
+ fprintf (STREAM, "\t.byte\t"); \
+ output_addr_const (STREAM, (VALUE)); \
+ fprintf (STREAM, "\n"); \
+}
+
+/* This is how to output an assembler line defining an `int' constant,
+ which is not in tree format (for collect.c). */
+
+#define ASM_OUTPUT_INT_CONST(STREAM,VALUE) \
+ fprintf(STREAM, "\t.word\t%d\n", VALUE)
+
+/* This is how to output an assembler line defining an external/static
+ address which is not in tree format (for collect.c). */
+
+#define ASM_OUTPUT_PTR_INT_SUM(STREAM, NAME, VALUE) \
+do { \
+ fprintf (STREAM, "\t.word\t"); \
+ ASM_OUTPUT_LABELREF (STREAM, NAME); \
+ fprintf (STREAM, "+%d\n", VALUE); \
+} while (0)
+
+#define ASM_OUTPUT_LABELREF_AS_INT(STREAM, NAME) \
+do { \
+ fprintf (STREAM, "\t.word\t"); \
+ ASM_OUTPUT_LABELREF (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+} while (0)
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
+{ \
+ fprintf (STREAM, "\t.byte\t0x%x\n", (VALUE)); \
+}
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+{ \
+ fprintf (STREAM, "\t.word\t$L%d\n", VALUE); \
+}
+
+/* This is how to output an element of a case-vector that is relative.
+ (We do not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, VALUE, REL) \
+{ \
+ fprintf (STREAM, "\t.word\t$L%d-$L%d\n", VALUE, REL); \
+}
+
+/* This is how to emit the initial label for switch statements. We
+ need to put the switch labels somewhere else from the text section,
+ because the MIPS assembler gets real confused about line numbers if
+ .word's appear in the text section. */
+
+#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, JUMPTABLE) \
+{ \
+ rdata_section (); \
+ ASM_OUTPUT_ALIGN (STREAM, 2); \
+ ASM_OUTPUT_INTERNAL_LABEL (STREAM, PREFIX, NUM); \
+}
+
+/* Output at the end of a switch's jump table. */
+
+#define ASM_OUTPUT_CASE_END(STREAM, NUM, INSN) \
+{ \
+ text_section (); \
+}
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
+{ \
+ int mask = (1 << (LOG)) - 1; \
+ fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
+}
+
+/* This is how to output an assembler line to to advance the location
+ counter by SIZE bytes. */
+#define ASM_OUTPUT_SKIP(STREAM,SIZE) \
+{ \
+ fprintf (STREAM, "\t.space\t%u\n", (SIZE)); \
+}
+
+/* This is how to output a string. */
+#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
+do { \
+ register int i, c, len = LEN, cur_pos = 17; \
+ register unsigned char *string = (unsigned char *)STRING; \
+ fprintf (STREAM, "\t.ascii\t\""); \
+ for (i = 0; i < len; i++) \
+ { \
+ register int c = string[i]; \
+ \
+ switch (c) \
+ { \
+ case '\"': \
+ case '\\': \
+ putc ('\\', STREAM); \
+ putc (c, STREAM); \
+ cur_pos += 2; \
+ break; \
+ \
+ case TARGET_NEWLINE: \
+ fputs ("\\n", STREAM); \
+ if (i+1 < len \
+ && (((c = string[i+1]) >= '\040' && c <= '~') \
+ || c == TARGET_TAB)) \
+ cur_pos = 32767; /* break right here */ \
+ else \
+ cur_pos += 2; \
+ break; \
+ \
+ case TARGET_TAB: \
+ fputs ("\\t", STREAM); \
+ cur_pos += 2; \
+ break; \
+ \
+ case TARGET_FF: \
+ fputs ("\\f", STREAM); \
+ cur_pos += 2; \
+ break; \
+ \
+ case TARGET_BS: \
+ fputs ("\\b", STREAM); \
+ cur_pos += 2; \
+ break; \
+ \
+ case TARGET_CR: \
+ fputs ("\\r", STREAM); \
+ cur_pos += 2; \
+ break; \
+ \
+ default: \
+ if (c >= ' ' && c < 0177) \
+ { \
+ putc (c, STREAM); \
+ cur_pos++; \
+ } \
+ else \
+ { \
+ fprintf (STREAM, "\\%03o", c); \
+ cur_pos += 4; \
+ } \
+ } \
+ \
+ if (cur_pos > 72 && i+1 < len) \
+ { \
+ cur_pos = 17; \
+ fprintf (STREAM, "\"\n\t.ascii\t\""); \
+ } \
+ } \
+ fprintf (STREAM, "\"\n"); \
+} while (0)
+
+/* Handle certain cpp directives used in header files on sysV. */
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a in the read-only data section. */
+#define ASM_OUTPUT_IDENT(FILE, STRING) \
+{ \
+ char *p = STRING; \
+ int size = strlen (p) + 1; \
+ rdata_section (); \
+ assemble_string (p, size); \
+}
+
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* Output before writable short data. */
+
+#define SDATA_SECTION_ASM_OP "\t.sdata"
+
+/* Output before read-only data. */
+
+#define RDATA_SECTION_ASM_OP "\t.rdata"
+
+/* What other sections we support other than the normal .data/.text. */
+
+#define EXTRA_SECTIONS in_sdata, in_rdata, in_last_p1
+
+/* Define the additional functions to select our additional sections. */
+
+/* on the MIPS it is not a good idea to put constants in the text
+ section, since this defeats the sdata/data mechanism. This is
+ especially true when -O is used. In this case an effort is made to
+ address with faster (gp) register relative addressing, which can
+ only get at sdata and sbss items (there is no stext !!) However,
+ if the constant is too large for sdata, and it's readonly, it
+ will go into the .rdata section. */
+
+#define EXTRA_SECTION_FUNCTIONS \
+void \
+sdata_section () \
+{ \
+ if (in_section != in_sdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
+ in_section = in_sdata; \
+ } \
+} \
+ \
+void \
+rdata_section () \
+{ \
+ if (in_section != in_rdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
+ in_section = in_rdata; \
+ } \
+}
+
+/* Given a decl node or constant node, choose the section to output it in
+ and select that section. */
+
+#define SELECT_SECTION_MODE(MODE,RTX) \
+{ \
+ extern int mips_section_threshold; \
+ if ((GET_MODE_SIZE(MODE) / BITS_PER_UNIT) <= mips_section_threshold \
+ && mips_section_threshold > 0) \
+ sdata_section (); \
+ else \
+ rdata_section (); \
+} \
+
+#define SELECT_SECTION(DECL) \
+{ \
+ extern int mips_section_threshold; \
+ if (int_size_in_bytes (TREE_TYPE (DECL)) <= mips_section_threshold \
+ && mips_section_threshold > 0) \
+ sdata_section (); \
+ else if (TREE_CODE (DECL) == STRING_CST) \
+ { \
+ if (flag_writable_strings) \
+ data_section (); \
+ else \
+ rdata_section (); \
+ } \
+ else if (TREE_CODE (DECL) != VAR_DECL) \
+ rdata_section (); \
+ else if (!TREE_READONLY (DECL) || TREE_VOLATILE (DECL)) \
+ data_section (); \
+ else \
+ rdata_section (); \
+}
+
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
+do { \
+ extern char *reg_numchar[]; \
+ char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; \
+ fprintf (STREAM, "\tsubu\t%s,%s,4\n\tsw\t%s,0(%s)\n", \
+ reg_name_ptr[STACK_POINTER_REGNUM], \
+ reg_name_ptr[STACK_POINTER_REGNUM], \
+ reg_name_ptr[REGNO], \
+ reg_name_ptr[STACK_POINTER_REGNUM]); \
+} while (0)
+
+#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
+do { \
+ extern char *reg_numchar[]; \
+ char **reg_name_ptr = (TARGET_NAME_REGS) ? reg_names : reg_numchar; \
+ fprintf (STREAM, "\tlw\t%s,0(%s)\n\taddu\t%s,%s,4\n", \
+ reg_name_ptr[REGNO], \
+ reg_name_ptr[STACK_POINTER_REGNUM], \
+ reg_name_ptr[STACK_POINTER_REGNUM], \
+ reg_name_ptr[STACK_POINTER_REGNUM]); \
+} while (0)
+
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+
+/* Tell G++'s collect that MIPS' based ports do not have leading
+ underscores. */
+
+#ifndef NO_UNDERSCORES
+#define NO_UNDERSCORES
+#endif NO_UNDERSCORES
+
+/* Tell G++ that we need to run collect. */
+
+#ifndef USE_COLLECT
+#define USE_COLLECT
+#endif
+
+#ifndef EXTENDED_COFF
+#define EXTENDED_COFF
+#endif
+
+/* The following are for collect.c which has it's own idea of
+ which macros should be used. */
+
+#define ASM_INT_OP ".word "
+#define ASM_SHORT_OP ".half "
+#define ASM_CHAR_OP ".byte "
diff --git a/gcc-1.40/config/tm-news.h b/gcc-1.40/config/tm-news.h
new file mode 100644
index 0000000..6ed2771
--- /dev/null
+++ b/gcc-1.40/config/tm-news.h
@@ -0,0 +1,408 @@
+/* Definitions of target machine for GNU compiler. SONY NEWS-OS 3.0 version.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef USE_GAS
+/* This controls conditionals in tm-m68k.h. */
+#define MOTOROLA
+#define SONY_ASM
+#endif
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#define TARGET_DEFAULT 7
+
+/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
+ This will control the use of inline 68881 insns in certain macros. */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+/* These are the ones defined by Sony, plus mc68000 for uniformity with
+ GCC on other 68000 systems. */
+
+#ifdef news700
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews700"
+#endif
+#ifdef news800
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews800"
+#endif
+#ifdef news900
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dnews900"
+#endif
+#ifdef news1500
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1500"
+#endif
+#ifdef news1700
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1700"
+#endif
+#ifdef news1800
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1800"
+#endif
+#ifdef news1900
+#define CPP_PREDEFINES "-Dunix -Dbsd43 -Dsony -Dsony_news -Dmc68000 -Dmc68020 -Dmc68030 -Dnews1900"
+#endif
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Override parts of tm-m68k.h to fit Sony's assembler syntax. */
+
+#undef POINTER_BOUNDARY
+#undef BIGGEST_ALIGNMENT
+#undef CALL_USED_REGISTERS
+#undef FUNCTION_VALUE
+#undef LIBCALL_VALUE
+#undef FUNCTION_PROFILER
+
+#ifdef MOTOROLA
+#undef FUNCTION_PROLOGUE
+#undef FUNCTION_EPILOGUE
+#undef REGISTER_NAMES
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+#undef ASM_OUTPUT_DOUBLE
+#undef ASM_OUTPUT_SKIP
+#undef ASM_FORMAT_PRIVATE_NAME
+#undef PRINT_OPERAND
+#undef PRINT_OPERAND_ADDRESS
+#endif
+
+#undef ASM_OUTPUT_ALIGN
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* There is no point aligning anything to a rounder boundary than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* NEWS makes d2, d3, fp2 and fp3 unsaved registers, unlike the Sun system. */
+
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 0, 0, 0, 0, \
+ 1, 1, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0}
+
+/* NEWS returns floats and doubles in fp0, not d0/d1. */
+
+#define FUNCTION_VALUE(VALTYPE,FUNC) LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), ((TARGET_68881 && ((MODE) == SFmode || (MODE) == DFmode)) ? 16 : 0))
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+#ifdef MOTOROLA
+
+/* Don't try to define `gcc_compiled.' since the assembler does not
+ accept symbols with periods. This is no real loss since GDB only
+ really needs it for parms passed in registers. */
+#define ASM_IDENTIFY_GCC(FILE)
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ if (frame_pointer_needed) \
+ { if (fsize < 0x8000) \
+ fprintf (FILE, "\tlink fp,#%d\n", -fsize); \
+ else if (TARGET_68020) \
+ fprintf (FILE, "\tlink.l fp,#%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink fp,#0\n\tsub.l #%d,sp\n", fsize); } \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if (mask != 0) \
+ fprintf (FILE, "\tfmovem.x #0x%x,-(sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovem.l #0x%x,-(sp)\n", mask); }
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmove.l #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset; \
+ extern char call_used_regs[]; \
+ extern int current_function_pops_args; \
+ extern int current_function_args_size; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ nregs = 0; fmask = 0; \
+ for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask)) \
+ { fprintf (FILE, "\tmove.l #%d,a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmove.l (-%d,fp,a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmove.l (-%d,fp),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovem.l (-%d,fp,a0.l),#0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovem.l (sp)+,#0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovem.l (-%d,fp),#0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovem.x (-%d,fp,a0.l),#0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovem.x (sp)+,#0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovem.x (-%d,fp),#0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk fp\n"); \
+ if (current_function_pops_args && current_function_args_size) \
+ fprintf (FILE, "\trtd #%d\n", current_function_args_size); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* Difference from tm-m68k.h is in `fp' instead of `a6'. */
+
+#define REGISTER_NAMES \
+{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7"}
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l %s,-(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmove.l (sp)+,%s\n", reg_names[REGNO])
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 13), \
+ sprintf ((OUTPUT), "%s$$$%d", (NAME), (LABELNO)))
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "#"); \
+ else if (CODE == '-') fprintf (FILE, "-(sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(sp)"); \
+ else if (CODE == '!') fprintf (FILE, "ccr"); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "#0f%.9e", u1.f); \
+ else \
+ fprintf (FILE, "#0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "#0d%.20e", u.d); } \
+ else if (CODE == 'b') output_addr_const (FILE, X); \
+ else { putc ('#', FILE); output_addr_const (FILE, X); }}
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "(L%d.b,pc,%s.w", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (breg)]); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr && GET_CODE (addr) == LABEL_REF) abort (); \
+ fprintf (FILE, "("); \
+ if (addr != 0) { \
+ output_addr_const (FILE, addr); \
+ putc (',', FILE); } \
+ fprintf (FILE, "%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "(L%d.b,pc,%s.l)", \
+ CODE_LABEL_NUMBER (XEXP (addr, 0)), \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ if (GET_CODE (addr) == CONST_INT \
+ && INTVAL (addr) < 0x8000 \
+ && INTVAL (addr) >= -0x8000) \
+ fprintf (FILE, "%d.w", INTVAL (addr)); \
+ else \
+ output_addr_const (FILE, addr); \
+ }}
+
+#else /* Using GAS, which uses the MIT assembler syntax, like a Sun. */
+
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmovl #LP%d,d0\n\tjsr mcount\n", (LABEL_NO));
+
+#endif /* MOTOROLA */
diff --git a/gcc-1.40/config/tm-newsgas.h b/gcc-1.40/config/tm-newsgas.h
new file mode 100644
index 0000000..ac36e6b
--- /dev/null
+++ b/gcc-1.40/config/tm-newsgas.h
@@ -0,0 +1,7 @@
+/* In Sony versions before 3.0, use the GNU Assembler, because the
+ system's assembler has no way to assemble the difference of two
+ labels for the displacement in a switch-dispatch instruction. */
+
+#define USE_GAS
+
+#include "tm-news.h"
diff --git a/gcc-1.40/config/tm-next.h b/gcc-1.40/config/tm-next.h
new file mode 100644
index 0000000..4292b27
--- /dev/null
+++ b/gcc-1.40/config/tm-next.h
@@ -0,0 +1,98 @@
+/* tm-next.h: Definitions for Next as target machine for GNU C compiler. */
+
+#include "tm-m68k.h"
+
+/* Enable recent gcc to compile under the old gcc in Next release 1.0. */
+#define __inline inline
+
+/* See tm-m68k.h. 7 means 68020/030 with 68881/882. */
+
+#define TARGET_DEFAULT 7
+
+/* These compiler options take an argument. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (!strcmp (STR, "Ttext") || !strcmp (STR, "Tdata"))
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -DNeXT -Dunix -D__MACH__"
+
+/* Machine dependent ccp options. */
+
+#define CPP_SPEC "%{bsd:-D__STRICT_BSD__}"
+
+/* Machine dependent ld options. */
+
+#define LINK_SPEC "%{Z} %{M} %{Mach} %{segcreate*} %{seglinkedit}"
+
+/* Machine dependent libraries. */
+
+#define LIB_SPEC "%{!p:%{!pg:-lsys_s}} %{pg:-lsys_p}"
+
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
+#define STARTFILE_SPEC \
+ "%{pg:-lgcrt0.o}%{!pg: \
+ %{p:%e-p profiling is no longer supported. Use -pg instead.} \
+ %{!p:-lcrt0.o}}"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* We want C++ style comments to be supported for Objective-C */
+
+#define CPLUSPLUS
+
+/* Why not? */
+
+#define DOLLARS_IN_IDENTIFIERS 1
+
+#if 0 /* These pertain to code changes that are not present in 1.36. */
+
+/* Allow Mach -MD and -MMD make depend switches. */
+
+#define MACH_MAKE_DEPEND
+
+/* These options take an argument. Note that we don't support -Ttext or -Tdata. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) (!strcmp (STR, "MD") || !strcmp (STR,
+"MMD"))
+
+#endif /* 0 */
+
+/* Allow #sscs (but don't do anything). */
+
+#define SCCS_DIRECTIVE
+
+/* We use Dbx symbol format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.double 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "\t.double 0r%.20e\n", (VALUE)))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.single 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "\t.single 0r%.20e\n", (VALUE)))
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "#0r%.9g", (VALUE)))
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "#0r%.20g", (VALUE)))
diff --git a/gcc-1.40/config/tm-ns32k.h b/gcc-1.40/config/tm-ns32k.h
new file mode 100644
index 0000000..16cb7b4
--- /dev/null
+++ b/gcc-1.40/config/tm-ns32k.h
@@ -0,0 +1,1457 @@
+/* Definitions of target machine for GNU compiler. NS32000 version.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dns32000 -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+#define TARGET_VERSION fprintf (stderr, " (32000, National syntax)");
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Compile 32081 insns for floating point (not library calls). */
+#define TARGET_32081 (target_flags & 1)
+/* Compile using rtd insn calling sequence.
+ This will not work unless you use prototypes at least
+ for all functions that can take varying numbers of args. */
+#define TARGET_RTD (target_flags & 2)
+/* Compile passing first two args in regs 0 and 1. */
+#define TARGET_REGPARM (target_flags & 4)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { { "32081", 1}, \
+ { "soft-float", -1}, \
+ { "rtd", 2}, \
+ { "nortd", -2}, \
+ { "regparm", 4}, \
+ { "noregparm", -4}, \
+ { "", TARGET_DEFAULT}}
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is not true on the ns32k. */
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on the ns32k. */
+/* #define BYTES_BIG_ENDIAN */
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* This is not true on the ns32k. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* Number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 32000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 16
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. National claims that the NS32032
+ works without strict alignment, but rumor has it that operands
+ crossing a page boundary cause unpredictable results. */
+#define STRICT_ALIGNMENT
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+#define FIRST_PSEUDO_REGISTER 18
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the ns32k, these are the FP, SP, (SB and PC are not included here). */
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS {1, 1, 1, 0, 0, 0, 0, 0, \
+ 1, 1, 1, 1, 0, 0, 0, 0, \
+ 1, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+ On the ns32k, all registers are 32 bits long. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the 32000, all registers can hold all modes, except that
+ double precision floats (and double ints) must fall on even-register
+ boundaries */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((MODE) == DFmode \
+ ? (((REGNO) & 1) == 0 \
+ && (TARGET_32081 ? (REGNO) < 16 : (REGNO) < 8)) \
+ : (MODE) == DImode ? ((REGNO) & 1) == 0 && (REGNO) < 8 \
+ : 1)
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == DFmode || (MODE1) == DImode) == ((MODE2) == DFmode || (MODE2) == DImode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* NS32000 pc is not overloaded on a register. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 17
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 16
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 16
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 1
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 2
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, GEN_AND_FLOAT_REGS,
+ GEN_AND_MEM_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "GENERAL_REGS", "FLOAT_REGS", "GEN_AND_FLOAT_REGS", "GEN_AND_MEM_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {0, 0x00ff, 0xff00, 0xffff, 0x300ff, 0x3ffff, }
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) < 8 ? GENERAL_REGS : (REGNO) < 16 ? FLOAT_REGS : ALL_REGS)
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS GEN_AND_MEM_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'r' ? GENERAL_REGS \
+ : (C) == 'f' ? FLOAT_REGS \
+ : (C) == 'x' ? GEN_AND_MEM_REGS \
+ : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ On the ns32k, these letters are used as follows:
+
+ I : Matches integers which are valid shift amounts for scaled indexing.
+ These are 0, 1, 2, 3 for byte, word, double, and quadword.
+ J : Matches integers which fit a "quick" operand.
+ K : Matches integers 0 to 7 (for inss and exts instructions). */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((VALUE) < 8 && (VALUE) + 8 >= 0 ? \
+ ((C) == 'I' ? (0 <= (VALUE) && (VALUE) <= 3) : \
+ (C) == 'J' ? (VALUE) <= 7 : \
+ (C) == 'K' ? 0 <= (VALUE) : 0) : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the 32000, this is the size of MODE in words */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the 32000, sp@- in a byte insn really pushes a BYTE. */
+#define PUSH_ROUNDING(BYTES) (BYTES)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 8
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ On the 32000, the RET insn may be used to pop them if the number
+ of args is fixed, but if the number is variable then the caller
+ must pop them all. RET can't be used for library calls now
+ because the library is compiled with the Unix compiler.
+ Use of RET is a selectable option, since it is incompatible with
+ standard Unix calling sequences. If the option is not selected,
+ the caller must always pop the args. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) \
+ (TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \
+ || TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) == void_type_node))
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the 32000 the return value is in R0,
+ or perhaps in F0 is there is fp support. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ (TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_32081 \
+ ? gen_rtx (REG, TYPE_MODE (VALTYPE), 8) \
+ : gen_rtx (REG, TYPE_MODE (VALTYPE), 0))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On the 32000 the return value is in R0,
+ or perhaps F0 is there is fp support. */
+
+#define LIBCALL_VALUE(MODE) \
+ (((MODE) == DFmode || (MODE) == SFmode) && TARGET_32081 \
+ ? gen_rtx (REG, MODE, 8) \
+ : gen_rtx (REG, MODE, 0))
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for a function value.
+ On the 32000, R0 and F0 are the only registers thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) (((N) & ~8) == 0)
+
+/* 1 if N is a possible register number for function argument passing.
+ On the 32000, no registers are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the ns32k, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the ns32k, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the 32000 all args are pushed, except if -mregparm is specified
+ then the first two words of arguments are passed in r0, r1.
+ *NOTE* -mregparm does not work.
+ It exists only to test register calling conventions. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8) ? gen_rtx (REG, (MODE), (CUM) / 4) : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+((TARGET_REGPARM && (CUM) < 8 \
+ && 8 < ((CUM) + ((MODE) == BLKmode \
+ ? int_size_in_bytes (TYPE) \
+ : GET_MODE_SIZE (MODE)))) \
+ ? 2 - (CUM) / 4 : 0)
+
+#ifndef MAIN_FUNCTION_PROLOGUE
+#define MAIN_FUNCTION_PROLOGUE
+#endif
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ int used_regs_buf[8], *bufp = used_regs_buf; \
+ int used_fregs_buf[8], *fbufp = used_fregs_buf; \
+ extern char call_used_regs[]; \
+ MAIN_FUNCTION_PROLOGUE; \
+ for (regno = 0; regno < 8; regno++) \
+ if (regs_ever_live[regno] && !call_used_regs[regno]) { \
+ *bufp++ = regno; \
+ } \
+ *bufp = -1; \
+ for (; regno < 16; regno++) \
+ if (regs_ever_live[regno] && !call_used_regs[regno]) { \
+ *fbufp++ = regno; \
+ } \
+ *fbufp = -1; \
+ bufp = used_regs_buf; \
+ if (frame_pointer_needed) \
+ { \
+ fprintf (FILE, "\tenter ["); \
+ while (*bufp >= 0) \
+ { \
+ fprintf (FILE, "r%d", *bufp++); \
+ if (*bufp >= 0) \
+ fputc (',', FILE); \
+ } \
+ fprintf (FILE, "],%d\n", SIZE); \
+ } \
+ else while (*bufp >= 0) \
+ fprintf (FILE, "\tmovd r%d,tos\n", *bufp++); \
+ fbufp = used_fregs_buf; \
+ while (*fbufp >= 0) \
+ { \
+ if ((*fbufp & 1) || (fbufp[0] != fbufp[1] - 1)) \
+ fprintf (FILE, "\tmovf f%d,tos\n", *fbufp++ - 8); \
+ else \
+ { \
+ fprintf (FILE, "\tmovl f%d,tos\n", fbufp[0] - 8); \
+ fbufp += 2; \
+ } \
+ } \
+}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry.
+
+ THIS DEFINITION FOR THE 32000 IS A GUESS. IT HAS NOT BEEN TESTED. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\taddr LP%d,r0\n\tbsr mcount\n", (LABELNO))
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+/* #define EXIT_IGNORE_STACK */
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ extern int current_function_pops_args; \
+ extern int current_function_args_size; \
+ register int regno; \
+ int used_regs_buf[8], *bufp = used_regs_buf; \
+ int used_fregs_buf[8], *fbufp = used_fregs_buf; \
+ extern char call_used_regs[]; \
+ *fbufp++ = -2; \
+ for (regno = 8; regno < 16; regno++) \
+ if (regs_ever_live[regno] && !call_used_regs[regno]) { \
+ *fbufp++ = regno; \
+ } \
+ fbufp--; \
+ while (fbufp > used_fregs_buf) \
+ { \
+ if ((*fbufp & 1) && fbufp[0] == fbufp[-1] + 1) \
+ { \
+ fprintf (FILE, "\tmovl tos,f%d\n", fbufp[-1] - 8); \
+ fbufp -= 2; \
+ } \
+ else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \
+ } \
+ for (regno = 0; regno < 8; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ *bufp++ = regno; \
+ if (frame_pointer_needed) \
+ { \
+ fprintf (FILE, "\texit ["); \
+ while (bufp > used_regs_buf) \
+ { \
+ fprintf (FILE, "r%d", *--bufp); \
+ if (bufp > used_regs_buf) \
+ fputc (',', FILE); \
+ } \
+ fprintf (FILE, "]\n"); \
+ } \
+ else \
+ { \
+ while (bufp > used_regs_buf) \
+ fprintf (FILE, "\tmovd tos,r%d\n", *--bufp); \
+ } \
+ if (current_function_pops_args && current_function_args_size) \
+ fprintf (FILE, "\tret %d\n", current_function_args_size); \
+ else fprintf (FILE, "\tret 0\n"); }
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#if 0
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ if (GET_CODE (ADDR) == REG && REGNO (ADDR) == FRAME_POINTER_REGNUM) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && GET_CODE (XEXP (ADDR, 0)) == REG \
+ && REGNO (XEXP (ADDR, 0)) == FRAME_POINTER_REGNUM \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = 0; regno < 8; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (gen_rtx (REG, Pmode, STACK_POINTER_REGNUM), \
+ offset + (DEPTH)); } }
+#else
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+ if (check_reg(ADDR, FRAME_POINTER_REGNUM)) { \
+ register int regno, offset = (DEPTH) - 4; \
+ extern char call_used_regs[]; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ if (GET_CODE (ADDR) == REG && REGNO (ADDR) == FRAME_POINTER_REGNUM) \
+ ADDR = plus_constant(stack_pointer_rtx, offset); \
+ else if (GET_CODE(ADDR) == PLUS) { \
+ register rtx a0 = XEXP(ADDR, 0); \
+ if (GET_CODE(a0) == REG && REGNO(a0) == FRAME_POINTER_REGNUM) \
+ if (GET_CODE(XEXP(ADDR, 1)) == CONST_INT) \
+ ADDR = plus_constant(stack_pointer_rtx, \
+ offset + INTVAL(XEXP(ADDR, 1))); \
+ else \
+ ADDR = plus_constant(gen_rtx(PLUS, Pmode, \
+ stack_pointer_rtx, XEXP (ADDR, 1)), \
+ offset); \
+ else if (GET_CODE(a0) == MEM) { \
+ register rtx a1 = XEXP(a0, 0); \
+ if (GET_CODE(a1) == REG && REGNO(a1) == FRAME_POINTER_REGNUM) \
+ ADDR = gen_rtx(PLUS, Pmode, \
+ gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, offset)), \
+ XEXP(ADDR, 1)); \
+ else if (GET_CODE(a1) == PLUS && GET_CODE(XEXP(a1, 0)) == REG \
+ && REGNO(XEXP(a1, 0)) == FRAME_POINTER_REGNUM) \
+ ADDR = gen_rtx(PLUS, Pmode, \
+ gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, \
+ offset+INTVAL(XEXP(a1, 1)))),\
+ XEXP(ADDR, 1)); \
+ else \
+ abort(); \
+ } else if (GET_CODE(XEXP(ADDR, 1)) == MEM) { \
+ register rtx a1 = XEXP(XEXP(ADDR, 1), 0); \
+ if (GET_CODE(a1) == REG && REGNO(a1) == FRAME_POINTER_REGNUM) \
+ ADDR = gen_rtx(PLUS, Pmode, \
+ XEXP(ADDR, 0), \
+ gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, \
+ offset))); \
+ else if (GET_CODE(a1) == PLUS && GET_CODE(XEXP(a1, 0)) == REG \
+ && REGNO(XEXP(a1, 0)) == FRAME_POINTER_REGNUM) \
+ ADDR = gen_rtx(PLUS, Pmode, \
+ XEXP(ADDR, 0), \
+ gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, \
+ offset+INTVAL(XEXP(a1, 1)))));\
+ else \
+ abort(); \
+ } else \
+ abort(); \
+ } else if (GET_CODE(ADDR) == MEM) { \
+ register rtx a0 = XEXP(ADDR, 0); \
+ if (GET_CODE (a0) == REG && REGNO (a0) == FRAME_POINTER_REGNUM) \
+ ADDR = gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, offset)); \
+ else if (GET_CODE(a0) == PLUS && GET_CODE(XEXP(a0, 0)) == REG \
+ && REGNO(XEXP(a0, 0)) == FRAME_POINTER_REGNUM \
+ && GET_CODE(XEXP(a0, 1)) == CONST_INT) \
+ ADDR = gen_rtx(MEM, Pmode, \
+ plus_constant(stack_pointer_rtx, \
+ offset + INTVAL(XEXP(a0, 1)))); \
+ else \
+ abort(); \
+ } else \
+ abort(); \
+ }
+#endif
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+/* note that FP and SP cannot be used as an index. What about PC? */
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 8 || (unsigned)reg_renumber[REGNO] < 8)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+((REGNO) < 8 || (unsigned)reg_renumber[REGNO] < 8 \
+ || (REGNO) == FRAME_POINTER_REGNUM || (REGNO) == STACK_POINTER_REGNUM)
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST \
+ || (GET_CODE (X) == CONST_INT \
+ && ((unsigned)INTVAL (X) >= 0xe0000000 \
+ || (unsigned)INTVAL (X) < 0x20000000)))
+
+#define CONSTANT_ADDRESS_NO_LABEL_P(X) \
+ (GET_CODE (X) == CONST_INT \
+ && ((unsigned)INTVAL (X) >= 0xe0000000 \
+ || (unsigned)INTVAL (X) < 0x20000000))
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) \
+ (REGNO (X) < 8 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ of if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (REGNO (X) < 8 || REGNO (X) >= FRAME_POINTER_REGNUM)
+/* Nonzero if X is a floating point reg or a pseudo reg. */
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
+
+/* 1 if X is an address that we could indirect through. */
+/***** NOTE ***** There is a bug in the Sequent assembler which fails
+ to fixup addressing information for symbols used as offsets
+ from registers which are not FP or SP (or SB or PC). This
+ makes _x(fp) valid, while _x(r0) is invalid. */
+
+#define INDIRECTABLE_1_ADDRESS_P(X) \
+ (CONSTANT_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))))
+
+#define MEM_REG(X) \
+ ((GET_CODE (X) == REG && (REGNO (X) ^ 16) < 2) \
+ || (GET_CODE (X) == SYMBOL_REF))
+
+#define INDIRECTABLE_2_ADDRESS_P(X) \
+ (GET_CODE (X) == MEM \
+ && (((xfoo0 = XEXP (X, 0), MEM_REG (xfoo0)) \
+ || (GET_CODE (xfoo0) == PLUS \
+ && GET_CODE (XEXP (xfoo0, 0)) == REG \
+ && MEM_REG (XEXP (xfoo0, 0)) \
+ && CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfoo0, 1)))) \
+ || CONSTANT_ADDRESS_P (xfoo0)))
+
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (INDIRECTABLE_1_ADDRESS_P(X) \
+ || INDIRECTABLE_2_ADDRESS_P (X) \
+ || (GET_CODE (X) == PLUS \
+ && CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1)) \
+ && INDIRECTABLE_2_ADDRESS_P (XEXP (X, 0))))
+
+/* Go to ADDR if X is a valid address not using indexing.
+ (This much is the easy part.) */
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ register rtx xfoob = (X); \
+ if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (INDIRECTABLE_1_ADDRESS_P(X)) goto ADDR; \
+ if (INDIRECTABLE_2_ADDRESS_P (X)) goto ADDR; \
+ if (GET_CODE (X) == PLUS) \
+ if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1))) \
+ if (INDIRECTABLE_2_ADDRESS_P (XEXP (X, 0))) \
+ goto ADDR; \
+}
+
+/* 1 if PROD is either a reg times size of mode MODE
+ or just a reg, if MODE is just one byte. Actually, on the ns32k,
+ since the index mode is independent of the operand size,
+ we can match more stuff...
+
+ This macro's expansion uses the temporary variables xfoo0, xfoo1
+ and xfoo2 that must be declared in the surrounding context. */
+#define INDEX_TERM_P(PROD, MODE) \
+((GET_CODE (PROD) == REG && REG_OK_FOR_INDEX_P (PROD)) \
+ || (GET_CODE (PROD) == MULT \
+ && (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
+ (GET_CODE (xfoo1) == CONST_INT \
+ && GET_CODE (xfoo0) == REG \
+ && FITS_INDEX_RANGE (INTVAL (xfoo1)) \
+ && REG_OK_FOR_INDEX_P (xfoo0)))))
+
+#define FITS_INDEX_RANGE(X) \
+ ((xfoo2 = (unsigned)(X)-1), \
+ ((xfoo2 < 4 && xfoo2 != 2) || xfoo2 == 7))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ register rtx xfooy, xfooz, xfoo0, xfoo1; \
+ unsigned xfoo2; \
+ xfooy = X; \
+ GO_IF_NONINDEXED_ADDRESS (xfooy, ADDR); \
+ if (GET_CODE (xfooy) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (xfooy, 1)) == CONST_INT \
+ && GET_CODE (XEXP (xfooy, 0)) == PLUS) \
+ xfooy = XEXP (xfooy, 0); \
+ else if (GET_CODE (XEXP (xfooy, 0)) == CONST_INT \
+ && GET_CODE (XEXP (xfooy, 1)) == PLUS) \
+ xfooy = XEXP (xfooy, 1); \
+ xfooz = XEXP (xfooy, 1); \
+ if (INDEX_TERM_P (xfooz, MODE)) \
+ { rtx t = XEXP (xfooy, 0); GO_IF_NONINDEXED_ADDRESS (t, ADDR); }\
+ xfooz = XEXP (xfooy, 0); \
+ if (INDEX_TERM_P (xfooz, MODE)) \
+ { rtx t = XEXP (xfooy, 1); GO_IF_NONINDEXED_ADDRESS (t, ADDR); }\
+ } \
+ else if (INDEX_TERM_P (xfooy, MODE)) \
+ goto ADDR; \
+ else if (GET_CODE (xfooy) == PRE_DEC) \
+ if (REGNO (XEXP (xfooy, 0)) == STACK_POINTER_REGNUM) goto ADDR; \
+ else abort (); \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the ns32k, we do nothing */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the ns32k, only predecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand). */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ { if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) \
+ goto LABEL;}
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction.
+ Can do SImode, but HI mode is more efficient. */
+#define CASE_VECTOR_MODE HImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+/* #define SHIFT_COUNT_TRUNCATED */
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (INTVAL (RTX) <= 7 && INTVAL (RTX) >= -8) return 0; \
+ if (INTVAL (RTX) < 0x4000 && INTVAL (RTX) >= -0x4000) \
+ return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* This bit means that what ought to be in the Z bit
+ should be tested in the F bit. */
+#define CC_Z_IN_F 04000
+
+/* This bit means that what ought to be in the Z bit
+ is complemented in the F bit. */
+#define CC_Z_IN_NOT_F 010000
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (GET_CODE (EXP) == SET) \
+ { if (GET_CODE (SET_DEST (EXP)) == CC0) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (EXP); \
+ cc_status.value2 = SET_SRC (EXP); \
+ } \
+ else if (GET_CODE (SET_SRC (EXP)) == CALL) \
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (SET_DEST (EXP)) == REG) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2)) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (EXP)) == MEM) \
+ { CC_STATUS_INIT; } \
+ } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \
+ { if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == CC0) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \
+ cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); \
+ } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == REG) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value2)) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == MEM) \
+ { CC_STATUS_INIT; } \
+ } \
+ else if (GET_CODE (EXP) == CALL) \
+ { /* all bets are off */ CC_STATUS_INIT; } \
+ else { /* nothing happens? CC_STATUS_INIT; */} \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \
+ && cc_status.value2 \
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \
+ printf ("here!\n", cc_status.value2 = 0); \
+}
+
+#define OUTPUT_JUMP(NORMAL, NO_OV) \
+{ if (cc_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "fp", "sp"}
+
+/* How to renumber registers for dbx and gdb.
+ NS32000 may need more change in the numeration. */
+
+#define DBX_REGISTER_NUMBER(REGNO) ((REGNO < 8) ? (REGNO)+4 : (REGNO))
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to align the code that follows an unconditional branch. */
+
+#define ASM_OUTPUT_ALIGN_CODE(FILE) \
+ fprintf (FILE, "\t.align 4\n")
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmovd %s,tos\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovd tos,%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The 68000 does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+/* ** Notice that the second element is LI format! */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-LI%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print an instruction operand X on file FILE.
+ CODE is the code from the %-spec that requested printing this operand;
+ if `%z3' was used to print operand 3, then CODE is 'z'. */
+
+/* %$ means print the prefix for an immediate operand. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '$' || (CODE) == '?')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '$') fprintf (FILE, "$"); \
+ else if (CODE == '?'); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ if (GET_MODE (X) == DFmode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0d%.20e", u.d); } \
+ else \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0f%.20e", u.d); } \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+/* Print a memory operand whose address is X, on file FILE. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ int mem=0, multval, offset_printed; \
+ char reg1_str[256], reg2_str[256]; \
+ retry: \
+ switch (GET_CODE (addr)) \
+ { \
+ case MEM: \
+ fprintf (FILE, "0("); \
+ addr = XEXP (addr, 0); \
+ mem =1; \
+ goto retry; \
+ case REG: \
+ fprintf (FILE, "0(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ if (REGNO(XEXP(addr, 0)) != STACK_POINTER_REGNUM) \
+ fprintf(FILE, ")1:%d", REGNO(XEXP(addr,0))); \
+ else fprintf (FILE, "tos", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ if (REGNO(XEXP(addr, 0)) != STACK_POINTER_REGNUM) \
+ fprintf(FILE, ")2:%d", REGNO(XEXP(addr,0))); \
+ else fprintf (FILE, "tos", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case MULT: \
+ reg1 = XEXP (addr, 0); /* [rX:Y] */ \
+ reg2 = XEXP (addr, 1); /* CONST/REG */ \
+ if (GET_CODE (reg1) == CONST_INT && GET_CODE(reg2) == REG) { \
+ reg1 = reg2; \
+ reg2 = XEXP (addr, 0); /* [rX:Y] */ \
+ } else \
+ if (GET_CODE (reg2) != CONST_INT || \
+ GET_CODE (reg1) != REG) { \
+ abort(); \
+ } \
+ fprintf (FILE, "0[%s:%c]", \
+ reg_names[ REGNO(reg1) ], \
+ "XbwXdXXXq"[INTVAL (reg2)]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ multval = 0; \
+ reg1_str[0] = 0; reg2_str[0] = 0; \
+ offset_printed = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) \
+ || GET_CODE (XEXP (addr, 0)) == MEM) \
+ { \
+ /* CONST / MEM(PLUS((REG)(CONST))) */ \
+ offset = XEXP (addr, 0); \
+ /* (REG) / PLUS((REG)(CONST)) / MULT((REG)(CONST)) */ \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) \
+ || GET_CODE (XEXP (addr, 1)) == MEM) \
+ { \
+ /* CONST / MEM(PLUS((REG)(CONST))) */ \
+ offset = XEXP (addr, 1); \
+ /* (REG) / PLUS((REG)(CONST)) / MULT((REG)(CONST)) */ \
+ addr = XEXP (addr, 0); \
+ } \
+ if (offset != 0) { \
+ if (GET_CODE (offset) == MEM) { \
+ offset = XEXP (offset, 0); /* skip MEM */ \
+ switch (GET_CODE (offset)) { \
+ case REG: \
+ sprintf (reg1_str, "(%s)", \
+ reg_names[REGNO (offset)]); \
+ offset = 0; \
+ break; \
+ case PLUS: \
+ if (!CONSTANT_ADDRESS_P (XEXP (offset, 1))) { \
+ fprintf (FILE, \
+ "PROGRAM in disorder PRINT_ADDR, PLUS, PLUS\n"); \
+ print_rtl(FILE, offset); \
+ exit (1); \
+ } \
+ if (GET_CODE (XEXP(offset,0)) != REG) { \
+ fprintf (FILE, \
+ "PROGRAM in disorder PRINT_ADDR, PLUS, REG\n"); \
+ print_rtl(FILE, offset); \
+ exit (1); \
+ } \
+ sprintf (reg1_str, "(%s))", \
+ reg_names[REGNO (XEXP(offset,0))]); \
+ offset = XEXP (offset, 1); \
+ break; \
+ default: \
+ abort(); \
+ } \
+ } else { /* !MEM */ \
+ if (!CONSTANT_ADDRESS_P (offset)) { \
+ abort(); \
+ } \
+ output_addr_const (FILE, offset); \
+ offset_printed = 1; \
+ offset = 0; \
+ } \
+ } \
+ \
+ if (GET_CODE (addr) == PLUS) { \
+ if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); /* [rX:Y] */ \
+ addr = XEXP (addr, 1); /* CONST/REG */ \
+ if (GET_CODE (XEXP (reg1, 1)) != CONST_INT || \
+ GET_CODE (XEXP (reg1, 0)) != REG) { \
+ abort(); \
+ } \
+ sprintf (reg2_str, "[%s:%c]", \
+ reg_names[ REGNO(XEXP (reg1, 0)) ], \
+ "XbwXdXXXq"[INTVAL (XEXP (reg1, 1))]); \
+ reg1 = 0; \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); /* [rX:Y] */ \
+ addr = XEXP (addr, 0); /* CONST */ \
+ if (GET_CODE (XEXP (reg1, 1)) != CONST_INT || \
+ GET_CODE (XEXP (reg1, 0)) != REG) { \
+ abort(); \
+ } \
+ sprintf (reg2_str, "[%s:%c]", \
+ reg_names[ REGNO(XEXP (reg1, 0)) ], \
+ "XbwXdXXXq"[INTVAL (XEXP (reg1, 1))]); \
+ reg1 = 0; \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG \
+ && REGNO (XEXP (addr, 0)) < 8) \
+ { \
+ sprintf (reg2_str, "[%s:b]", \
+ reg_names[ REGNO(XEXP (addr, 0)) ]); \
+ addr = XEXP (addr, 1); /* CONST / REG */ \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG \
+ && REGNO (XEXP (addr, 1)) < 8) \
+ { \
+ sprintf (reg2_str, "[%s:b]", \
+ reg_names[ REGNO(XEXP (addr, 1)) ]); \
+ addr = XEXP (addr, 0); /* CONST / REG */ \
+ } \
+ else abort (); \
+ } \
+ if (addr) \
+ switch (GET_CODE (addr)) { \
+ case MULT: \
+ if(*reg2_str) { \
+ fprintf (FILE, \
+ "PROGRAM in disorder PRINT_ADDR, INDEX, two mults\n"); \
+ print_rtl(FILE, addr); \
+ exit (1); \
+ } \
+ reg1 = XEXP (addr, 0); /* [rX:Y] */ \
+ addr = XEXP (addr, 1); /* CONST */ \
+ if (GET_CODE (addr) != CONST_INT) { \
+ fprintf (FILE, \
+ "PROGRAM in disorder PRINT_ADDR, INDEX, !CONS3 (%d)\n", \
+ GET_CODE (addr)); \
+ print_rtl(FILE, addr); \
+ exit (1); \
+ } \
+ sprintf (reg2_str, "[%s:%c]", reg_names[ REGNO(reg1) ], \
+ "XbwXdXXXq"[INTVAL (addr)]); \
+ break; \
+ case REG: \
+ if (!*reg1_str) { \
+ if (offset || offset_printed) \
+ sprintf (reg1_str, "(%s)", reg_names[REGNO (addr)]); \
+ else \
+ sprintf (reg1_str, "0(%s)", reg_names[REGNO (addr)]); \
+ } else if (!*reg2_str) \
+ sprintf (reg2_str, "[%s:b]", \
+ reg_names[REGNO (addr)]); \
+ else abort(); \
+ break; \
+ case MEM: \
+ addr = XEXP(addr,0); \
+ switch (GET_CODE(addr)) { \
+ case REG: \
+ if (!*reg1_str) { \
+ if (offset || offset_printed) \
+ sprintf (reg1_str, "(0(%s))", \
+ reg_names[REGNO (addr)]); \
+ else \
+ sprintf (reg1_str, "0(0(%s))", \
+ reg_names[REGNO (addr)]); \
+ } else \
+ abort(); \
+ break; \
+ case PLUS: \
+ if (GET_CODE (XEXP (addr, 0)) == REG) { \
+ if (!*reg1_str) { \
+ sprintf (reg1_str, "(%s))", \
+ reg_names[REGNO(XEXP(addr, 0))]); \
+ offset = XEXP(addr, 1); \
+ } else \
+ abort(); \
+ } else { \
+ if (!*reg1_str) { \
+ sprintf (reg1_str, "(%s))", \
+ reg_names[REGNO(XEXP(addr, 1))]); \
+ offset = XEXP(addr, 0); \
+ } else \
+ abort(); \
+ } \
+ break; \
+ default: \
+ abort(); \
+ } \
+ break; \
+ default: \
+ if (offset_printed) \
+ fprintf (FILE, "+"); \
+ output_addr_const (FILE, addr); \
+ offset_printed ++; \
+ } \
+ if (offset) { \
+ if(!offset_printed) \
+ fputc ('0', FILE); \
+ fputc ('(', FILE); \
+ output_addr_const (FILE, offset); \
+ } \
+ if (*reg1_str) \
+ fprintf (FILE, "%s", reg1_str); \
+ if (*reg2_str) \
+ fprintf (FILE, "%s", reg2_str); \
+ break; \
+ default: \
+ output_addr_const (FILE, addr); \
+ } \
+ if(mem) \
+ fprintf(FILE,")");}
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/gcc-1.40/config/tm-pyr.h b/gcc-1.40/config/tm-pyr.h
new file mode 100644
index 0000000..6d1c593
--- /dev/null
+++ b/gcc-1.40/config/tm-pyr.h
@@ -0,0 +1,1406 @@
+/* Definitions of target machine for GNU compiler for Pyramid 90 Series.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * If you're going to change this, and you haven't already,
+ * you should get and read
+ * ``OSx Operating System Porting Guide'',
+ * publication number 4100-0066-A
+ * Revision A
+ * Pyramid Technology Corporation.
+ *
+ * or whatever the most recent version is. In any case, page and
+ * section number references given herein refer to this document.
+ *
+ * The instruction table for gdb lists the available insns and
+ * the valid addressing modes.
+ *
+ * Any other information on the Pyramid architecture is proprietary
+ * and hard to get. (Pyramid cc -S and adb are also useful.)
+ *
+ */
+
+/*** Run-time compilation parameters selecting different hardware subsets. ***/
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dpyr -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (pyr)");
+
+extern int target_flags;
+
+/* Nonzero if compiling code that Unix assembler can assemble. */
+#define TARGET_UNIX_ASM (target_flags & 1)
+
+/* Use the indexed addressing modes (were once not known to work).
+ Leaving this in means we can disable them and so find out what
+ they win us. */
+#define TARGET_INDEX (target_flags & 2)
+
+/* Implement stdarg in the same fashion used on all other machines. */
+#define TARGET_GNU_STDARG (target_flags & 4)
+
+/* Compile using RETD to pop off the args.
+ This will not work unless you use prototypes at least
+ for all functions that can take varying numbers of args.
+ This contravenes the Pyramid calling convention, so we don't
+ do it yet. */
+
+#define TARGET_RETD (target_flags & 8)
+
+/* Macros used in the machine description to test the flags. */
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE.
+
+ -mgnu will be useful if we ever have GAS on a pyramid.
+ -mindex was used to enable indexing when I didn't understand
+ how pyramid's indexing modes worked. */
+
+#define TARGET_SWITCHES \
+ { {"unix", 1}, \
+ {"gnu", -1}, \
+ {"index", 2}, \
+ {"noindex", -2}, \
+ {"gnu-stdarg", 4}, \
+ {"nognu-stdarg", -4}, \
+ {"retd", 8}, \
+ {"no-retd", -8}, \
+ { "", TARGET_DEFAULT}}
+
+/* Default target_flags if no switches specified.
+
+ (equivalent to "-munix -mindex -mgnu-stdarg") */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT (1 + 2 + 4)
+#endif
+
+/*** Target machine storage layout ***/
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is not true on the pyramid. */
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+#define WORDS_BIG_ENDIAN
+
+/* Number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+/* --> FIXME: I don't know if this is what pyr cc does. */
+#define STRUCTURE_SIZE_BOUNDARY 32
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* Make strings word-aligned so dhrystone will run faster.
+ Pyramid documentation says the best alignment is to align
+ on the size of a cache line, which is 16 bytes.
+ Newer pyrs have single insns that do strcmp() and strcpy(), so this
+ may not actually win anything. */
+/* Try to increase aligment. */
+
+/* Use kludge to maintain alignment for pyramid. See
+ DATA_SECTION_ASM_OP below. */
+#define CONSTANT_ALIGNMENT(CODE, TYPEALIGN) \
+ ((CODE) == STRING_CST ? (TYPEALIGN) * 4 : (TYPEALIGN))
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/*** Standard register usage. ***/
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+
+/* Nota Bene:
+ Pyramids have 64 addressable 32-bit registers, arranged as four
+ groups: global, parameter, local, and temporary.
+ The sixteen global registers are fairly conventional; the last
+ four are overloaded with a PSW, frame pointer, and stack pointer.
+ The non-dedicated global registers used to be reserved for Pyramid
+ operating systems, and still have cryptic and undocumented uses for
+ certain library calls. We avoid them.
+
+ The parameter, local, and temporary registers provide _register_
+ _windowing_. Each procedure call has its own set of these 48
+ registers, which constitute its call frame. (These frames are
+ allocated on a stack separate from the conventional data stack,
+ called the _control_ _stack_.
+ facility hereby the temporary registers of frame n
+ become the parameter registers of frame n+1, viz.:
+
+ 0 15 0 15 0 15
+ +------------+------------+------------+
+ | | | |
+ +------------+------------+------------+
+ Parameter Local Temporary
+
+ ^
+ |
+ v
+
+ 0 15 0 15 0 15
+ +------------+------------+------------+
+ | | | |
+ +------------+------------+------------+
+ Parameter Local Temporary
+
+
+ Temporary registers are used for parameter passing, and are not
+ preserved across calls. TR14 and TR15 are reserved and should
+ never be used; since they are used to save the next frame's PC
+ and stack pointer, their contents may be destroyed at any time by
+ an interrupt.
+ */
+
+#define PYR_GREG(n) (n)
+#define PYR_PREG(n) (16+(n))
+#define PYR_LREG(n) (32+(n))
+#define PYR_TREG(n) (48+(n))
+
+#define FIRST_PSEUDO_REGISTER 64
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+
+ On the pyramid, these are LOGPSW, CFP, SP, PC, but we leave the other
+ global regs alone as well. */
+
+#define FIXED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
+
+/* #define DEFAULT_CALLER_SAVES */
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+ On the pyramid, all registers are one word long. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the pyramid, all registers can hold all modes. */
+
+/* -->FIXME: this is not the case for 64-bit quantities in tr11/12 through
+ --> TR14/15. This should be fixed, but to do it correctly, we also
+ --> need to fix MODES_TIEABLE_P. Yuk. We ignore this, since GCC should
+ --> do the "right" thing due to FIXED_REGISTERS. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* Pyramid pc is overloaded on global register 15. */
+#define PC_REGNUM PYR_GREG(15)
+
+/* Register to use for pushing function arguments.
+ --> on Pyramids, the data stack pointer. */
+#define STACK_POINTER_REGNUM PYR_GREG(14)
+
+/* Base register for access to local variables of the function.
+ Pyramid uses CFP (GR13) as both frame pointer and argument pointer. */
+#define FRAME_POINTER_REGNUM 13 /* PYR_GREG(13) */
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c.
+
+ Setting this to 1 can't break anything. Since the Pyramid has
+ register windows, I don't know if defining this to be zero can
+ win anything. It could changed later, if it wins. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 13 /* PYR_GREG(13) */
+
+/* Register in which static-chain is passed to a function. */
+/* If needed, Pyramid says to use temporary register 12. */
+#define STATIC_CHAIN_REGNUM PYR_TREG(12)
+
+/* Register in which address to store a structure value
+ is passed to a function.
+ On a Pyramid, this is temporary register 0 (TR0). */
+
+#define STRUCT_VALUE_REGNUM PYR_TREG(0)
+#define STRUCT_VALUE_INCOMING_REGNUM PYR_PREG(0)
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The pyramid has only one kind of registers, so NO_REGS and ALL_REGS
+ are the only classes. */
+
+enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Since GENERAL_REGS is the same class as ALL_REGS,
+ don't give it a different class number; just make it an alias. */
+
+#define GENERAL_REGS ALL_REGS
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {{0,0}, {0xffffffff,0xffffffff}}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) ALL_REGS
+
+/* The class value for index registers, and the one for base regs. */
+
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) NO_REGS
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the pyramid, this is always the size of MODE in words,
+ since all registers are the same size. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ --> For the Pyramid, 'I' can be used for the 6-bit signed integers
+ --> (-32 to 31) allowed as immediate short operands in many
+ --> instructions. 'J' cane be used for any value that doesn't fit
+ --> in 6 bits. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (VALUE) >= -32 && (VALUE) < 32 : \
+ (C) == 'J' ? (VALUE) < -32 || (VALUE) >= 32 : \
+ (C) == 'K' ? (VALUE) == 0xff || (VALUE) == 0xffff : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
+
+
+/*** Stack layout; function entry, exit and calling. ***/
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+/* FIXME: this used to work when defined as 0. But that makes gnu
+ stdargs clobber the first arg. What gives?? */
+#define STARTING_FRAME_OFFSET 0
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ The Pyramid OSx Porting Guide says we are never to do this;
+ using RETD in this way violates the Pyramid calling convention.
+ We may nevertheless provide this as an option. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) \
+ (TARGET_RETD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \
+ || TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) == void_type_node))
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* --> Pyramid has register windows.
+ --> The caller sees the return value is in TR0(/TR1) regardless of
+ --> its type. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), PYR_TREG(0))
+
+/* --> but the callee has to leave it in PR0(/PR1) */
+
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), PYR_PREG(0))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* --> On Pyramid the return value is in TR0/TR1 regardless. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, PYR_TREG(0))
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller.
+
+ On the Pyramid, TR0 is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == PYR_TREG(0))
+
+/* 1 if N is a possible register number for function argument passing.
+ On the Pyramid, the first twelve temporary registers are available. */
+
+/* FIXME FIXME FIXME
+ it's not clear whether this macro should be defined from the point
+ of view of the caller or the callee. Since it's never actually used
+ in GNU CC, the point is somewhat moot :-).
+
+ This definition is consistent with register usage in the md's for
+ other register-window architectures (sparc and spur).
+ */
+#define FUNCTION_ARG_REGNO_P(N) ((PYR_TREG(0) <= (N)) && ((N) <= PYR_TREG(11)))
+
+/*** Parameter passing: FUNCTION_ARG and FUNCTION_INCOMING_ARG ***/
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On Pyramids, each parameter is passed either completely on the stack
+ or completely in registers. No parameter larger than a double may
+ be passed in a register. Also, no struct or union may be passed in
+ a register, even if it would fit.
+
+ So parameters are not necessarily passed "consecutively".
+ Thus we need a vector data type: one element to record how many
+ parameters have been passed in registers and on the stack,
+ respectively.
+
+ ((These constraints seem like a gross waste of registers. But if we
+ ignore the constraint about structs & unions, we won`t be able to
+ freely mix gcc-compiled code and pyr cc-compiled code. It looks
+ like better argument passing conventions, and a machine-dependent
+ flag to enable them, might be a win.)) */
+
+
+#define CUMULATIVE_ARGS int
+
+/* Define the number of registers that can hold paramters.
+ This macro is used only in other macro definitions below. */
+#define NPARM_REGS 12
+
+/* Decide whether or not a parameter can be put in a register.
+ (We may still have problems with libcalls. GCC doesn't seem
+ to know about anything more than the machine mode. I trust
+ structures are never passed to a libcall...
+
+ If compiling with -mgnu-stdarg, this definition should make
+ functions using the gcc-supplied stdarg, and calls to such
+ functions (declared with an arglist ending in"..."), work.
+ But such fns won't be able to call pyr cc-compiled
+ varargs fns (eg, printf(), _doprnt.)
+
+ If compiling with -mnognu-stdarg, this definition should make
+ calls to pyr cc-compiled functions work. Functions using
+ the gcc-supplied stdarg will be utterly broken.
+ There will be no better solution until RMS can be persuaded that
+ one is needed.
+
+ This macro is used only in other macro definitions below.
+ (well, it may be used in out-pyr.c, because the damn pyramid cc
+ can't handle the macro definition of PARAM_SAFE_FOR_REG_P ! */
+
+
+#define INNER_PARAM_SAFE_HELPER(TYPE) \
+ ((TARGET_GNU_STDARG ? (! TREE_ADDRESSABLE ((tree)TYPE)): 1) \
+ && (TREE_CODE ((tree)TYPE) != RECORD_TYPE) \
+ && (TREE_CODE ((tree)TYPE) != UNION_TYPE))
+
+#ifdef __GNUC__
+#define PARAM_SAFE_HELPER(TYPE) \
+ INNER_PARAM_SAFE_HELPER((TYPE))
+#else
+extern int inner_param_safe_helper();
+#define PARAM_SAFE_HELPER(TYPE) \
+ inner_param_safe_helper((tree)(TYPE))
+#endif
+
+/* Be careful with the expression (long) (TYPE) == 0.
+ Writing it in more obvious/correct forms makes the Pyr cc
+ dump core! */
+#define PARAM_SAFE_FOR_REG_P(MODE, TYPE, NAMED) \
+ (((MODE) != BLKmode) \
+ && ((TARGET_GNU_STDARG) ? (NAMED) : 1) \
+ && ((((long)(TYPE))==0) || PARAM_SAFE_HELPER((TYPE))))
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = (FNTYPE && !flag_pcc_struct_return && aggregate_value_p (FNTYPE)))
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+#define FUNCTION_ARG_HELPER(CUM, MODE, TYPE, NAMED) \
+(PARAM_SAFE_FOR_REG_P(MODE,TYPE,NAMED) \
+ ? (NPARM_REGS >= ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) \
+ ? gen_rtx (REG, (MODE), PYR_TREG(CUM)) \
+ : 0) \
+ : 0)
+#ifdef __GNUC__
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ FUNCTION_ARG_HELPER(CUM, MODE, TYPE, NAMED)
+#else
+/***************** Avoid bug in Pyramid OSx compiler... ******************/
+#define FUNCTION_ARG (rtx) pyr_function_arg
+extern void* pyr_function_arg ();
+#endif
+
+/* Define where a function finds its arguments.
+ This is different from FUNCTION_ARG because of register windows. */
+
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+(PARAM_SAFE_FOR_REG_P(MODE,TYPE,NAMED) \
+ ? (NPARM_REGS >= ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) \
+ ? gen_rtx (REG, (MODE), PYR_PREG(CUM)) \
+ : 0) \
+ : 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
+((CUM) += (PARAM_SAFE_FOR_REG_P(MODE,TYPE,NAMED) \
+ ? ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) / 4 \
+ : (int_size_in_bytes (TYPE) + 3) / 4) \
+ : 0))
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#if FRAME_POINTER_REQUIRED
+
+/* We always have frame pointers */
+
+/* Don't set up a frame pointer if it's not referenced. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ int _size = (SIZE) + current_function_pretend_args_size; \
+ if (_size + current_function_args_size != 0 \
+ || current_function_calls_alloca) \
+ { \
+ fprintf (FILE, "\tadsf $%d\n", _size); \
+ if (current_function_pretend_args_size > 0) \
+ fprintf (FILE, "\tsubw $%d,cfp\n", \
+ current_function_pretend_args_size); \
+ } \
+}
+
+#else /* !FRAME_POINTER_REQUIRED */
+
+/* Don't set up a frame pointer if `frame_pointer_needed' tells us
+ there is no need. Also, don't set up a frame pointer if it's not
+ referenced. */
+
+/* The definition used to be broken. Write a new one. */
+
+#endif /* !FRAME_POINTER_REQUIRED */
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tmova LP%d,tr0\n\tcall mcount\n", (LABELNO));
+
+/* Output assembler code to FILE to initialize this source file's
+ basic block profiling info, if that has not already been done.
+ Don't know if this works on Pyrs. */
+
+#if 0 /* don't do basic_block profiling yet */
+#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, \
+ "\tmtstw LPBX0,tr0\n\tbne LPI%d\n\tmova LP%d,TR0\n\tcall __bb_init_func\nLPI%d:\n", \
+ LABELNO, LABELNO);
+
+/* Output assembler code to increment the count associated with
+ the basic block number BLOCKNO. Not sure how to do this on pyrs. */
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+ fprintf (FILE, "\taddw", 4 * BLOCKNO)
+#endif /* don't do basic_block profiling yet */
+
+/* When returning from a function, the stack pointer does not matter
+ (as long as there is a frame pointer). */
+
+/* This should return non-zero when we really set up a frame pointer.
+ Otherwise, GCC is directed to preserve sp by returning zero. */
+extern int current_function_pretend_args_size;
+extern int current_function_args_size;
+extern int current_function_calls_alloca;
+#define EXIT_IGNORE_STACK \
+ (get_frame_size () + current_function_pretend_args_size \
+ + current_function_args_size != 0 \
+ || current_function_calls_alloca) \
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+/* ---> Since we always have a frame pointer, it is safe for this
+ to not work. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+ fatal ("compiler error, Pyramid call without frame ptr!\n")
+
+/*** Addressing modes, and classification of registers for them. ***/
+
+/* #define HAVE_POST_INCREMENT */ /* pyramid has none of these */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+/* All registers except gr0 OK as index or base registers. */
+
+#define REGNO_OK_FOR_BASE_P(regno) \
+((0 < (regno) && (regno) < FIRST_PSEUDO_REGISTER) || reg_renumber[regno] > 0)
+
+#define REGNO_OK_FOR_INDEX_P(regno) \
+((0 < (regno) && (regno) < FIRST_PSEUDO_REGISTER) || reg_renumber[regno] > 0)
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2 /* check MAX_REGS_PER_ADDRESS */
+
+/* 1 if X is an rtx for a constant that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) 1
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) 1
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) 1
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is actually machine-independent. */
+
+
+/* Go to ADDR if X is indexable -- ie, neither indexed nor offset.
+ Note that X is indexable iff x is offset. */
+#define GO_IF_INDEXABLE_ADDRESS(X, ADDR) \
+{ register rtx xfoob = (X); \
+ if ((CONSTANT_ADDRESS_P (xfoob)) \
+ || (GET_CODE (xfoob) == REG && (REG_OK_FOR_BASE_P (xfoob)))) \
+ goto ADDR; \
+ }
+
+
+/* Go to label ADDR if X is a valid address that doesn't use indexing.
+ This is so if X is either a simple address, or the contents of a register
+ plus an offset.
+ This macro also gets used in output-pyramid.h in the function that
+ recognizes non-indexed operands. */
+
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ \
+ if (GET_CODE (X) == REG) \
+ goto ADDR; \
+ GO_IF_INDEXABLE_ADDRESS (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { /* Handle offset(reg) represented with offset on left */ \
+ if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ { if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ goto ADDR; \
+ } \
+ /* Handle offset(reg) represented with offset on right */ \
+ if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ { if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ goto ADDR; \
+ } \
+ } \
+}
+
+/* 1 if PROD is either a reg or a reg times a valid offset multiplier
+ (ie, 2, 4, or 8).
+ This macro's expansion uses the temporary variables xfoo0 and xfoo1
+ that must be declared in the surrounding context. */
+#define INDEX_TERM_P(PROD, MODE) \
+((GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \
+ || (GET_CODE (PROD) == MULT \
+ && \
+ (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
+ ((GET_CODE (xfoo0) == CONST_INT \
+ && (INTVAL (xfoo0) == 1 \
+ || INTVAL (xfoo0) == 2 \
+ || INTVAL (xfoo0) == 4 \
+ || INTVAL (xfoo0) == 8) \
+ && GET_CODE (xfoo1) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo1)) \
+ || \
+ (GET_CODE (xfoo1) == CONST_INT \
+ && (INTVAL (xfoo1) == 1 \
+ || INTVAL (xfoo1) == 2 \
+ || INTVAL (xfoo1) == 4 \
+ || INTVAL (xfoo1) == 8) \
+ && GET_CODE (xfoo0) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo0))))))
+
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ register rtx xone, xtwo, xfoo0, xfoo1; \
+ GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
+ if (TARGET_INDEX && GET_CODE (X) == PLUS) \
+ { \
+ /* Handle <address>[index] represented with index-sum outermost */\
+ xone = XEXP (X, 0); \
+ xtwo = XEXP (X, 1); \
+ if (INDEX_TERM_P (xone, MODE)) \
+ { GO_IF_INDEXABLE_ADDRESS (xtwo, ADDR); } \
+ /* Handle <address>[index] represented with index-sum innermost */\
+ if (INDEX_TERM_P (xtwo, MODE)) \
+ { GO_IF_INDEXABLE_ADDRESS (xone, ADDR); } \
+ } \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ --> FIXME: We haven't yet figured out what optimizations are useful
+ --> on Pyramids. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ There don't seem to be any such modes on pyramids. */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+
+/*** Miscellaneous Parameters ***/
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/*#define CASE_VECTOR_PC_RELATIVE*/
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case.
+ It's just a guess. I have no idea of insn cost on pyrs. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* This flag, if defined, says the same insns that convert to a signed fixnum
+ also convert validly to an unsigned one. */
+/* This is untrue for pyramid. The cvtdw instruction generates a trap
+ for input operands that are out-of-range for a signed int. */
+/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */
+
+/* Define this macro if the preprocessor should silently ignore
+ '#sccs' directives. */
+/* #define SCCS_DIRECTIVE */
+
+/* Define this macro if the preprocessor should silently ignore
+ '#ident' directives. */
+/* #define IDENT_DIRECTIVE */
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 8
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* number of bits in an 'int' on target machine */
+#define INT_TYPE_SIZE 32
+
+/* 1 if byte access requires more than one instruction */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Define this macro if it is as good or better to call a constant
+ function address than to call an address kept in a register.
+/* #define NO_FUNCTION_CSE */
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* There are no flag store insns on a pyr. */
+/* #define STORE_FLAG_VALUE */
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (CONST_OK_FOR_LETTER_P (INTVAL (RTX),'I')) return 0; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 2; \
+ case CONST_DOUBLE: \
+ return 4;
+
+/*** Condition Code Information ***/
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for the pyr. */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* This is a very simple definition of NOTICE_UPDATE_CC.
+ Many cases can be optimized, to improve condition code usage.
+ Maybe we should handle this entirely in the md, since it complicated
+ to describe the way pyr sets cc. */
+
+#define TRULY_UNSIGNED_COMPARE_P(X) \
+ (X == GEU || X == GTU || X == LEU || X == LTU)
+#define CC_VALID_FOR_UNSIGNED 2
+
+#define CC_STATUS_MDEP_INIT cc_status.mdep = 0
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+ notice_update_cc(EXP, INSN)
+
+/*** Output of Assembler Code ***/
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) \
+ fprintf (FILE, ((TARGET_UNIX_ASM)? "" : "#NO_APP\n"));
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ((TARGET_UNIX_ASM) ? "" : "#APP\n")
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ((TARGET_UNIX_ASM) ? "" : "#NO_APP\n")
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"gr0", "gr1", "gr2", "gr3", "gr4", "gr5", "gr6", "gr7", "gr8", \
+ "gr9", "gr10", "gr11", "logpsw", "cfp", "sp", "pc", \
+ "pr0", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", \
+ "pr8", "pr9", "pr10", "pr11", "pr12", "pr13", "pr14", "pr15", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", \
+ "lr8", "lr9", "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", \
+ "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", \
+ "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15"}
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* Our preference is for dbx rather than sdb.
+ Yours may be different. */
+#define DBX_DEBUGGING_INFO
+/* #define SDB_DEBUGGING_INFO */
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS 1
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME);
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.half "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tsubw $4,sp\n\tmovw %s,(sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovw (sp),%s\n\taddw $4,sp\n", reg_names[REGNO])
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.word L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes.
+
+ On Pyramids, .align takes only args between 2 and 5.
+ */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", (LOG) < 2 ? 2 : (LOG))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+ On the Pyr, we support the conventional CODE characters:
+
+ 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex)
+ which are never used. */
+
+/* FIXME : should be more robust with CONST_DOUBLE. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names [REGNO (X)]); \
+ \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ if (CODE == 'f') \
+ fprintf (FILE, "$0f%.0e", u1.f); \
+ else \
+ fprintf (FILE, "$0x%x", u1.i); } \
+ \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0d%.20e", u.d); } \
+ \
+ else if (CODE == 'N') \
+ switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("eq", FILE); break; \
+ case NE: fputs ("ne", FILE); break; \
+ case GT: \
+ case GTU: fputs ("gt", FILE); break; \
+ case LT: \
+ case LTU: fputs ("lt", FILE); break; \
+ case GE: \
+ case GEU: fputs ("ge", FILE); break; \
+ case LE: \
+ case LEU: fputs ("le", FILE); break; \
+ } \
+ \
+ else if (CODE == 'C') \
+ switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("ne", FILE); break; \
+ case NE: fputs ("eq", FILE); break; \
+ case GT: \
+ case GTU: fputs ("le", FILE); break; \
+ case LT: \
+ case LTU: fputs ("ge", FILE); break; \
+ case GE: \
+ case GEU: fputs ("lt", FILE); break; \
+ case LE: \
+ case LEU: fputs ("gt", FILE); break; \
+ } \
+ \
+ else if (CODE == 'R') \
+ switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("eq", FILE); break; \
+ case NE: fputs ("ne", FILE); break; \
+ case GT: \
+ case GTU: fputs ("lt", FILE); break; \
+ case LT: \
+ case LTU: fputs ("gt", FILE); break; \
+ case GE: \
+ case GEU: fputs ("le", FILE); break; \
+ case LE: \
+ case LEU: fputs ("ge", FILE); break; \
+ } \
+ \
+ else { putc ('$', FILE); output_addr_const (FILE, X); } \
+}
+
+/* Print a memory operand whose address is ADDR, on file FILE. */
+/* This is horrendously complicated. */
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ \
+ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset, scale; \
+ retry: \
+ switch (GET_CODE (addr)) \
+ { \
+ case MEM: \
+ fprintf (stderr, "bad Mem "); debug_rtx (addr); \
+ addr = XEXP (addr, 0); \
+ abort (); \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names [REGNO (addr)]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) \
+ || GET_CODE (XEXP (addr, 0)) == MEM) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) \
+ || GET_CODE (XEXP (addr, 1)) == MEM) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) \
+ { \
+ if (reg1 == 0) \
+ reg1 = addr; \
+ else \
+ reg2 = addr; \
+ addr = 0; \
+ } \
+ if (offset != 0) \
+ { \
+ if (addr != 0) { \
+ fprintf (stderr, "\nBad addr "); debug_rtx (addr); \
+ abort ();} \
+ addr = offset; \
+ } \
+ if (reg1 != 0 && GET_CODE (reg1) == MULT) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg2 != 0 && GET_CODE (reg2) == MULT) \
+ { breg = reg1; ireg = reg2; } \
+ else if (reg2 != 0 || GET_CODE (addr) == MEM) \
+ { breg = reg2; ireg = reg1; } \
+ else \
+ { breg = reg1; ireg = reg2; } \
+ if (addr != 0) \
+ output_address (offset); \
+ if (breg != 0) \
+ { if (GET_CODE (breg) != REG) \
+ { \
+ fprintf (stderr, "bad Breg"); debug_rtx (addr); \
+ abort (); \
+ } \
+ fprintf (FILE, "(%s)", reg_names[REGNO (breg)]); } \
+ if (ireg != 0) \
+ { \
+ if (GET_CODE (ireg) == MULT) \
+ { \
+ scale = XEXP (ireg, 1); \
+ ireg = XEXP (ireg, 0); \
+ if (GET_CODE (ireg) != REG) \
+ { register rtx tem; \
+ tem = ireg; ireg = scale; scale = tem; \
+ } \
+ if (GET_CODE (ireg) != REG) { \
+ fprintf (stderr, "bad idx "); debug_rtx (addr); \
+ abort (); } \
+ if ((GET_CODE (scale) == CONST_INT) && (INTVAL(scale) >= 1))\
+ fprintf (FILE, "[%s*0x%x]", reg_names[REGNO (ireg)], \
+ INTVAL(scale)); \
+ else \
+ fprintf (FILE, "[%s*1]", reg_names[REGNO (ireg)]); \
+ } \
+ else if (GET_CODE (ireg) == REG) \
+ fprintf (FILE, "[%s*1]", reg_names[REGNO (ireg)]); \
+ else \
+ { \
+ fprintf (stderr, "Not indexed at all!"); debug_rtx (addr);\
+ abort (); \
+ } \
+ } \
+ break; \
+ default: \
+ output_addr_const (FILE, addr); \
+ } \
+}
diff --git a/gcc-1.40/config/tm-seq386.h b/gcc-1.40/config/tm-seq386.h
new file mode 100644
index 0000000..615c6cf
--- /dev/null
+++ b/gcc-1.40/config/tm-seq386.h
@@ -0,0 +1,79 @@
+/* Definitions for Sequent Intel 386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-i386.h"
+
+/* Use the BSD assembler syntax. */
+
+#include "tm-bsd386.h"
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-Dunix -Di386 -Dsequent"
+
+/* Pass -Z and -ZO options to the linker. */
+
+#define LINK_SPEC "%{Z*}"
+
+/* We don't want to output SDB debugging information. */
+
+#undef SDB_DEBUGGING_INFO
+
+/* We want to output DBX debugging information. */
+
+#define DBX_DEBUGGING_INFO
+
+/* gcc order is ax, dx, cx, bx, si, di, bp, sp, st, st.
+ * dbx order is ax, dx, cx, st(0), st(1), bx, si, di, st(2), st(3),
+ * st(4), st(5), st(6), st(7), sp, bp */
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+((n) < 3 ? (n) : (n) < 6 ? (n) + 2 \
+ : (n) == 6 ? 15 : (n) == 7 ? 14 : 3)
+
+/* Prevent anything from being allocated in the register pair cx/bx,
+ since that would confuse GDB. */
+
+#undef HARD_REGNO_MODE_OK
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (hard_regno_mode_ok (REGNO, MODE) \
+ && ! (REGNO == 2 && GET_MODE_SIZE (MODE) > 4))
+
+/* Floating-point return values come in the FP register. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tmovl $LP%d,%%eax\n\tcall mcount\n", (LABELNO));
+
+/* Assember pseudo-op for shared data segment. */
+#define SHARED_SECTION_ASM_OP ".shdata"
diff --git a/gcc-1.40/config/tm-sequent.h b/gcc-1.40/config/tm-sequent.h
new file mode 100644
index 0000000..d34c249
--- /dev/null
+++ b/gcc-1.40/config/tm-sequent.h
@@ -0,0 +1,110 @@
+/* Definitions of target machine for GNU compiler. SEQUENT NS32000 version.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Two flags to control how addresses are printed in assembler insns. */
+#define SEQUENT_ADDRESS_BUG 1
+#define SEQUENT_BASE_REGS
+
+#include "tm-ns32k.h"
+
+/* This is BSD, so it wants DBX format. */
+#define DBX_DEBUGGING_INFO
+
+/* Sequent has some changes in the format of DBX symbols. */
+#define DBX_NO_XREFS 1
+
+/* Don't split DBX symbols into continuations. */
+#define DBX_CONTIN_LENGTH 0
+
+#define TARGET_DEFAULT 1
+
+/* Print subsidiary information on the compiler version in use. */
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (32000, Sequent syntax)");
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dns32000 -Dsequent -Dunix"
+
+/* This is how to align the code that follows an unconditional branch.
+ Don't define it, since it confuses the assembler (we hear). */
+
+#undef ASM_OUTPUT_ALIGN_CODE
+
+/* Assember pseudo-op for shared data segment. */
+#define SHARED_SECTION_ASM_OP ".shdata"
+
+/* Control how stack adjust insns are output. */
+#define SEQUENT_ADJUST_STACK
+
+/* %$ means print the prefix for an immediate operand.
+ On the sequent, no prefix is used for such. */
+
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '$') ; \
+ else if (CODE == '?'); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ rtx xfoo; \
+ xfoo = XEXP (X, 0); \
+ switch (GET_CODE (xfoo)) \
+ { \
+ case MEM: \
+ if (GET_CODE (XEXP (xfoo, 0)) == REG) \
+ if (REGNO (XEXP (xfoo, 0)) == STACK_POINTER_REGNUM) \
+ fprintf (FILE, "0(0(sp))"); \
+ else fprintf (FILE, "0(0(%s))", \
+ reg_names[REGNO (XEXP (xfoo, 0))]); \
+ else \
+ { \
+ fprintf (FILE, "0("); \
+ output_address (xfoo); \
+ putc (')', FILE); \
+ } \
+ break; \
+ case REG: \
+ fprintf (FILE, "0(%s)", reg_names[REGNO (xfoo)]); \
+ break; \
+ case PRE_DEC: \
+ case POST_INC: \
+ fprintf (FILE, "tos"); \
+ break; \
+ case CONST_INT: \
+ fprintf (FILE, "@%d", INTVAL (xfoo)); \
+ break; \
+ default: \
+ output_address (xfoo); \
+ break; \
+ } \
+ } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ if (GET_MODE (X) == DFmode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "0d%.20e", u.d); } \
+ else { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "0f%.20e", u.d); } \
+ else output_addr_const (FILE, X); }
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address(FILE, ADDR)
diff --git a/gcc-1.40/config/tm-sparc.h b/gcc-1.40/config/tm-sparc.h
new file mode 100644
index 0000000..6924a17
--- /dev/null
+++ b/gcc-1.40/config/tm-sparc.h
@@ -0,0 +1,1435 @@
+/* Definitions of target machine for GNU compiler, for Sun SPARC.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+/* Specify library to handle `-a' basic block profiling. */
+
+#define LIB_SPEC "%{a:/usr/lib/bb_link.o} \
+%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} "
+
+/* Provide required defaults for linker -e and -d switches.
+ Also, it is hard to debug with shared libraries,
+ so don't use them if going to debug. */
+
+#define LINK_SPEC "%{!e*:-e start} -dc -dp %{g:-Bstatic} %{static:-Bstatic} %{Bstatic}"
+
+/* Special flags to the Sun-4 assembler when using pipe for input. */
+
+#define ASM_SPEC " %{pipe:-} "
+
+/* Prevent error on `-dalign', `-sun4' and `-target sun4' options. */
+
+#define CC1_SPEC "%{dalign:} %{sun4:} %{target:}"
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) (!strcmp (STR, "target"))
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dsparc -Dsun -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (sparc)");
+
+/* Generate DBX debugging information. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Nonzero if we should generate code to use the fpu. */
+#define TARGET_FPU (target_flags & 1)
+
+/* Nonzero if we should use FUNCTION_EPILOGUE. Otherwise, we
+ use fast return insns, but lose some generality. */
+#define TARGET_EPILOGUE (target_flags & 2)
+
+/* Nonzero if we expect to be passed through the Sun
+ optimizing assembler. This requires us to generate
+ code which we otherwise would not. For example,
+ calls via pointers-to-functions must be output
+ specially because Sun assemble does not do proper flow
+ analysis for this case. */
+#define TARGET_SUN_ASM (target_flags & 4)
+
+/* Nonzero if we should do eager peepholes for conditional branch
+ scheduling. */
+#define TARGET_EAGER (target_flags & 8)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { {"fpu", 1}, \
+ {"soft-float", -1}, \
+ {"epilogue", 2}, \
+ {"no-epilogue", -2}, \
+ {"sun-asm", 4}, \
+ {"eager", 8}, \
+ { "", TARGET_DEFAULT}}
+
+#define TARGET_DEFAULT 3
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields. */
+#define BITS_BIG_ENDIAN
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* This is true on the SPARC. */
+#define BYTES_BIG_ENDIAN
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For SPARC we can decide arbitrarily
+ since there are no machine instructions for them. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 64
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 64
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Things that must be doubleword aligned cannot go in the text section,
+ because the linker fails to align the text section enough!
+ Put them in the data section. */
+#define MAX_TEXT_ALIGN 32
+
+#define SELECT_SECTION(T) \
+{ \
+ if (TREE_CODE (T) == VAR_DECL) \
+ { \
+ if (TREE_READONLY (T) && ! TREE_VOLATILE (T) \
+ && DECL_ALIGN (T) <= MAX_TEXT_ALIGN) \
+ text_section (); \
+ else \
+ data_section (); \
+ } \
+ if (*tree_code_type[(int) TREE_CODE (T)] == 'c') \
+ { \
+ if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \
+ || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN) \
+ data_section (); \
+ else \
+ text_section (); \
+ } \
+}
+
+/* Use text section for a constant
+ unless we need more alignment than that offers. */
+#define SELECT_RTX_SECTION(MODE, X) \
+{ \
+ if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN)\
+ text_section (); \
+ else \
+ data_section (); \
+}
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+
+ SPARC has 32 fullword registers and 32 floating point registers. */
+
+#define FIRST_PSEUDO_REGISTER 64
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On SPARC, this includes all the global registers
+ (registers r[0] through r[7]) and the callee return
+ address register, r[15]. */
+#define FIXED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 1, 1, \
+ \
+ 1, 1, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 1, 1, \
+ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On SPARC, ordinary registers hold 32 bits worth;
+ this means both integer and floating point registers. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On SPARC, the cpu registers can hold any mode but the float registers
+ can only hold SFmode or DFmode. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((REGNO) < 32 ? ((GET_MODE_SIZE (MODE) <= 4) ? 1 : ((REGNO) & 1) == 0) : \
+ ((MODE) == SFmode ? 1 : (MODE) == DFmode && ((REGNO) & 1) == 0))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* SPARC pc isn't overloaded on a register that the compiler knows about. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 14
+
+/* Actual top-of-stack address is 92 greater
+ than the contents of the stack pointer register. */
+#define STACK_POINTER_OFFSET 92
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 30
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 30
+
+/* Register in which static-chain is passed to a function. */
+/* ??? */
+#define STATIC_CHAIN_REGNUM 1
+
+
+/* Functions which return large structures get the address
+ to place the wanted value at offset 64 from the frame. */
+#define STRUCT_VALUE_OFFSET 64 /* Used only in other #defines in this file. */
+#define STRUCT_VALUE \
+ gen_rtx (MEM, Pmode, \
+ gen_rtx (PLUS, SImode, stack_pointer_rtx, \
+ gen_rtx (CONST_INT, VOIDmode, STRUCT_VALUE_OFFSET)))
+#define STRUCT_VALUE_INCOMING \
+ gen_rtx (MEM, Pmode, \
+ gen_rtx (PLUS, SImode, frame_pointer_rtx, \
+ gen_rtx (CONST_INT, VOIDmode, STRUCT_VALUE_OFFSET)))
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The SPARC has two kinds of registers, general and floating point. */
+
+enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {{0, 0}, {-1, 0}, {0, -1}, {-1, -1}}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) >= 32 ? FP_REGS : GENERAL_REGS)
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'f' ? FP_REGS : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For SPARC, `I' is used for the range of constants an insn
+ can actually contain.
+ `J' is used for the range which is just zero (since that is R0).
+ `K' is used for the 5-bit operand of a compare insns. */
+
+#define SMALL_INT(X) ((unsigned) (INTVAL (X) + 0x1000) < 0x2000)
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (unsigned) ((VALUE) + 0x1000) < 0x2000 \
+ : (C) == 'J' ? (VALUE) == 0 \
+ : (C) == 'K' ? (unsigned) (VALUE) < 0x20 \
+ : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' && CONST_DOUBLE_LOW ((VALUE)) == 0 \
+ && CONST_DOUBLE_HIGH ((VALUE)) == 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On SPARC, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET -16
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On SPARC, don't define this because there are no push insns. */
+/* #define PUSH_ROUNDING(BYTES) */
+
+/* Offset of first parameter from the argument pointer register value.
+ This is 64 for the ins and locals, plus 4 for the struct-return reg
+ if this function isn't going to use it. */
+#define FIRST_PARM_OFFSET(FNDECL) \
+ (DECL_MODE (DECL_RESULT (fndecl)) == BLKmode \
+ ? STRUCT_VALUE_OFFSET : STRUCT_VALUE_OFFSET + 4)
+
+/* Offset from top-of-stack address to location to store the
+ function parameter if it can't go in a register.
+ Addresses for following parameters are computed relative to this one. */
+#define FIRST_PARM_CALLER_OFFSET(FNDECL) \
+ (STRUCT_VALUE_OFFSET + 4 - STACK_POINTER_OFFSET)
+
+/* When a parameter is passed in a register, stack space is still
+ allocated for it. */
+#define REG_PARM_STACK_SPACE
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 0
+
+/* Some subroutine macros specific to this machine. */
+#define BASE_RETURN_VALUE_REG(MODE) \
+ ((MODE) == SFmode || (MODE) == DFmode ? 32 : 8)
+#define BASE_OUTGOING_VALUE_REG(MODE) \
+ ((MODE) == SFmode || (MODE) == DFmode ? 32 : 24)
+#define BASE_PASSING_ARG_REG(MODE) (8)
+#define BASE_INCOMING_ARG_REG(MODE) (24)
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On SPARC the value is found in the first "output" register. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
+
+/* But the called function leaves it in the first "input" register. */
+
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), BASE_OUTGOING_VALUE_REG (TYPE_MODE (VALTYPE)))
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, BASE_RETURN_VALUE_REG (MODE))
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller.
+ On SPARC, the first "output" reg is used for integer values,
+ and the first floating point register is used for floating point values. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 8 || (N) == 32)
+
+/* 1 if N is a possible register number for function argument passing.
+ On SPARC, these are the "output" registers. */
+
+#define FUNCTION_ARG_REGNO_P(N) ((N) < 14 && (N) > 7)
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On SPARC, this is a single integer, which is a number of words
+ of arguments scanned so far (including the invisible argument,
+ if any, which holds the structure-value-address).
+ Thus 7 or more means all following args should go on the stack. */
+
+#define CUMULATIVE_ARGS int
+
+/* Define the number of register that can hold parameters.
+ This macro is used only in other macro definitions below. */
+#define NPARM_REGS 6
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On SPARC, the offset always starts at 0: the first parm reg is always
+ the same reg. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) / 4 \
+ : (int_size_in_bytes (TYPE) + 3) / 4))
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On SPARC the first six args are normally in registers
+ and the rest are pushed. Any arg that starts within the first 6 words
+ is at least partially passed in a register unless its data type forbids. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+((CUM) < NPARM_REGS \
+ && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \
+ && ((MODE) != BLKmode || (TYPE_ALIGN ((TYPE)) % 32 == 0)) \
+ ? gen_rtx (REG, (MODE), BASE_PASSING_ARG_REG (MODE) + (CUM)) : 0)
+
+/* Define where a function finds its arguments.
+ This is different from FUNCTION_ARG because of register windows. */
+
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+((CUM) < NPARM_REGS \
+ && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \
+ && ((MODE) != BLKmode || (TYPE_ALIGN ((TYPE)) % 32 == 0)) \
+ ? gen_rtx (REG, (MODE), BASE_INCOMING_ARG_REG (MODE) + (CUM)) : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero.
+ Any arg that starts in the first 6 regs but won't entirely fit in them
+ needs partial registers on the Sparc. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+ (((CUM) < NPARM_REGS \
+ && ((TYPE)==0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \
+ && ((MODE) != BLKmode || (TYPE_ALIGN ((TYPE)) % 32 == 0)) \
+ && ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) - NPARM_REGS > 0) \
+ ? (NPARM_REGS - (CUM)) \
+ : 0)
+
+/* Output the label for a function definition. */
+
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+{ \
+ extern tree double_type_node, float_type_node; \
+ if (TREE_TYPE (DECL) == float_type_node) \
+ fprintf (FILE, "\t.proc 6\n"); \
+ else if (TREE_TYPE (DECL) == double_type_node) \
+ fprintf (FILE, "\t.proc 7\n"); \
+ else if (TREE_TYPE (DECL) == void_type_node) \
+ fprintf (FILE, "\t.proc 0\n"); \
+ else fprintf (FILE, "\t.proc 1\n"); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+}
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
+ of memory. If any fpu reg is used in the function, we allocate
+ such a block here, at the bottom of the frame, just in case it's needed.
+
+ If this function is a leaf procedure, then we may choose not
+ to do a "save" insn. Currently we do this only if it touches
+ the "output" registers. The "local" and "input" registers
+ are off limits. It might be better to allow one such register
+ to go to the stack, but I doubt it. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int current_function_pretend_args_size; \
+ extern int frame_pointer_needed; \
+ int fsize = (((SIZE) + 7 - STARTING_FRAME_OFFSET) & -8); \
+ int actual_fsize; \
+ int n_fregs = 0, i; \
+ int n_iregs = 64; \
+ for (i = 32; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ n_fregs++; \
+ for (i = 16; i < 32; i++) \
+ if (regs_ever_live[i]) { n_iregs = 96; break; } \
+ fprintf (FILE, "\t!#PROLOGUE# 0\n"); \
+ actual_fsize = fsize + n_iregs + (n_fregs*4+7 & -8); \
+ fsize += current_function_pretend_args_size+7 & -8; \
+ actual_fsize += current_function_pretend_args_size+7 & -8; \
+ if (actual_fsize < 4096) \
+ fprintf (FILE, "\tsave %%sp,-%d,%%sp\n", actual_fsize); \
+ else \
+ { \
+ fprintf (FILE, "\tsethi %%hi(0x%x),%%g1\n\tadd %%g1,%%lo(0x%x),%%g1\n", \
+ -actual_fsize, -actual_fsize); \
+ fprintf (FILE, "\tsave %%sp,%%g1,%%sp\n"); \
+ } \
+ fprintf (FILE, "\t!#PROLOGUE# 1\n"); \
+ if (n_fregs) \
+ { \
+ for (i = 32, n_fregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ { \
+ if (regs_ever_live[i+1] && ! call_used_regs[i+1]) \
+ fprintf (FILE, "\tstd %s,[%%sp+0x%x]\n", \
+ reg_names[i], n_iregs + 4 * n_fregs), \
+ n_fregs += 2, i += 1; \
+ else \
+ fprintf (FILE, "\tstf %s,[%%sp+0x%x]\n", \
+ reg_names[i], n_iregs + 4 * n_fregs++); \
+ } \
+ } \
+ if (regs_ever_live[32]) \
+ fprintf (FILE, "\tst %s,[%%fp-16]\n\tst %s,[%%fp-12]\n", \
+ reg_names[0], reg_names[0]); \
+}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tsethi %%hi(LP%d),%%o0\n\tcall mcount\n\tor %%lo(LP%d),%%o0,%%o0\n", \
+ (LABELNO), (LABELNO))
+
+/* Output assembler code to FILE to initialize this source file's
+ basic block profiling info, if that has not already been done. */
+
+#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tsethi %%hi(LPBX0),%%o0\n\tld [%%lo(LPBX0)+%%o0],%%o1\n\ttst %%o1\n\tbne LPY%d\n\tadd %%o0,%%lo(LPBX0),%%o0\n\tcall ___bb_init_func\n\tnop\nLPY%d:\n", \
+ (LABELNO), (LABELNO))
+
+/* Output assembler code to FILE to increment the entry-count for
+ the BLOCKNO'th basic block in this source file. */
+
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+{ \
+ int blockn = (BLOCKNO); \
+ fprintf (FILE, "\tsethi %%hi(LPBX2+%d),%%g1\n\tld [%%lo(LPBX2+%d)+%%g1],%%g2\n\
+\tadd %%g2,1,%%g2\n\tst %%g2,[%%lo(LPBX2+%d)+%%g1]\n", \
+ 4 * blockn, 4 * blockn, 4 * blockn); \
+ CC_STATUS_INIT; /* We have clobbered %g1. Also %g2. */ \
+}
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+extern int may_call_alloca;
+extern int current_function_pretend_args_size;
+
+#define EXIT_IGNORE_STACK \
+ (get_frame_size () != 0 \
+ || may_call_alloca || current_function_pretend_args_size)
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+/* This declaration is needed due to traditional/ANSI
+ incompatibilities which cannot be #ifdefed away
+ because they occur inside of macros. Sigh. */
+extern union tree_node *current_function_decl;
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int may_call_alloca; \
+ extern int current_function_pretend_args_size; \
+ extern int max_pending_stack_adjust; \
+ extern int frame_pointer_needed; \
+ int fsize = (((SIZE) + 7 - STARTING_FRAME_OFFSET) & -8); \
+ int actual_fsize; \
+ int n_fregs = 0, i; \
+ int n_iregs = 64; \
+ for (i = 32, n_fregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ n_fregs++; \
+ for (i = 16; i < 32; i++) \
+ if (regs_ever_live[i]) { n_iregs = 96; break; } \
+ actual_fsize = fsize + n_iregs + (n_fregs*4+7 & -8); \
+ actual_fsize += current_function_pretend_args_size+7 & -8; \
+ fsize += current_function_pretend_args_size+7 & -8; \
+ if (n_fregs) \
+ { \
+ char *base; \
+ int offset; \
+ if (fsize < 4096) \
+ { base = "%fp"; offset = n_iregs - actual_fsize; } \
+ else \
+ { base = "%g1"; offset = n_iregs; \
+ if (fsize < 4096) \
+ fprintf (FILE, "sethi %%hi(0x%x),%%g1\n\tadd %%g1,%%lo(0x%x),%%g1\n\tadd %%fp,%%g1,%%g1\n", -actual_fsize, -actual_fsize);\
+ } \
+ for (i = 32, n_fregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ { \
+ if (regs_ever_live[i+1] && ! call_used_regs[i+1]) \
+ fprintf (FILE, "\tldd [%s%+d],%s\n", \
+ base, offset + 4 * n_fregs, \
+ reg_names[i]), \
+ n_fregs += 2, i += 1; \
+ else \
+ fprintf (FILE, "\tldf [%s%+d],%s\n", \
+ base, offset + 4 * n_fregs++, \
+ reg_names[i]); \
+ } \
+ } \
+ fprintf (FILE, "\tret\n\trestore\n"); \
+}
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+{ int offset = -1; \
+ rtx regs = stack_pointer_rtx; \
+ if (ADDR == frame_pointer_rtx) \
+ offset = 0; \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx \
+ && GET_CODE (XEXP (ADDR, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (ADDR, 1)); \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 0) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 1); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ else if (GET_CODE (ADDR) == PLUS && XEXP (ADDR, 1) == frame_pointer_rtx) \
+ { rtx other_reg = XEXP (ADDR, 0); \
+ offset = 0; \
+ regs = gen_rtx (PLUS, Pmode, stack_pointer_rtx, other_reg); } \
+ if (offset >= 0) \
+ { int regno; \
+ extern char call_used_regs[]; \
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ offset += 4; \
+ offset -= 4; \
+ ADDR = plus_constant (regs, offset + (DEPTH)); } }
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 0x20) < 32 || (unsigned) (reg_renumber[REGNO] ^ 0x20) < 32)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the SPARC, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
+
+ Anything but a CONST_DOUBLE can be made to work. */
+
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) != CONST_DOUBLE)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (((unsigned) REGNO (X)) - 32 >= 32)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (((unsigned) REGNO (X)) - 32 >= 32)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ On SPARC, the actual legitimate addresses must be REG+REG or REG+SMALLINT.
+ But we can treat a SYMBOL_REF as legitimate if it is part of this
+ function's constant-pool, because such addresses can actually
+ be output as REG+SMALLINT.
+
+ Try making SYMBOL_REF (and other things which are CONSTANT_ADDRESS_P)
+ a legitimate address, regardless. Because the only insns which can use
+ memory are load or store insns, the added hair in the machine description
+ is not that bad. It should also speed up the compiler by halving the number
+ of insns it must manage for each (MEM (SYMBOL_REF ...)) involved. */
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (GET_CODE (X) == REG) \
+ { if (REG_OK_FOR_BASE_P (X)) goto ADDR; } \
+ else if (GET_CODE (X) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ { \
+ if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
+ goto ADDR; \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && INTVAL (XEXP (X, 1)) >= -0x1000 \
+ && INTVAL (XEXP (X, 1)) < 0x1000) \
+ goto ADDR; \
+ } \
+ else if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ { \
+ if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
+ goto ADDR; \
+ if (GET_CODE (XEXP (X, 0)) == CONST_INT \
+ && INTVAL (XEXP (X, 0)) >= -0x1000 \
+ && INTVAL (XEXP (X, 0)) < 0x1000) \
+ goto ADDR; \
+ } \
+ } \
+ else if (CONSTANT_ADDRESS_P (X)) \
+ goto ADDR; \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output. */
+
+/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ copy_to_mode_reg (SImode, XEXP (X, 1))); \
+ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ copy_to_mode_reg (SImode, XEXP (X, 0))); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ force_operand (XEXP (X, 0), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ force_operand (XEXP (X, 1), 0)); \
+ if (GET_CODE (x) == SYMBOL_REF) \
+ (X) = copy_to_reg (X); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; }
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the SPARC this is never true. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* We assume that the store-condition-codes instructions store 0 for false
+ and some other value for true. This is the value stored for true. */
+
+#define STORE_FLAG_VALUE 1
+
+/* When a prototype says `char' or `short', really pass an `int'. */
+#define PROMOTE_PROTOTYPES
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE SImode
+
+/* Define this if addresses of constant functions
+ shouldn't be put through pseudo regs where they can be cse'd.
+ Desirable on machines where ordinary constants are expensive
+ but a CALL with constant address is cheap. */
+#define NO_FUNCTION_CSE
+
+/* Define subroutines to call to handle multiply and divide.
+ Use the subroutines that Sun's library provides.
+ The `*' prevents an underscore from being prepended by the compiler. */
+
+#define DIVSI3_LIBCALL "*.div"
+#define UDIVSI3_LIBCALL "*.udiv"
+#define MODSI3_LIBCALL "*.rem"
+#define UMODSI3_LIBCALL "*.urem"
+#define MULSI3_LIBCALL "*.mul"
+#define UMULSI3_LIBCALL "*.umul"
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (INTVAL (RTX) < 0x1000 && INTVAL (RTX) >= -0x1000) return 0; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 2; \
+ case CONST_DOUBLE: \
+ return 4;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* This holds the value sourcing %hi(%g1). We keep this info
+ around so that mem/mem ops, such as increment and decrement,
+ etc, can be performed reasonably. */
+#define CC_STATUS_MDEP rtx
+
+/* Nonzero if the results of the previous comparison are
+ in the floating point condition code register. */
+
+#define CC_IN_FCCR 04000
+
+/* Nonzero if the results of the previous comparison are
+ int the coprocessor's condition code register. */
+
+#define CC_IN_CCCR 010000
+
+/* Nonzero if we know (easily) that floating point register f0
+ (f1) contains the value 0. */
+#define CC_F0_IS_0 020000
+#define CC_F1_IS_0 040000
+
+/* Nonzero if we know the value of %hi(%g1). */
+#define CC_KNOW_HI_G1 0100000
+
+#define CC_STATUS_MDEP_INIT (cc_status.mdep = 0)
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (GET_CODE (EXP) == SET) \
+ { if (SET_DEST (EXP) == cc0_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (EXP); \
+ cc_status.value2 = SET_SRC (EXP); } \
+ else if (GET_CODE (SET_SRC (EXP)) == CALL) \
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (SET_DEST (EXP)) == REG) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (EXP), cc_status.value2)) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (EXP)) == MEM) \
+ { rtx x = cc_status.mdep; int know = cc_status.flags & CC_KNOW_HI_G1; \
+ CC_STATUS_INIT; \
+ if (x && know) \
+ { cc_status.mdep = x; cc_status.flags |= CC_KNOW_HI_G1; } \
+ } \
+ } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET) \
+ { if (SET_DEST (XVECEXP (EXP, 0, 0)) == cc0_rtx) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \
+ cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); \
+ } \
+ else if (GET_CODE (SET_SRC (XVECEXP (EXP, 0, 0))) == CALL) \
+ { /* all bets are off */ CC_STATUS_INIT; } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == REG) \
+ { if (cc_status.value1 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value1)) \
+ cc_status.value1 = 0; \
+ if (cc_status.value2 \
+ && reg_overlap_mentioned_p (SET_DEST (XVECEXP (EXP, 0, 0)), cc_status.value2)) \
+ cc_status.value2 = 0; \
+ } \
+ else if (GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) == MEM) \
+ { rtx x = cc_status.mdep; int know = cc_status.flags & CC_KNOW_HI_G1; \
+ CC_STATUS_INIT; \
+ if (x && know) \
+ { cc_status.mdep = x; cc_status.flags |= CC_KNOW_HI_G1; } \
+ } \
+ } \
+ else if (GET_CODE (EXP) == PARALLEL) \
+ /* insn-peep has changed this insn beyond recognition
+ by NOTICE_UPDATE_CC. However, we know it is either
+ a call or a branch with a delay slot filled, so we can
+ give up on knowing condition codes in any case. */ \
+ { CC_STATUS_INIT; } \
+ else if (GET_CODE (EXP) == CALL) \
+ { /* all bets are off */ CC_STATUS_INIT; } \
+}
+
+#define OUTPUT_JUMP(NORMAL, NO_OV, FLOAT) \
+{ if (cc_prev_status.flags & CC_IN_FCCR) \
+ return FLOAT; \
+ if (cc_prev_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(file)
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ""
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ""
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", \
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7", \
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7", \
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", \
+ "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", \
+ "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", \
+ "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"} \
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* On Sun 4, this limit is 2048. We use 1500 to be safe,
+ since the length can run past this up to a continuation point. */
+#define DBX_CONTIN_LENGTH 1500
+
+/* This is how to output a note to DBX telling it the line number
+ to which the following sequence of instructions corresponds.
+
+ This is needed for SunOS 4.0, and should not hurt for 3.2
+ versions either. */
+#define ASM_OUTPUT_SOURCE_LINE(file, line) \
+ { static int sym_lineno = 1; \
+ fprintf (file, ".stabn 68,0,%d,LM%d\nLM%d:\n", \
+ line, sym_lineno, sym_lineno); \
+ sym_lineno += 1; }
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.double 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "\t.double 0r%.20e\n", (VALUE)))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.single 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : fprintf (FILE, "\t.single 0r%.20e\n", (VALUE)))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.half "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.word L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ (SPARC does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.skip %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".global ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fputs ("\n.common ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,\"bss\"\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\n.reserve ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u,\"bss\"\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On SPARC, the CODE can be `r', meaning this is a register-only operand
+ and an immediate zero should be represented as `r0'.
+ It can also be `m', meaning that X is a memory reference but print
+ its address as a non-memory operand.
+
+ Codes C, N, F, I, and U are used for printing the opcodes of conditional
+ branches. C prints the opcode for a given condition; N the negated opcode.
+ F prints the negated floating point opcode (different because of nans).
+ I prints the opcode that ignores the overflow bit, and U its negation. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if ((CODE) == 'm') \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == MEM) \
+ { \
+ fputc ('[', FILE); \
+ output_address (XEXP (X, 0)); \
+ fputc (']', FILE); \
+ } \
+ else if (GET_CODE (X) == CONST_DOUBLE) \
+ abort (); \
+ else if ((CODE) == 'r' && (X) == const0_rtx) \
+ fprintf (FILE, "%%g0"); \
+ else if ((CODE) == 'C') switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("e", FILE); break; \
+ case NE: fputs ("ne", FILE); break; \
+ case GT: fputs ("g", FILE); break; \
+ case GE: fputs ("ge", FILE); break; \
+ case LT: fputs ("l", FILE); break; \
+ case LE: fputs ("le", FILE); break; \
+ case GTU: fputs ("gu", FILE); break; \
+ case GEU: fputs ("geu", FILE); break; \
+ case LTU: fputs ("lu", FILE); break; \
+ case LEU: fputs ("leu", FILE); break; \
+ } \
+ else if ((CODE) == 'I') switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("e", FILE); break; \
+ case NE: fputs ("ne", FILE); break; \
+ case GE: fputs ("pos", FILE); break; \
+ case LT: fputs ("neg", FILE); break; \
+ default: \
+ abort (); \
+ } \
+ else if ((CODE) == 'U') switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("ne", FILE); break; \
+ case NE: fputs ("e", FILE); break; \
+ case GE: fputs ("neg", FILE); break; \
+ case LT: fputs ("pos", FILE); break; \
+ default: \
+ abort (); \
+ } \
+ else if ((CODE) == 'N') switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("ne", FILE); break; \
+ case NE: fputs ("e", FILE); break; \
+ case GT: fputs ("le", FILE); break; \
+ case GE: fputs ("l", FILE); break; \
+ case LT: fputs ("ge", FILE); break; \
+ case LE: fputs ("g", FILE); break; \
+ case GTU: fputs ("leu", FILE); break; \
+ case GEU: fputs ("lu", FILE); break; \
+ case LTU: fputs ("geu", FILE); break; \
+ case LEU: fputs ("gu", FILE); break; \
+ } \
+ else if ((CODE) == 'F') switch (GET_CODE (X)) \
+ { \
+ case EQ: fputs ("ne", FILE); break; \
+ case NE: fputs ("e", FILE); break; \
+ case GT: fputs ("ule", FILE); break; \
+ case GE: fputs ("ul", FILE); break; \
+ case LT: fputs ("uge", FILE); break; \
+ case LE: fputs ("ug", FILE); break; \
+ default: abort (); \
+ } \
+ else { output_addr_const (FILE, X); }}
+
+/* Print a memory address as an operand to reference that memory location. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx base, index = 0; \
+ int offset = 0; \
+ register rtx addr = ADDR; \
+ if (GET_CODE (addr) == REG) \
+ { \
+ fprintf (FILE, "%s", reg_names[REGNO (addr)]); \
+ } \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);\
+ else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\
+ else \
+ base = XEXP (addr, 0), index = XEXP (addr, 1); \
+ fprintf (FILE, "%s", reg_names[REGNO (base)]); \
+ if (index == 0) \
+ fprintf (FILE, "%+d", offset); \
+ else \
+ fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
+ } \
+ else \
+ { \
+ output_addr_const (FILE, addr); \
+ } \
+}
+
diff --git a/gcc-1.40/config/tm-spur.h b/gcc-1.40/config/tm-spur.h
new file mode 100644
index 0000000..485b07f
--- /dev/null
+++ b/gcc-1.40/config/tm-spur.h
@@ -0,0 +1,1033 @@
+/* Definitions of target machine for GNU compiler, for SPUR chip.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Note that some other tm- files include this one and then override
+ many of the definitions that relate to assembler syntax. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dspur"
+
+/* Print subsidiary information on the compiler version in use. */
+#define TARGET_VERSION fprintf (stderr, " (spur)");
+
+/* Run-time compilation parameters selecting different hardware subsets.
+
+ On the SPUR, we don't yet need any. */
+
+extern int target_flags;
+
+/* Nonzero if we should generate code to use the fpu. */
+#define TARGET_FPU (target_flags & 1)
+
+/* Nonzero if we should expand constant shifts into series of shift
+ instructions. */
+#define TARGET_EXPAND_SHIFTS (target_flags & 2)
+
+/* Nonzero if we should generate long jumps for compares. */
+#define TARGET_LONG_JUMPS (target_flags & 4)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { {"fpu", 1}, \
+ {"soft-float", -1}, \
+ {"expand-shifts", 2}, \
+ {"lib-shifts", -2}, \
+ {"long-jumps", 4}, \
+ {"short-jumps", -4}, \
+ { "", TARGET_DEFAULT}}
+
+#define TARGET_DEFAULT 0
+
+/* target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is a moot question on the SPUR due to the lack of bit-field insns. */
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on SPUR. */
+/* #define BYTES_BIG_ENDIAN */
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* For SPUR we can decide arbitrarily
+ since there are no machine instructions for them. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 64
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY 64
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 32
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 64
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+
+ SPUR has 32 fullword registers and 15 floating point registers. */
+
+#define FIRST_PSEUDO_REGISTER 47
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On SPUR, this includes all the global registers
+ and the callee return address register. */
+#define FIXED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, \
+ 1, 0, 0, 0, 0, 0, \
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS \
+ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, \
+ 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ On SPUR, ordinary registers hold 32 bits worth;
+ a single floating point register is always enough for
+ anything that can be stored in them at all. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((REGNO) >= 32 ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On SPUR, the cpu registers can hold any mode but the float registers
+ can hold only SFmode or DFmode. And they can't hold anything if use
+ of hardware floating point is disabled. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (((REGNO) < 32 && (GET_MODE_SIZE (MODE) <= 4 || (REGNO) < 31)) \
+ || (TARGET_FPU && ((MODE) == SFmode || (MODE) == DFmode)))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == SFmode || (MODE1) == DFmode) \
+ == ((MODE2) == SFmode || (MODE2) == DFmode))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* SPUR pc isn't overloaded on a register that the compiler knows about. */
+/* #define PC_REGNUM */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 4
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 25
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 25
+
+/* Register in which static-chain is passed to a function. */
+/* ??? */
+#define STATIC_CHAIN_REGNUM 8
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 27
+#define STRUCT_VALUE_INCOMING_REGNUM 11
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The 68000 has two kinds of registers, hence four classes. */
+
+enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {{0, 0}, {-1, 0}, {0, 0x7fff}, {-1, 0x7fff}}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) >= 32 ? FP_REGS : GENERAL_REGS)
+
+/* The class value for index registers, and the one for base regs. */
+#define INDEX_REG_CLASS GENERAL_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) \
+ ((C) == 'f' ? FP_REGS : NO_REGS)
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C.
+
+ For SPUR, `I' is used for the range of constants an insn
+ can actually contain.
+ `J' is used for the range which is just zero (since that is R0).
+ `K' is used for the 5-bit operand of a compare insns. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? (unsigned) ((VALUE) + 0x2000) < 0x4000 \
+ : (C) == 'J' ? (VALUE) == 0 \
+ : (C) == 'K' ? (unsigned) (VALUE) < 0x20 \
+ : 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' && CONST_DOUBLE_LOW ((VALUE)) == 0 \
+ && CONST_DOUBLE_HIGH ((VALUE)) == 0)
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On SPUR, this is the size of MODE in words,
+ except in the FP regs, where a single reg is always enough. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? 1 \
+ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On SPUR, don't define this because there are no push insns. */
+/* #define PUSH_ROUNDING(BYTES) */
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 0
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On SPUR the value is found in the second "output" register. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 27)
+
+/* But the called function leaves it in the second "input" register. */
+
+#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 11)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 27)
+
+/* 1 if N is a possible register number for a function value
+ as seen by the caller.
+ On SPUR, the first "output" reg is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 27)
+
+/* 1 if N is a possible register number for function argument passing.
+ On SPUR, these are the "output" registers. */
+
+#define FUNCTION_ARG_REGNO_P(N) ((N) < 32 && (N) > 26)
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On SPUR, this is a single integer, which is a number of words
+ of arguments scanned so far (including the invisible argument,
+ if any, which holds the structure-value-address).
+ Thus 5 or more means all following args should go on the stack. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On SPUR, the offset normally starts at 0, but starts at 4 bytes
+ when the function gets a structure-value-address as an
+ invisible first argument. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = ((FNTYPE) != 0 && aggregate_value_p ((FNTYPE))))
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) / 4 \
+ : (int_size_in_bytes (TYPE) + 3) / 4))
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On SPUR the first five words of args are normally in registers
+ and the rest are pushed. But any arg that won't entirely fit in regs
+ is pushed. Also, any non-word-aligned structure is pushed. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+(5 >= ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) \
+ && ((MODE) != BLKmode || (TYPE_ALIGN ((TYPE)) % 32 == 0)) \
+ ? gen_rtx (REG, (MODE), 27 + (CUM)) \
+ : 0)
+
+/* Define where a function finds its arguments.
+ This is different from FUNCTION_ARG because of register windows. */
+
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+(5 >= ((CUM) \
+ + ((MODE) == BLKmode \
+ ? (int_size_in_bytes (TYPE) + 3) / 4 \
+ : (GET_MODE_SIZE (MODE) + 3) / 4)) \
+ && ((MODE) != BLKmode || (TYPE_ALIGN ((TYPE)) % 32 == 0)) \
+ ? gen_rtx (REG, (MODE), 11 + (CUM)) \
+ : 0)
+
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of registers used.
+ For args passed entirely in registers or entirely in memory, zero. */
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+/* On spur, move-double insns between fpu and cpu need an 8-byte block
+ of memory. If any fpu reg is used in the function, we allocate
+ such a block here, at the bottom of the frame, just in case it's needed. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int current_function_pretend_args_size; \
+ int fsize = ((SIZE) + 7) & ~7; \
+ int nregs, i, fp_used = 0; \
+ for (i = 32, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ { \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ nregs++; \
+ if (regs_ever_live[i]) fp_used = 1; \
+ } \
+ if (fp_used) fsize += 8; \
+ fprintf (FILE, "0:\trd_special r24,pc\n"); \
+ fprintf (FILE, "\tand r24,r24,$~0x3\n"); \
+ fprintf (FILE, "\tadd_nt r25,r4,$%d\n", \
+ - current_function_pretend_args_size); \
+ if (fsize + nregs != 0 || current_function_pretend_args_size > 0)\
+ { \
+ int n = - fsize - nregs * 16; \
+ if (n >= -8192) \
+ fprintf (FILE, "\tadd_nt r4,r25,$%d\n", n); \
+ else \
+ { \
+ fprintf (FILE, "\tadd_nt r4,r25,$-8192\n"); \
+ n += 8192; \
+ while (n < -8192) \
+ fprintf (FILE, "\tadd_nt r4,r4,$-8192\n"), n += 8192; \
+ if (n != 0) \
+ fprintf (FILE, "\tadd_nt r4,r4,$%d\n", n); \
+ } \
+ } \
+ for (i = 32, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ { \
+ fprintf (FILE, "\tst_ext1 %s,r4,$%d\n", \
+ reg_names[i], 8 * nregs++); \
+ fprintf (FILE, "\tst_ext2 %s,r4,$%d\n", \
+ reg_names[i], 8 * nregs++); \
+ } \
+}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ abort ();
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+extern int may_call_alloca;
+extern int current_function_pretend_args_size;
+
+#define EXIT_IGNORE_STACK \
+ (get_frame_size () != 0 \
+ || may_call_alloca || current_function_pretend_args_size)
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE.
+
+ The function epilogue should not depend on the current stack pointer!
+ It should use the frame pointer only. This is mandatory because
+ of alloca; we also take advantage of it to omit stack adjustments
+ before returning. */
+
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ \
+ extern char call_used_regs[]; \
+ extern int may_call_alloca; \
+ extern int current_function_pretend_args_size; \
+ int fsize = ((SIZE) + 7) & ~7; \
+ int nregs, i, fp_used = 0; \
+ for (i = 32, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ { \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ nregs++; \
+ if (regs_ever_live[i]) fp_used = 1; \
+ } \
+ if (fp_used) fsize += 8; \
+ if (nregs != 0) \
+ { \
+ fprintf (FILE, "\tadd_nt r4,r25,$%d\n", - fsize - nregs * 16); \
+ for (i = 32, nregs = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ if (regs_ever_live[i] && ! call_used_regs[i]) \
+ { \
+ fprintf (FILE, "\tld_ext1 %s,r4,$%d\n\tnop\n", \
+ reg_names[i], 8 * nregs++); \
+ fprintf (FILE, "\tld_ext2 %s,r4,$%d\n\tnop\n", \
+ reg_names[i], 8 * nregs++); \
+ } \
+ } \
+ if (fsize != 0 || nregs != 0 || may_call_alloca \
+ || current_function_pretend_args_size > 0) \
+ fprintf (FILE, "\tadd_nt r4,r25,$%d\n", \
+ current_function_pretend_args_size); \
+ fprintf (FILE, "\treturn r10,$8\n\tnop\n"); \
+}
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) abort ();
+
+/* Addressing modes, and classification of registers for them. */
+
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
+
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
+#define REGNO_OK_FOR_FP_P(REGNO) \
+(((REGNO) ^ 0x20) < 14 || (unsigned) (reg_renumber[REGNO] ^ 0x20) < 14)
+
+/* Now macros that check whether X is a register and also,
+ strictly, whether it is in a specified class.
+
+ These macros are specific to the SPUR, and may be used only
+ in code for printing assembler insns and in conditions for
+ define_optimization. */
+
+/* 1 if X is an fp register. */
+
+#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* Recognize any constant value that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) \
+ ((GET_CODE (X) == CONST_INT \
+ && (unsigned) (INTVAL (X) + 0x2000) < 0x4000)\
+ || (GET_CODE (X) == SYMBOL_REF && (X)->unchanging))
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) (((unsigned) REGNO (X)) - 32 >= 14)
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) (((unsigned) REGNO (X)) - 32 >= 14)
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ On SPUR, the actual legitimate addresses must be REG+SMALLINT or REG+REG.
+ Actually, REG+REG is not legitimate for stores, so
+ it is obtained only by combination on loads.
+ We can treat a SYMBOL_REF as legitimate if it is part of this
+ function's constant-pool, because such addresses can actually
+ be output as REG+SMALLINT. */
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ if (GET_CODE (X) == REG \
+ && REG_OK_FOR_BASE_P (X)) \
+ goto ADDR; \
+ if (GET_CODE (X) == SYMBOL_REF && (X)->unchanging) \
+ goto ADDR; \
+ if (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ { \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && INTVAL (XEXP (X, 1)) >= -0x2000 \
+ && INTVAL (XEXP (X, 1)) < 0x2000) \
+ goto ADDR; \
+ } \
+}
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output. */
+
+/* On SPUR, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ copy_to_mode_reg (SImode, XEXP (X, 1))); \
+ if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ copy_to_mode_reg (SImode, XEXP (X, 0))); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 1), \
+ force_operand (XEXP (X, 0), 0)); \
+ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT) \
+ (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
+ force_operand (XEXP (X, 1), 0)); \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; }
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the SPUR this is never true. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this if the tablejump instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+/* #define CASE_VECTOR_PC_RELATIVE */
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 0
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 1
+
+/* This is BSD, so it wants DBX format. */
+#define DBX_DEBUGGING_INFO
+
+/* Do not break .stabs pseudos into continuations. */
+#define DBX_CONTIN_LENGTH 0
+
+/* Don't try to use the `x' type-cross-reference character in DBX data.
+ Also has the consequence of putting each struct, union or enum
+ into a separate .stabs, containing only cross-refs to the others. */
+#define DBX_NO_XREFS
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE SImode
+
+/* Define this if addresses of constant functions
+ shouldn't be put through pseudo regs where they can be cse'd.
+ Desirable on machines where ordinary constants are expensive
+ but a CALL with constant address is cheap. */
+#define NO_FUNCTION_CSE
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (INTVAL (RTX) < 0x2000 && INTVAL (RTX) >= -0x2000) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 2; \
+ case CONST_DOUBLE: \
+ return 4;
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). */
+
+/* (None are needed on SPUR.) */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+/* The SPUR does not really have a condition code. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ CC_STATUS_INIT; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE)
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON ""
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF ""
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", \
+ "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", \
+ "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \
+ "r30", "r31", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", \
+ "f10", "f11", "f12", "f13", "f14" }
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double %.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.single %.12e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output code to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tadd_nt r4,r4,$-4\n\tst_32 %s,r4,$0\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tld_32 %s,r4,$0\n\tadd_nt r4,r4,$4\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ (SPUR does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print operand X (an rtx) in assembler syntax to file FILE.
+ CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
+ For `%' followed by punctuation, CODE is the punctuation and X is null.
+
+ On SPUR, the CODE can be `r', meaning this is a register-only operand
+ and an immediate zero should be represented as `r0'. */
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE) \
+ abort (); \
+ else if ((CODE) == 'r' && (X) == const0_rtx) \
+ fprintf (FILE, "r0"); \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+/* Print a memory address as an operand to reference that memory location. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx base, index = 0; \
+ int offset = 0; \
+ register rtx addr = ADDR; \
+ if (GET_CODE (addr) == REG) \
+ { \
+ fprintf (FILE, "%s,$0", reg_names[REGNO (addr)]); \
+ } \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);\
+ else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) \
+ offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);\
+ else \
+ base = XEXP (addr, 0), index = XEXP (addr, 1); \
+ fprintf (FILE, "%s,", reg_names[REGNO (base)]); \
+ if (index == 0) \
+ fprintf (FILE, "$%d", offset); \
+ else \
+ fprintf (FILE, "%s,", reg_names[REGNO (index)]); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "r24,$("); \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "-0b)"); \
+ } \
+}
diff --git a/gcc-1.40/config/tm-sun2.h b/gcc-1.40/config/tm-sun2.h
new file mode 100644
index 0000000..6ae8d86
--- /dev/null
+++ b/gcc-1.40/config/tm-sun2.h
@@ -0,0 +1,67 @@
+/* Definitions of target machine for GNU compiler. Sun 68010 version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 0 means 68000 with no 68881. */
+
+#define TARGET_DEFAULT 0
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#define CPP_SPEC "%{m68881:-D__HAVE_68881__} \
+%{!ansi:%{m68020:-Dmc68020}%{mc68020:-Dmc68020}%{!mc68020:%{!m68020:-Dmc68010}}}"
+
+/* -m68020 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68020:-mc68020}%{mc68020:-mc68020}%{!mc68020:%{!m68020:-mc68010}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dunix"
+
+/* Prevent error on `-sun2' and `-target sun2' options. */
+
+#define CC1_SPEC "%{sun2:} %{target:}"
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) (!strcmp (STR, "target"))
+
+/* Specify what to link with. */
+
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} "
+
+/* Alignment of field after `int : 0' in a structure. */
+
+#undef EMPTY_FIELD_BOUNDARY
+#define EMPTY_FIELD_BOUNDARY 16
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
diff --git a/gcc-1.40/config/tm-sun2os4.h b/gcc-1.40/config/tm-sun2os4.h
new file mode 100644
index 0000000..17b4c49
--- /dev/null
+++ b/gcc-1.40/config/tm-sun2os4.h
@@ -0,0 +1,57 @@
+/* Definitions of target machine for GNU compiler. For Sun 2 running Sunos 4.
+ Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-sun2.h"
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{!e*:-e start} -dc -dp %{g:-Bstatic} %{static:-Bstatic} %{-Bstatic}"
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.double 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "\t.long 0x80000000,0\n") \
+ : fprintf (FILE, "\t.double 0r%.20e\n", (VALUE)))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.single 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "\t.long 0x80000000\n") \
+ : fprintf (FILE, "\t.single 0r%.20e\n", (VALUE)))
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "#0r-0.0") \
+ : fprintf (FILE, "#0r%.9g", (VALUE)))
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "#0r-0.0") \
+ : fprintf (FILE, "#0r%.20g", (VALUE)))
diff --git a/gcc-1.40/config/tm-sun3-nfp.h b/gcc-1.40/config/tm-sun3-nfp.h
new file mode 100644
index 0000000..0a6005d
--- /dev/null
+++ b/gcc-1.40/config/tm-sun3-nfp.h
@@ -0,0 +1,5 @@
+/* Define target machine as a Sun 3 with no 68881. */
+
+#define TARGET_DEFAULT 5
+
+#include "tm-sun3.h"
diff --git a/gcc-1.40/config/tm-sun3.h b/gcc-1.40/config/tm-sun3.h
new file mode 100644
index 0000000..90f54b0
--- /dev/null
+++ b/gcc-1.40/config/tm-sun3.h
@@ -0,0 +1,186 @@
+/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This comment is here to see if it will keep Sun's cpp from dying. */
+
+#include "tm-m68k.h"
+
+/* See tm-m68k.h. 7 means 68020 with 68881. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+#endif
+
+/* Define __HAVE_FPA__ or __HAVE_68881__ in preprocessor,
+ according to the -m flags.
+ This will control the use of inline 68881 insns in certain macros.
+ Also inform the program which CPU this is for. */
+
+#if TARGET_DEFAULT & 02
+
+/* -m68881 is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#else
+#if TARGET_DEFAULT & 0100
+
+/* -mfpa is the default */
+#define CPP_SPEC \
+"%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#else
+
+/* -msoft-float is the default */
+#define CPP_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
+%{!ansi:%{m68000:-Dmc68010}%{mc68000:-Dmc68010}%{!mc68000:%{!m68000:-Dmc68020}}}"
+
+#endif
+#endif
+
+/* Prevent error on `-sun3' and `-target sun3' options. */
+
+#define CC1_SPEC "%{sun3:} %{target:}"
+
+/* These compiler options take an argument. We ignore -target for now. */
+
+#define WORD_SWITCH_TAKES_ARG(STR) (!strcmp (STR, "target"))
+
+/* -m68000 requires special flags to the assembler. */
+
+#define ASM_SPEC \
+ "%{m68000:-mc68010}%{mc68000:-mc68010}%{!mc68000:%{!m68000:-mc68020}}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dunix"
+
+/* STARTFILE_SPEC to include sun floating point initialization
+ This is necessary (tr: Sun does it) for both the m68881 and the fpa
+ routines.
+ Note that includes knowledge of the default specs for gcc, ie. no
+ args translates to the same effect as -m68881
+ I'm not sure what would happen below if people gave contradictory
+ arguments (eg. -msoft-float -mfpa) */
+
+#if TARGET_DEFAULT & 0100
+/* -mfpa is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{m68881:Mcrt1.o%s} \
+ %{msoft-float:Fcrt1.o%s} \
+ %{!m68881:%{!msoft-float:Wcrt1.o%s}}"
+#else
+#if TARGET_DEFAULT & 2
+/* -m68881 is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{mfpa:Wcrt1.o%s} \
+ %{msoft-float:Fcrt1.o%s} \
+ %{!mfpa:%{!msoft-float:Mcrt1.o%s}}"
+#else
+/* -msoft-float is the default */
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
+ %{m68881:Mcrt1.o%s} \
+ %{mfpa:Wcrt1.o%s} \
+ %{!m68881:%{!mfpa:Fcrt1.o%s}}"
+#endif
+#endif
+
+/* Specify library to handle `-a' basic block profiling. */
+
+/* Specify library to handle `-a' basic block profiling.
+ Control choice of libm.a (if user says -lm)
+ based on fp arith default and options. */
+
+#if TARGET_DEFAULT & 0100
+/* -mfpa is the default */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
+%{msoft-float:-L/usr/lib/fsoft}%{m68881:-L/usr/lib/f68881}\
+%{!msoft_float:%{!m68881:-L/usr/lib/ffpa}}"
+#else
+#if TARGET_DEFAULT & 2
+/* -m68881 is the default */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
+%{msoft-float:-L/usr/lib/fsoft}%{!msoft-float:%{!mfpa:-L/usr/lib/f68881}}\
+%{mfpa:-L/usr/lib/ffpa}"
+#else
+/* -msoft-float is the default */
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
+%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
+%{!m68881:%{!mfpa:-L/usr/lib/fsoft}}%{m68881:-L/usr/lib/f68881}\
+%{mfpa:-L/usr/lib/ffpa}"
+#endif
+#endif
+
+/* Provide required defaults for linker -e and -d switches.
+ Also, it is hard to debug with shared libraries,
+ so don't use them if going to debug. */
+
+#define LINK_SPEC "%{!e*:-e start} -dc -dp %{g:-Bstatic} %{static:-Bstatic} %{-Bstatic}"
+
+/* Every structure or union's size must be a multiple of 2 bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.double 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "\t.long 0x80000000,0\n") \
+ : fprintf (FILE, "\t.double 0r%.20e\n", (VALUE)))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "\t.single 0r%s99e999\n", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "\t.long 0x80000000\n") \
+ : fprintf (FILE, "\t.single 0r%.20e\n", (VALUE)))
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "#0r-0.0") \
+ : fprintf (FILE, "#0r%.9g", (VALUE)))
+
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ (isinf ((VALUE)) \
+ ? fprintf (FILE, "#0r%s99e999", ((VALUE) > 0 ? "" : "-")) \
+ : double_is_minus_zero ((VALUE)) \
+ ? fprintf (FILE, "#0r-0.0") \
+ : fprintf (FILE, "#0r%.20g", (VALUE)))
diff --git a/gcc-1.40/config/tm-sun386.h b/gcc-1.40/config/tm-sun386.h
new file mode 100644
index 0000000..0b54855
--- /dev/null
+++ b/gcc-1.40/config/tm-sun386.h
@@ -0,0 +1,218 @@
+/* Definitions for Sun assembler syntax for the Intel 80386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define TARGET_VERSION fprintf (stderr, " (80386, Sun syntax)");
+
+/* Define the syntax of instructions and addresses. */
+
+/* Define some concatenation macros to concatenate an opcode
+ and one, two or three operands. In other assembler syntaxes
+ they may alter the order of ther operands. */
+
+#ifdef __STDC__
+#define AS2(a,b,c) #a " " #b "," #c
+#define AS3(a,b,c,d) #a " " #b "," #c "," #d
+#define AS1(a,b) #a " " #b
+#else
+#define AS1(a,b) "a b"
+#define AS2(a,b,c) "a b,c"
+#define AS3(a,b,c,d) "a b,c,d"
+#endif
+
+/* Output the size-letter for an opcode.
+ CODE is the letter used in an operand spec (L, B, W, S or Q).
+ CH is the corresponding lower case letter
+ (except if CODE is L then CH is `l'). */
+#define PUT_OP_SIZE(CODE,CH,FILE) putc (CH,(FILE))
+
+/* Opcode suffix for fullword insn. */
+#define L_SIZE "l"
+
+/* Prefix for register names in this syntax. */
+#define RP "%"
+
+/* Prefix for immediate operands in this syntax. */
+#define IP "$"
+
+/* Prefix for internally generated assembler labels. */
+#define LPREFIX ".L"
+
+/* Output the prefix for an immediate operand, or for an offset operand. */
+#define PRINT_IMMED_PREFIX(FILE) fputs ("$", (FILE))
+#define PRINT_OFFSET_PREFIX(FILE) fputs ("$", (FILE))
+
+/* Indirect call instructions should use `*'. */
+#define USE_STAR 1
+
+/* Prefix for a memory-operand X. */
+#define PRINT_PTR(X, FILE)
+
+/* Delimiters that surround base reg and index reg. */
+#define ADDR_BEG(FILE) putc('(', (FILE))
+#define ADDR_END(FILE) putc(')', (FILE))
+
+/* Print an index register (whose rtx is IREG). */
+#define PRINT_IREG(FILE,IREG) \
+ do \
+ { fputs (",", (FILE)); PRINT_REG ((IREG), 0, (FILE)); } \
+ while (0)
+
+/* Print an index scale factor SCALE. */
+#define PRINT_SCALE(FILE,SCALE) \
+ if ((SCALE) != 1) fprintf ((FILE), ",%d", (SCALE))
+
+/* Print a base/index combination.
+ BREG is the base reg rtx, IREG is the index reg rtx,
+ and SCALE is the index scale factor (an integer). */
+
+#define PRINT_B_I_S(BREG,IREG,SCALE,FILE) \
+ { ADDR_BEG (FILE); \
+ if (BREG) PRINT_REG ((BREG), 0, (FILE)); \
+ if ((IREG) != 0) \
+ { PRINT_IREG ((FILE), (IREG)); \
+ PRINT_SCALE ((FILE), (SCALE)); } \
+ ADDR_END (FILE); }
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#define ASM_BYTE "\t.byte\t"
+#define ASM_SHORT "\t.value\t"
+#define ASM_LONG "\t.long\t"
+#define ASM_DOUBLE "\t.double\t"
+
+/* String containing the assembler's comment-starter. */
+
+#define COMMENT_BEGIN "/"
+
+/* Output at beginning of assembler file. */
+/* The .file command should always begin the output. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+ do { \
+ extern char *version_string, *language_string; \
+ { \
+ int len = strlen (dump_base_name); \
+ char *na = dump_base_name + len; \
+ char shorter[15]; \
+ /* NA gets DUMP_BASE_NAME sans directory names. */\
+ while (na > dump_base_name) \
+ { \
+ if (na[-1] == '/') \
+ break; \
+ na--; \
+ } \
+ strncpy (shorter, na, 14); \
+ shorter[14] = 0; \
+ fprintf (FILE, "\t.file\t\"%s\"\n", shorter); \
+ } \
+ fprintf (FILE, "\t.version\t\"%s %s\"\n", \
+ language_string, version_string); \
+ if (optimize) ASM_FILE_START_1 (FILE); \
+ } while (0)
+
+#define ASM_FILE_START_1(FILE) fprintf (FILE, "\t.optim\n")
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "/APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "/NO_APP\n"
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE))
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* Define the syntax of labels and symbol definitions/declarations. */
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), ".%s%d", (PREFIX), (NUMBER))
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ (fputs ("\t.globl\t", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
+
+/* How to output an ASCII string constant. */
+
+#define ASM_OUTPUT_ASCII(FILE, p, size) \
+{ int i=0; \
+ while (i < size) \
+ { if (i%10 == 0) { if (i!=0) fprintf (FILE, "\n"); \
+ fprintf (FILE, ASM_BYTE); } \
+ else fprintf (FILE, ","); \
+ fprintf (FILE, "0x%x",(p[i++] & 0377)) ;} \
+ fprintf (FILE, "\n"); }
diff --git a/gcc-1.40/config/tm-sun386i.h b/gcc-1.40/config/tm-sun386i.h
new file mode 100644
index 0000000..edcebfe
--- /dev/null
+++ b/gcc-1.40/config/tm-sun386i.h
@@ -0,0 +1,105 @@
+/* Definitions for Intel 386 running SunOS 4.0.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-i386.h"
+
+/* Use the Sun assembler syntax. */
+
+#include "tm-sun386.h"
+
+/* By default, target has a 80387. */
+
+#define TARGET_DEFAULT 1
+
+/* Use crt0.o as a startup file. */
+
+#define STARTFILE_SPEC \
+ "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
+
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}\
+%{sun386:}"
+/* That last item is just to prevent a spurious error. */
+
+/* It is hard to debug with shared libraries,
+ so don't use them if going to debug. */
+
+#undef LINK_SPEC
+#define LINK_SPEC "%{!e*:-e _start} -dc -dp %{g:-Bstatic} %{static:-Bstatic} %{-Bstatic}"
+
+/* Extra switches to give the assembler. */
+
+#define ASM_SPEC "-i386"
+
+/* Specify predefined symbols in preprocessor. */
+
+#define CPP_PREDEFINES "-Dunix -Di386 -Dsun386 -Dsun"
+
+/* Allow #sccs in preprocessor. */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+/* We don't want to output SDB debugging information. */
+
+#undef SDB_DEBUGGING_INFO
+
+/* We want to output DBX debugging information. */
+
+#define DBX_DEBUGGING_INFO
+
+/* Implicit library calls should use memcpy, not bcopy, etc. */
+
+#define TARGET_MEM_FUNCTIONS
+
+/* Force structure alignment to the type used for a bitfield. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define VALUE_REGNO(MODE) \
+ (((MODE)==SFmode || (MODE)==DFmode) ? FIRST_FLOAT_REG : 0)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N)== FIRST_FLOAT_REG)
+
+/* This is partly guess. */
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+ ((n) == 0 ? 11 : (n) == 1 ? 9 : (n) == 2 ? 10 : (n) == 3 ? 8 \
+ : (n) == 4 ? 5 : (n) == 5 ? 4 : (n) == 6 ? 6 : (n))
+
+/* Every debugger symbol must be in the text section.
+ Otherwise the assembler or the linker screws up. */
+
+#define DEBUG_SYMS_TEXT
+
+/* This NOP insn makes profiling not fail. */
+
+#define ASM_IDENTIFY_GCC(FILE) \
+fprintf (FILE, (profile_flag ? "gcc_compiled.:\n\tnop\n" : "gcc_compiled.:\n"))
diff --git a/gcc-1.40/config/tm-sun3mach.h b/gcc-1.40/config/tm-sun3mach.h
new file mode 100644
index 0000000..602da86
--- /dev/null
+++ b/gcc-1.40/config/tm-sun3mach.h
@@ -0,0 +1,8 @@
+#include "tm-sun3.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -Dsun -Dsun3 -Dunix -DMACH -DCMU -DMTXINU -DBIT_MSF -DBYTE_MSF"
+
+/* LINK_SPEC is needed only for Sunos 4. */
+
+#undef LINK_SPEC
diff --git a/gcc-1.40/config/tm-sun3os3.h b/gcc-1.40/config/tm-sun3os3.h
new file mode 100644
index 0000000..c4afb4e
--- /dev/null
+++ b/gcc-1.40/config/tm-sun3os3.h
@@ -0,0 +1,5 @@
+#include "tm-sun3.h"
+
+/* LINK_SPEC is needed only for Sunos 4. */
+
+#undef LINK_SPEC
diff --git a/gcc-1.40/config/tm-sun3os3nf.h b/gcc-1.40/config/tm-sun3os3nf.h
new file mode 100644
index 0000000..44e57f7
--- /dev/null
+++ b/gcc-1.40/config/tm-sun3os3nf.h
@@ -0,0 +1,5 @@
+#include "tm-sun3-nfp.h"
+
+/* LINK_SPEC is needed only for Sunos 4. */
+
+#undef LINK_SPEC
diff --git a/gcc-1.40/config/tm-sun4os3.h b/gcc-1.40/config/tm-sun4os3.h
new file mode 100644
index 0000000..a0334d9
--- /dev/null
+++ b/gcc-1.40/config/tm-sun4os3.h
@@ -0,0 +1,15 @@
+#include "tm-sparc.h"
+
+/* Define the Sun-asm flag, which is necessary for Sun 4 with os version 3. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT 7
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tsethi %%hi(LP%d),%%o0\n\tcall .mcount\n\tor %%lo(LP%d),%%o0,%%o0\n", \
+ (LABELNO), (LABELNO))
+
+/* LINK_SPEC is needed only for Sunos 4. */
+
+#undef LINK_SPEC
+
diff --git a/gcc-1.40/config/tm-tahoe.h b/gcc-1.40/config/tm-tahoe.h
new file mode 100644
index 0000000..de9901f
--- /dev/null
+++ b/gcc-1.40/config/tm-tahoe.h
@@ -0,0 +1,850 @@
+/* Definitions of target machine for GNU compiler. Tahoe version.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * File: tm-tahoe.h
+ *
+ * This port made at the University of Buffalo by Devon Bowen,
+ * Dale Wiles and Kevin Zachmann.
+ *
+ * Mail bugs reports or fixes to: gcc@cs.buffalo.edu
+ */
+
+
+/*
+ * Run-time Target Specification
+ */
+
+/* we want "tahoe" and "unix" auto-defined for all future compilations */
+
+#define CPP_PREDEFINES "-Dtahoe -Dunix"
+
+/* have cc1 print that this is the tahoe version */
+
+#define TARGET_VERSION printf (" (tahoe)");
+
+/* this is required in all tm files to hold flags */
+
+extern int target_flags;
+
+/* Zero if it is safe to output .dfloat and .float pseudos. */
+#define TARGET_HEX_FLOAT (target_flags & 1)
+
+#define TARGET_DEFAULT 1
+
+#define TARGET_SWITCHES \
+ { {"hex-float", 1}, \
+ {"no-hex-float", -1}, \
+ { "", TARGET_DEFAULT} }
+
+
+/*
+ * Storage Layout
+ */
+
+/* tahoe uses a big endian byte order */
+
+#define BYTES_BIG_ENDIAN
+
+/* tahoe uses a big endian word order */
+
+#define WORDS_BIG_ENDIAN
+
+/* standard byte size is usable on tahoe */
+
+#define BITS_PER_UNIT 8
+
+/* longs on the tahoe are 4 byte groups */
+
+#define BITS_PER_WORD 32
+
+/* from the last two params we get 4 bytes per word */
+
+#define UNITS_PER_WORD 4
+
+/* addresses are 32 bits (one word) */
+
+#define POINTER_SIZE 32
+
+/* pointers should align every 32 bits */
+
+#define POINTER_BOUNDARY 32
+
+/* all parameters line up on 32 boundaries */
+
+#define PARM_BOUNDARY 32
+
+/* stack should line up on 32 boundaries */
+
+#define STACK_BOUNDARY 32
+
+/* line functions up on 32 bits */
+
+#define FUNCTION_BOUNDARY 32
+
+/* the biggest alignment the tahoe needs in 32 bits */
+
+#define BIGGEST_ALIGNMENT 32
+
+/* we have to align after an 'int : 0' in a structure */
+
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* structures must be made of full bytes */
+
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* tahoe is picky about data alignment */
+
+#define STRICT_ALIGNMENT
+
+/* keep things standard with pcc */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* this section is borrowed from the vax version since the */
+/* formats are the same in both of the architectures */
+
+#define CHECK_FLOAT_VALUE(mode, d) \
+ if ((mode) == SFmode) \
+ { \
+ if ((d) > 1.7014117331926443e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = 1.7014117331926443e+38; } \
+ else if ((d) < -1.7014117331926443e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = -1.7014117331926443e+38; } \
+ else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ }
+
+
+/*
+ * Register Usage
+ */
+
+/* define 15 general regs plus one for the floating point reg (FPP) */
+
+#define FIRST_PSEUDO_REGISTER 17
+
+/* let the compiler know what the fp, sp and pc are */
+
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}
+
+/* lots of regs aren't guarenteed to return from a call. The FPP reg */
+/* must be included in these since it can't be saved by the reg mask */
+
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+
+/* The FPP can handle any type, but the others may require as many as */
+/* two regs depending on the mode needed */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ (REGNO != 16 ? ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) : 1)
+
+/* any mode greater than 4 bytes (doubles) can only go in an even regs */
+/* and the FPP can only hold SFmode and DFmode */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (REGNO != 16 ? (GET_MODE_SIZE (MODE) <= 4 ? 1 : (REGNO % 2 - 1)) : \
+ (MODE == SFmode || MODE == DFmode))
+
+/* if mode1 or mode2, but not both, are doubles then modes cannot be tied */
+
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ ((MODE1 == DFmode) == (MODE2 == DFmode))
+
+/* the program counter is reg 15 */
+
+#define PC_REGNUM 15
+
+/* the stack pointer is reg 14 */
+
+#define STACK_POINTER_REGNUM 14
+
+/* the frame pointer is reg 13 */
+
+#define FRAME_POINTER_REGNUM 13
+
+/* tahoe does require an fp */
+
+#define FRAME_POINTER_REQUIRED 1
+
+/* since tahoe doesn't have a argument pointer, make it the fp */
+
+#define ARG_POINTER_REGNUM 13
+
+/* this isn't currently used since C doesn't support this feature */
+
+#define STATIC_CHAIN_REGNUM 0
+
+/* we'll use reg 1 for structure passing cause the destination */
+/* of the eventual movblk requires it to be there anyway. */
+
+#define STRUCT_VALUE_REGNUM 1
+
+
+/*
+ * Register Classes
+ */
+
+/* tahoe has two types of regs. GENERALY_REGS are all the regs up */
+/* to number 15. FPP_REG is the special floating point processor */
+/* register class (only one reg). */
+
+enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES};
+
+/* defines the number of reg classes. */
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* this defines what the classes are officially named for debugging */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS","GENERAL_REGS","FPP_REG","ALL_REGS"}
+
+/* set general regs to be the first 16 regs and the fpp reg to be 17th */
+
+#define REG_CLASS_CONTENTS {0,0xffff,0x10000,0x1ffff}
+
+/* register class for the fpp reg is FPP_REG, all others are GENERAL_REGS */
+
+#define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS)
+
+/* only gereral registers can be used as a base reg */
+
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* only gereral registers can be used to index */
+
+#define INDEX_REG_CLASS GENERAL_REGS
+
+/* 'a' as a contraint in the md file means the FFP_REG class */
+
+#define REG_CLASS_FROM_LETTER(C) (C == 'a' ? FPP_REG : NO_REGS)
+
+/* any general reg but the fpp can be a base reg */
+
+#define REGNO_OK_FOR_BASE_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER - 1 || reg_renumber[regno] >= 0)
+
+/* any general reg except the pc and fpp can be an index reg */
+
+#define REGNO_OK_FOR_INDEX_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER - 2 || reg_renumber[regno] >= 0)
+
+/* if your loading a floating point constant, it can't be done */
+/* through a register. Force it to be a memory constant. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ ((GET_CODE (X) == CONST_DOUBLE) ? NO_REGS : CLASS)
+
+/* for the fpp reg, all modes fit; for any others, you need two for doubles */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ (CLASS != FPP_REG ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : 1)
+
+/* we don't define any special constant sizes so all should fail */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) 0
+
+/* we don't define any special double sizes so all should fail */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
+
+
+/*
+ * Describing Stack Layout
+ */
+
+/* tahoe stack grows from high to low memory */
+
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if longjmp restores from saved registers
+ rather than from what setjmp saved. */
+#define LONGJMP_RESTORE_FROM_STACK
+
+/* tahoe call frames grow from high to low memory on the stack */
+
+#define FRAME_GROWS_DOWNWARD
+
+/* the tahoe fp points to the *top* of the frame instead of the */
+/* bottom, so we have to make this offset a constant large enough */
+/* to jump over the biggest frame possible. */
+
+#define STARTING_FRAME_OFFSET -52
+
+/* tahoe always pushes 4 bytes unless it's a double in which case */
+/* it pushes a full 8 bytes. */
+
+#define PUSH_ROUNDING(BYTES) (BYTES <= 4 ? 4 : 8)
+
+/* the first parameter in a function is at the fp + 4 */
+
+#define FIRST_PARM_OFFSET(FNDECL) 4
+
+/* the tahoe return function takes care of everything on the stack */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 1
+
+/* function values for all types are returned in register 0 */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
+
+/* libarary routines also return things in reg 0 */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0)
+
+/* Tahoe doesn't return structures in a reentrant way */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* we only return values from a function in reg 0 */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+/* we never pass args through a register */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
+
+/* int is fine to hold the argument summary in FUNCTION_ARG */
+
+#define CUMULATIVE_ARGS int
+
+/* we just set CUM to 0 before the FUNCTION_ARG call. No matter what */
+/* we make it, FUNCTION_ARG will return 0 anyway */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* all modes push their size rounded to the nearest word boundary */
+/* except block which is the size of the block rounded up */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* this is always false since we never pass params in regs */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* this code calculates the register entry mask and sets up */
+/* the stack pointer for the function. The stack is set down */
+/* far enough from the fp to jump over any push regs and local */
+/* vars. This is a problem since the tahoe has the fp pointing */
+/* to the top of the frame and the compiler must know the off- */
+/* set off the fp to the local vars. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER-1; regno++) \
+ if (regs_ever_live[regno] && !call_used_regs[regno]) \
+ mask |= 1 << regno; \
+ fprintf (FILE, "\t.word 0x%x\n", mask); \
+ if (SIZE != 0) fprintf (FILE, "\tsubl3 $%d,fp,sp\n", (SIZE) - STARTING_FRAME_OFFSET); }
+
+/* to call the profiler, push the variable value onto the stack */
+/* and call mcount like a regular function. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tpushl $LP%d\n\tcallf $8,mcount\n", (LABELNO));
+
+/* all stack handling at the end of a function is handled by the */
+/* return command. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* this never gets executed since the system knows it always gets */
+/* an fp to work with. It just prints a friendly message since the */
+/* person must be playing with the tm file defs */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
+ { abort(); }
+
+
+/*
+ * Library Subroutine Names
+ */
+
+/* udiv is a valid C library routine in libc.a, so we call that */
+
+#define UDIVSI3_LIBCALL "*udiv"
+
+/* urem is a valid C library routine in libc.a, so we call that */
+
+#define UMODSI3_LIBCALL "*urem"
+
+
+/*
+ * Addressing Modes
+ */
+
+/* constant addresses can be treated exactly the same as normal constants */
+
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* we can have as many as two regs in any given address */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* The following is all the code for GO_IF_LEGITIMATE_ADDRESS */
+/* most of this taken directly from the vax tm file since the */
+/* tahoe and vax addressing modes are nearly identicle. */
+
+/* Is x an indirectable address? */
+
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))))
+
+/* If x is a non-indexed-address, go to ADDR. */
+
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ register rtx xfoob = (X); \
+ if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \
+ xfoob = XEXP (X, 0); \
+ if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \
+ goto ADDR; \
+ if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
+ && GET_CODE (xfoob) == REG && REGNO (xfoob) == 14) \
+ goto ADDR; }
+
+/* Is PROD an index term in mode MODE. */
+
+#define INDEX_TERM_P(PROD, MODE) \
+(GET_MODE_SIZE (MODE) == 1 \
+ ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \
+ : (GET_CODE (PROD) == MULT \
+ && \
+ (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
+ ((GET_CODE (xfoo0) == CONST_INT \
+ && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \
+ && GET_CODE (xfoo1) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo1)) \
+ || \
+ (GET_CODE (xfoo1) == CONST_INT \
+ && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \
+ && GET_CODE (xfoo0) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo0))))))
+
+/* Is the addition to the index a reg? */
+
+#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \
+{ register rtx xfooa; \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && (xfooa = XEXP (X, 1), \
+ INDEX_TERM_P (xfooa, MODE))) \
+ goto ADDR; \
+ if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1)) \
+ && (xfooa = XEXP (X, 0), \
+ INDEX_TERM_P (xfooa, MODE))) \
+ goto ADDR; } }
+
+/* Is the rtx X a valid memoy address for operand of mode MODE? */
+/* If it is, go to ADDR */
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ register rtx xfoo, xfoo0, xfoo1; \
+ GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { xfoo = XEXP (X, 0); \
+ if (INDEX_TERM_P (xfoo, MODE)) \
+ { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \
+ xfoo = XEXP (X, 1); \
+ if (INDEX_TERM_P (xfoo, MODE)) \
+ { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \
+ if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ { if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ goto ADDR; \
+ GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \
+ if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ { if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ goto ADDR; \
+ GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } }
+
+/* Register 16 can never be used for index or base */
+
+#ifndef REG_OK_STRICT
+#define REG_OK_FOR_INDEX_P(X) (REGNO(X) != 16)
+#define REG_OK_FOR_BASE_P(X) (REGNO(X) != 16)
+#else
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+#endif
+
+/* Addressing is too simple to allow optimizing here */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Post_inc and pre_dec always adds 4 */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ { if (GET_CODE(ADDR) == POST_INC || GET_CODE(ADDR) == PRE_DEC) \
+ goto LABEL; \
+ if (GET_CODE (ADDR) == PLUS) \
+ { if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \
+ && GET_CODE (XEXP (ADDR, 1)) == REG); \
+ else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \
+ && GET_CODE (XEXP (ADDR, 0)) == REG); \
+ else goto LABEL; }}
+
+/* Double's are not legitimate as immediate operands */
+
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) != CONST_DOUBLE)
+
+
+/*
+ * Miscellaneous Parameters
+ */
+
+/* the elements in the case jump table are all words */
+
+#define CASE_VECTOR_MODE HImode
+
+/* each of the table elements in a case are relative to the jump addess */
+
+#define CASE_VECTOR_PC_RELATIVE
+
+/* tahoe case instructions just fall through to the next instruction */
+/* if not satisfied. It doesn't support a default action */
+
+#define CASE_DROPS_THROUGH
+
+/* the standard answer is given here and work ok */
+
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* in a general div case, it's easiest to use TRUNC_DIV_EXPR */
+
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* the standard seems to be leaving char's as signed so we left it */
+/* this way even though we think they should be unsigned! */
+
+#define DEFAULT_SIGNED_CHAR 1
+
+/* the most we can move without cutting down speed is 4 bytes */
+
+#define MOVE_MAX 4
+
+/* our int is 32 bits */
+
+#define INT_TYPE_SIZE 32
+
+/* byte access isn't really slower than anything else */
+
+#define SLOW_BYTE_ACCESS 0
+
+/* zero extension is more than one instruction so try to avoid it */
+
+#define SLOW_ZERO_EXTEND
+
+/* any bits higher than the low 4 are ignored in the shift count */
+/* so don't bother zero extending or sign extending them */
+
+#define SHIFT_COUNT_TRUNCATED
+
+/* we don't need to officially convert from one fixed type to another */
+/* in order to use it as that type. We can just assume it's the same */
+
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* pass chars as ints */
+
+#define PROMOTE_PROTOTYPES
+
+/* pointers can be represented by an si mode expression */
+
+#define Pmode SImode
+
+/* function addresses are made by specifying a byte address */
+
+#define FUNCTION_MODE QImode
+
+/* all the costs here were borrowed from the vax version of the */
+/* tm file. They're pretty much the same in the tahoe */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ if (RTX == const0_rtx) return 0; \
+ if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+
+/*
+ * Condition Code Information
+ */
+
+/* Condition codes still break in one case that we haven't tracked */
+/* down yet, so we have to leave them like this for now. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (GET_CODE(EXP) == SET && GET_CODE(SET_DEST(EXP)) == CC0) { \
+ cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST(EXP); \
+ cc_status.value2 = SET_SRC(EXP); \
+ } else \
+ CC_STATUS_INIT; }
+
+
+/*
+ * Output of Assembler Code
+ */
+
+/* start the assembly by turning off APP */
+
+#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n\n");
+
+/* the instruction that turns on the APP for the gnu assembler */
+
+#define ASM_APP_ON "#APP\n"
+
+/* the instruction that turns off the APP for the gnu assembler */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* what to output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* what to output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* this is what we call each of the regs. notice that the FPP reg is */
+/* called "ac". This should never get used due to the way we've set */
+/* up FPP instructions in the md file. But we call it "ac" here to */
+/* fill the list. */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \
+ "r9", "r10", "r11", "r12", "fp", "sp", "pc", "ac"}
+
+/* registers are called the same thing in dbx anything else */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* allow generation of dbx info in the assembly */
+
+#define DBX_DEBUGGING_INFO
+
+/* our dbx doesn't support this */
+
+#define DBX_NO_XREFS
+
+/* we don't want symbols broken up */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* this'll really never be used, but we'll leave it at this */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* labels are the label followed by a colon and a newline */
+/* must be a statement, so surround it in a null loop */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* use the .globl directive to make labels global for the linker */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* output a label by appending an underscore to it */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* use the standard format for printing internal labels */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* a * is used for label indirection in unix assembly */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* outputing a double is easy cause we only have one kind */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+{ \
+ union { int i[2]; double d;} temp; \
+ temp.d = (VALUE); \
+ if (TARGET_HEX_FLOAT) \
+ fprintf ((FILE), "\t.long 0x%x,0x%x # %.20e\n", \
+ temp.i[0], temp.i[1], temp.d); \
+ else \
+ fprintf (FILE, "\t.dfloat 0d%.20e\n", temp.d); \
+}
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+{ \
+ union { int i; float f;} temp; \
+ temp.f = (float) (VALUE); \
+ if (TARGET_HEX_FLOAT) \
+ fprintf ((FILE), "\t.long 0x%x # %.20e\n", \
+ temp.i, temp.f); \
+ else \
+ fprintf (FILE, "\t.float 0f%.20e\n", temp.f); \
+}
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* this is the insn to push a register onto the stack */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tpushl %s\n", reg_names[REGNO])
+
+/* this is the insn to pop a register from the stack */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovl (sp)+,%s\n", reg_names[REGNO])
+
+/* this is required even thought tahoe doesn't support it */
+/* cause the C code expects it to be defined */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This aligns the assembler output */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ LOG ? fprintf (FILE, "\t.align %d\n", (LOG)) : 0
+
+/* This is how to skip over some space */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* This defines common variables across files */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This defines a common varible in the local file */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* code to generate a label */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* parenthesis for expressions in the assembly */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print an operand. Some difference from the vax code,
+ since the tahoe can't support immediate floats and doubles.
+
+ %@ means print the proper alignment operand for aligning after a casesi.
+ This depends on the assembler syntax.
+ This is 1 for our assembler, since .align is logarithmic. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '@')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '@') \
+ putc ('1', FILE); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+/* When the operand is an address, call print_operand_address to */
+/* do the work from output-tahoe.c. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+ print_operand_address (FILE, ADDR)
+
diff --git a/gcc-1.40/config/tm-tower-as.h b/gcc-1.40/config/tm-tower-as.h
new file mode 100644
index 0000000..1edf4dd
--- /dev/null
+++ b/gcc-1.40/config/tm-tower-as.h
@@ -0,0 +1,616 @@
+/* Definitions of target machine for GNU compiler.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+ Written by Robert Andersson, International Systems, Oslo, Norway.
+ Send bug reports, questions and improvements to ra@intsys.no.
+
+ For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
+ This file outputs assembler source suitable for the native Tower as
+ and with sdb debugging symbols. See tm-tower.h for more comments.
+
+ This file was based on tm-m68k.h, tm-hp9k320.h and tm-3b1.h
+ as of the 1.37.1 version.
+
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-tower.h"
+
+
+/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
+ This will control the use of inline 68881 insns in certain macros.
+ Also, define special define used to identify the Tower assembler. */
+
+#define CPP_SPEC "-D__TOWER_ASM__ %{m68881:-D__HAVE_68881__}"
+
+/* The startfiles and libraries depend on the -p and -m68881 options.
+ The Tower does not support the -pg option. */
+
+#define STARTFILE_SPEC \
+"%{p:%{m68881:/usr/lib/fp/mcrt1.o}%{!m68881:/lib/mcrt1.o}} \
+ %{!p:%{m68881:/usr/lib/fp/crt1.o}%{!m68881:/lib/crt1.o}}"
+
+/* These four macros control how m68k.md is expanded. */
+
+#define MOTOROLA
+#define SGS
+#define SONY_ASM
+#define HPUX_ASM
+
+/* Turn on SDB debugging info. */
+
+#define SDB_DEBUGGING_INFO
+
+/* This is only useful if gdb is changed, but doesn't harm anyway. */
+
+#define ASM_IDENTIFY_GCC(FILE) \
+ fprintf (FILE, "gcc_compiled%%:\n")
+
+/* All the ASM_OUTPUT macros need to conform to the Tower as syntax. */
+
+#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
+ fprintf (FILE, "\tfile\t\"%s\"\n", FILENAME)
+
+#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \
+ fprintf (FILE, "\tln\t%d\n", \
+ (sdb_begin_function_line \
+ ? last_linenum - sdb_begin_function_line : 1))
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\tident\t\"%s\" \n", NAME)
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+ { register int sp = 0, lp = 0; \
+ fprintf (FILE, "\tbyte\t"); \
+ loop: \
+ if (PTR[sp] > ' ' && ! (PTR[sp] & 0x80) && PTR[sp] != '\\') \
+ { lp += 3; \
+ fprintf (FILE, "'%c", PTR[sp]); } \
+ else \
+ { lp += 5; \
+ fprintf (FILE, "0x%x", PTR[sp]); } \
+ if (++sp < LEN) \
+ { if (lp > 60) \
+ { lp = 0; \
+ fprintf (FILE, "\n\tbyte\t"); } \
+ else \
+ putc (',', FILE); \
+ goto loop; } \
+ putc ('\n', FILE); }
+
+/* Translate Motorola opcodes such as `jbeq'
+ into SGS/Tower opcodes such as `beq.w'.
+ Change `move' to `mov'.
+ Change `cmpm' to `cmp'.
+ Change `divsl' to `tdivs'.
+ Change `divul' to `tdivu'.
+ Change `ftst' to `ftest'.
+ Change `fmove' to `fmov'. */
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+{ if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \
+ { ++(PTR); \
+ while (*(PTR) != ' ') \
+ { putc (*(PTR), (FILE)); ++(PTR); } \
+ fprintf ((FILE), ".w"); } \
+ else if ((PTR)[0] == 'm' && (PTR)[1] == 'o' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'e') \
+ { fprintf ((FILE), "mov"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'c' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'p' && (PTR)[3] == 'm') \
+ { fprintf ((FILE), "cmp"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 's' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivs"); (PTR) += 5; } \
+ else if ((PTR)[0] == 'd' && (PTR)[1] == 'i' \
+ && (PTR)[2] == 'v' && (PTR)[3] == 'u' \
+ && (PTR)[4] == 'l') \
+ { fprintf ((FILE), "tdivu"); (PTR) += 5; } \
+ else if ((PTR)[0] == 'f' && (PTR)[1] == 't' \
+ && (PTR)[2] == 's' && (PTR)[3] == 't') \
+ { fprintf ((FILE), "ftest"); (PTR) += 4; } \
+ else if ((PTR)[0] == 'f' && (PTR)[1] == 'm' \
+ && (PTR)[2] == 'o' && (PTR)[3] == 'v' \
+ && (PTR)[4] == 'e') \
+ { fprintf ((FILE), "fmov"); (PTR) += 5; } \
+}
+
+
+
+/* Override parts of tm-m68k.h to fit the Tower assembler.
+ This section needs to track changes done to tm-m68k.h in the future. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (68k, Motorola/SGS/Tower32 syntax)");
+
+#undef BLOCK_PROFILER
+#undef FUNCTION_BLOCK_PROFILER
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABEL_NO) \
+ fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
+
+/* The prologue is identical to the one in tm-m68k.h except that the
+ assembler syntax is different. */
+
+#undef FUNCTION_PROLOGUE
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ int fsize = ((SIZE) + 3) & -4; \
+ if (frame_pointer_needed) \
+ { if (TARGET_68020 || fsize < 0x8000) \
+ fprintf (FILE, "\tlink %%a6,&%d\n", -fsize); \
+ else \
+ fprintf (FILE, "\tlink %%a6,&0\n\tsub.l &%d,%%sp\n", fsize); } \
+ for (regno = 24; regno < 56; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ fprintf(FILE, "\tfpmoved %s,-(%%sp)\n", \
+ reg_names[regno]); \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (regno - 16); \
+ if ((mask & 0xff) != 0) \
+ fprintf (FILE, "\tfmovm &0x%x,-(%%sp)\n", mask & 0xff); \
+ mask = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ mask |= 1 << (15 - regno); \
+ if (frame_pointer_needed) \
+ mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \
+ if (exact_log2 (mask) >= 0) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[15 - exact_log2 (mask)]); \
+ else if (mask) fprintf (FILE, "\tmovm.l &0x%x,-(%%sp)\n", mask); }
+
+/* The epilogue is identical to the one in tm-m68k.h except that:
+ a) The assembler syntax is different.
+ b) Pointers are returned both in %d0 and %a0.
+ c) FUNCTION_EXTRA_EPILOGUE is not needed. */
+
+#undef FUNCTION_EPILOGUE
+#define FUNCTION_EPILOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask, fmask; \
+ register int nregs; \
+ int offset, foffset, fpoffset; \
+ extern char call_used_regs[]; \
+ extern int current_function_pops_args; \
+ extern int current_function_args_size; \
+ extern int current_function_returns_pointer; \
+ int fsize = ((SIZE) + 3) & -4; \
+ int big = 0; \
+ nregs = 0; fmask = 0; fpoffset = 0; \
+ for (regno = 24 ; regno < 56 ; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ nregs++; \
+ fpoffset = nregs*8; \
+ nregs = 0; \
+ for (regno = 16; regno < 24; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; fmask |= 1 << (23 - regno); } \
+ foffset = fpoffset + nregs * 12; \
+ nregs = 0; mask = 0; \
+ if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \
+ for (regno = 0; regno < 16; regno++) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ { nregs++; mask |= 1 << regno; } \
+ offset = foffset + nregs * 4; \
+ if (offset + fsize >= 0x8000 \
+ && frame_pointer_needed \
+ && (mask || fmask || fpoffset)) \
+ { fprintf (FILE, "\tmov.l &%d,%%a0\n", -fsize); \
+ fsize = 0, big = 1; } \
+ if (exact_log2 (mask) >= 0) { \
+ if (big) \
+ fprintf (FILE, "\tmov.l -%d(%%a6,%%a0.l),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", \
+ reg_names[exact_log2 (mask)]); \
+ else \
+ fprintf (FILE, "\tmov.l -%d(%%a6),%s\n", \
+ offset + fsize, reg_names[exact_log2 (mask)]); } \
+ else if (mask) { \
+ if (big) \
+ fprintf (FILE, "\tmovm.l -%d(%%a6,%%a0.l),&0x%x\n", \
+ offset + fsize, mask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tmovm.l (%%sp)+,&0x%x\n", mask); \
+ else \
+ fprintf (FILE, "\tmovm.l -%d(%%a6),&0x%x\n", \
+ offset + fsize, mask); } \
+ if (fmask) { \
+ if (big) \
+ fprintf (FILE, "\tfmovm -%d(%%a6,%%a0.l),&0x%x\n", \
+ foffset + fsize, fmask); \
+ else if (! frame_pointer_needed) \
+ fprintf (FILE, "\tfmovm (%%sp)+,&0x%x\n", fmask); \
+ else \
+ fprintf (FILE, "\tfmovm -%d(%%a6),&0x%x\n", \
+ foffset + fsize, fmask); } \
+ if (fpoffset != 0) \
+ for (regno = 55; regno >= 24; regno--) \
+ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \
+ if (big) \
+ fprintf(FILE, "\tfpmoved -%d(%%a6,%%a0.l),%s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ else if (! frame_pointer_needed) \
+ fprintf(FILE, "\tfpmoved (%%sp)+,%s\n", \
+ reg_names[regno]); \
+ else \
+ fprintf(FILE, "\tfpmoved -%d(%%a6),%s\n", \
+ fpoffset + fsize, reg_names[regno]); \
+ fpoffset -= 8; \
+ } \
+ if (current_function_returns_pointer) \
+ fprintf (FILE, "\tmov.l %%d0,%%a0\n"); \
+ if (frame_pointer_needed) \
+ fprintf (FILE, "\tunlk %%a6\n"); \
+ if (current_function_pops_args && current_function_args_size) \
+ fprintf (FILE, "\trtd &%d\n", current_function_args_size); \
+ else fprintf (FILE, "\trts\n"); }
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_PUSH
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l %s,-(%%sp)\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#undef ASM_OUTPUT_REG_POP
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) \
+( fprintf (FILE, "#NO_APP\n"), \
+ sdbout_filename ((FILE), main_input_filename))
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\ttext"
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\tdata"
+
+/* This says how to output an assembler line to define a global common symbol.
+ We use SIZE rather than ROUNDED, as this is what the native cc does. */
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
+
+/* This says how to output an assembler line to define a local common symbol.
+ We use SIZE rather than ROUNDED, as this is what the native cc does. */
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\tlcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", ((SIZE) == 0) ? (ROUNDED) : (SIZE)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#undef ASM_FORMAT_PRIVATE_NAME
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 11), \
+ sprintf ((OUTPUT), "%s%%%%%d", (NAME), (LABELNO)))
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#undef ASM_GLOBALIZE_LABEL
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+do { fputs ("\tglobal ", FILE); \
+ assemble_name (FILE, NAME); \
+ fputs ("\n", FILE); \
+ } while (0)
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+
+#undef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf ((FILE), "%s%%%d:\n", (PREFIX), (NUM))
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM)); \
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+do { union { double d; long l[2]; } tem; \
+ tem.d = (VALUE); \
+ fprintf(FILE, "\tlong 0x%x,0x%x\n", tem.l[0], tem.l[1]); \
+ } while (0)
+
+#undef ASM_OUTPUT_FLOAT
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+do { union { float f; long l;} tem; \
+ tem.f = (VALUE); \
+ fprintf (FILE, "\tlong 0x%x\n", tem.l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\tlong "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#undef ASM_OUTPUT_SHORT
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\tshort "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#undef ASM_OUTPUT_CHAR
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\tbyte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#undef ASM_OUTPUT_BYTE
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) == 1) \
+ fprintf (FILE, "\teven\n"); \
+ else if ((LOG) != 0) \
+ abort ();
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\tspace %u\n", (SIZE))
+
+#undef PRINT_OPERAND
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '.') fprintf (FILE, "."); \
+ else if (CODE == '#') fprintf (FILE, "&"); \
+ else if (CODE == '-') fprintf (FILE, "-(%%sp)"); \
+ else if (CODE == '+') fprintf (FILE, "(%%sp)+"); \
+ else if (CODE == '@') fprintf (FILE, "(%%sp)"); \
+ else if (CODE == '!') fprintf (FILE, "%%cc"); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { union { double d; int i[2]; } u; \
+ union { float f; int i; } u1; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ u1.f = u.d; \
+ fprintf (FILE, "&0x%x", u1.i); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ fprintf (FILE, "&0x%x%08x", CONST_DOUBLE_LOW (X), CONST_DOUBLE_HIGH (X));\
+ else { putc ('&', FILE); output_addr_const (FILE, X); }}
+
+/* Note that this contains a kludge that knows that the only reason
+ we have an address (plus (label_ref...) (reg...))
+ is in the insn before a tablejump, and we know that the table is
+ exactly 10 bytes away. */
+
+#undef PRINT_OPERAND_ADDRESS
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+{ register rtx reg1, reg2, breg, ireg; \
+ register rtx addr = ADDR; \
+ rtx offset; \
+ switch (GET_CODE (addr)) \
+ { \
+ case REG: \
+ fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \
+ break; \
+ case PRE_DEC: \
+ fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case POST_INC: \
+ fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \
+ break; \
+ case PLUS: \
+ reg1 = 0; reg2 = 0; \
+ ireg = 0; breg = 0; \
+ offset = 0; \
+ if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \
+ { \
+ offset = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \
+ { \
+ offset = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) != PLUS) ; \
+ else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == MULT) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ else if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg1 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg1 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \
+ || GET_CODE (addr) == SIGN_EXTEND) \
+ { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \
+/* for OLD_INDEXING \
+ else if (GET_CODE (addr) == PLUS) \
+ { \
+ if (GET_CODE (XEXP (addr, 0)) == REG) \
+ { \
+ reg2 = XEXP (addr, 0); \
+ addr = XEXP (addr, 1); \
+ } \
+ else if (GET_CODE (XEXP (addr, 1)) == REG) \
+ { \
+ reg2 = XEXP (addr, 1); \
+ addr = XEXP (addr, 0); \
+ } \
+ } \
+ */ \
+ if (offset != 0) { if (addr != 0) abort (); addr = offset; } \
+ if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \
+ || GET_CODE (reg1) == MULT)) \
+ || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \
+ { breg = reg2; ireg = reg1; } \
+ else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \
+ { breg = reg1; ireg = reg2; } \
+ if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \
+ { int scale = 1; \
+ if (GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "10(%%pc,%s.w", \
+ reg_names[REGNO (XEXP (ireg, 0))]); \
+ else \
+ fprintf (FILE, "10(%%pc,%s.l", \
+ reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; } \
+ if (ireg != 0 || breg != 0) \
+ { int scale = 1; \
+ if (breg == 0) \
+ abort (); \
+ if (addr != 0) \
+ output_addr_const (FILE, addr); \
+ fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \
+ if (ireg != 0) \
+ putc (',', FILE); \
+ if (ireg != 0 && GET_CODE (ireg) == MULT) \
+ { scale = INTVAL (XEXP (ireg, 1)); \
+ ireg = XEXP (ireg, 0); } \
+ if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \
+ fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \
+ else if (ireg != 0) \
+ fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \
+ if (scale != 1) fprintf (FILE, "*%d", scale); \
+ putc (')', FILE); \
+ break; \
+ } \
+ else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \
+ { fprintf (FILE, "10(%%pc,%s.w)", \
+ reg_names[REGNO (reg1)]); \
+ break; } \
+ default: \
+ output_addr_const (FILE, addr); \
+ }}
+
+
+
+/* Override usual definitions of SDB output macros.
+ These definitions differ only in the absence of the period
+ at the beginning of the name of the directive
+ and in the use of `~' as the symbol for the current location. */
+
+#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\tscl\t%d;", (a))
+#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\tval\t%d;", (a))
+#define PUT_SDB_VAL(a) \
+( fputs ("\tval\t", asm_out_file), \
+ output_addr_const (asm_out_file, (a)), \
+ fputc (';', asm_out_file))
+
+#define PUT_SDB_DEF(a) \
+do { fprintf (asm_out_file, "\tdef\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\tdef\t~%s;",a)
+#define PUT_SDB_ENDEF fputs("\tendef\n", asm_out_file)
+#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\ttype\t0%o;", a)
+#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\tsize\t%d;", a)
+#define PUT_SDB_START_DIM fprintf(asm_out_file, "\tdim\t")
+
+#define PUT_SDB_TAG(a) \
+do { fprintf (asm_out_file, "\ttag\t"); \
+ ASM_OUTPUT_LABELREF (asm_out_file, a); \
+ fprintf (asm_out_file, ";"); } while (0)
+
+#define PUT_SDB_BLOCK_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_BLOCK_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~eb;\tval\t~;\tscl\t100;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_START(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~bf;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+ fprintf (asm_out_file, \
+ "\tdef\t~ef;\tval\t~;\tscl\t101;\tline\t%d;\tendef\n", \
+ (LINE))
+
+#define PUT_SDB_EPILOGUE_END(NAME) \
+ fprintf (asm_out_file, \
+ "\tdef\t%s;\tval\t~;\tscl\t-1;\tendef\n", \
+ (NAME))
+
+#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
+ sprintf ((BUFFER), "~%dfake", (NUMBER));
diff --git a/gcc-1.40/config/tm-tower.h b/gcc-1.40/config/tm-tower.h
new file mode 100644
index 0000000..68e74a6
--- /dev/null
+++ b/gcc-1.40/config/tm-tower.h
@@ -0,0 +1,100 @@
+/* Definitions of target machine for GNU compiler.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+ Written by Robert Andersson, International Systems, Oslo, Norway.
+ Please send bug reports, questions and improvements to ra@intsys.no.
+
+ For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
+ I don't have access to 200/700/800/850 machines, so I don't know if it
+ works on those as well. It shouldn't be far from it however.
+ The hardware floating point support is completely untested, as I do
+ not have access to a machine with a 6888x FPU in it.
+ It does not work on the System V Release 2 based OS releases. Making it
+ work will not be easy, due to the silly way in which stack expansion is
+ implemented in the OS.
+
+ This file is included in both tm-tower-as.h and tm-tower-gc.h, and contains
+ definitions common to both of them. Do *NOT* include this file directly.
+
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "tm-m68k.h"
+
+
+/* See tm-m68k.h. 5 means 68020 with no 68881. */
+
+#define TARGET_DEFAULT 5
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#ifdef tower32_200
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_200"
+#endif
+#ifdef tower32_600
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_600"
+#endif
+#ifdef tower32_700
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_700"
+#endif
+#ifdef tower32_800
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_800"
+#endif
+#ifdef tower32_850
+#define CPP_PREDEFINES "-Dunix -Dtower32 -Dtower32_850"
+#endif
+
+/* The startfiles and libraries depend on the -p and -m68881 options.
+ The Tower does not support the -pg option. */
+
+#define LINK_SPEC \
+"%{p:%{m68881:-L/usr/lib/fp/libp} -L/usr/lib/libp} \
+ %{m68881:-L/usr/lib/fp}"
+
+#define LIB_SPEC "-lc %{m68881:/usr/lib/fp/crtn.o}%{!m68881:/lib/crtn.o}"
+
+/* Use mem* functions, recognize #ident lines. */
+
+#define TARGET_MEM_FUNCTIONS
+#define IDENT_DIRECTIVE
+
+/* This is only used in g++, don't prepend underscore. */
+
+#define NO_UNDERSCORES
+
+/* Every structure and union's size must be a multiple of two bytes. */
+
+#define STRUCTURE_SIZE_BOUNDARY 16
+
+/* All register names should have a leading % character. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES \
+{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", \
+ "%fpa0", "%fpa1", "%fpa2", "%fpa3", "%fpa4", "%fpa5", "%fpa6", "%fpa7", \
+ "%fpa8", "%fpa9", "%fpa10", "%fpa11", "%fpa12", "%fpa13", "%fpa14", "%fpa15",\
+ "%fpa16","%fpa17", "%fpa18", "%fpa19", "%fpa20", "%fpa21", "%fpa22","%fpa23",\
+ "%fpa24","%fpa25", "%fpa26", "%fpa27", "%fpa28", "%fpa29", "%fpa30","%fpa31"}
+
+/* We do not want leading underscores. */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "%s", NAME)
diff --git a/gcc-1.40/config/tm-ultrix.h b/gcc-1.40/config/tm-ultrix.h
new file mode 100644
index 0000000..025dc0d
--- /dev/null
+++ b/gcc-1.40/config/tm-ultrix.h
@@ -0,0 +1,7 @@
+#include "tm-vax.h"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dultrix -Dbsd4_2 -Dvax -Dunix -D__vax"
+
+/* By default, allow $ to be part of an identifier. */
+#define DOLLARS_IN_IDENTIFIERS 1
diff --git a/gcc-1.40/config/tm-vax.h b/gcc-1.40/config/tm-vax.h
new file mode 100644
index 0000000..f92af96
--- /dev/null
+++ b/gcc-1.40/config/tm-vax.h
@@ -0,0 +1,1080 @@
+/* Definitions of target machine for GNU compiler. Vax version.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-Dvax -Dunix"
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (vax)");
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Macros used in the machine description to test the flags. */
+
+/* Nonzero if compiling code that Unix assembler can assemble. */
+#define TARGET_UNIX_ASM (target_flags & 1)
+
+/* Nonzero if compiling with VAX-11 "C" style structure alignment */
+#define TARGET_VAXC_ALIGNMENT (target_flags & 2)
+
+/* Nonzero if compiling with `G'-format floating point */
+#define TARGET_G_FLOAT (target_flags & 4)
+
+/* Macro to define tables used to set the flags.
+ This is a list in braces of pairs in braces,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ { {"unix", 1}, \
+ {"gnu", -1}, \
+ {"vaxc-alignment", 2}, \
+ {"g", 4}, \
+ {"g-float", 4}, \
+ {"d", -4}, \
+ {"d-float", -4}, \
+ { "", TARGET_DEFAULT}}
+
+/* Default target_flags if no switches specified. */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 1
+#endif
+
+/* Target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is not true on the vax. */
+/* #define BITS_BIG_ENDIAN */
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on the vax. */
+/* #define BYTES_BIG_ENDIAN */
+
+/* Define this if most significant word of a multiword number is numbered. */
+/* This is not true on the vax. */
+/* #define WORDS_BIG_ENDIAN */
+
+/* Number of bits in an addressible storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Allocation boundary (in *bits*) for storing pointers in memory. */
+#define POINTER_BOUNDARY (TARGET_VAXC_ALIGNMENT ? 8 : 32)
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 16
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY (TARGET_VAXC_ALIGNMENT ? 8 : 32)
+
+/* Every structure's size must be a multiple of this. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* A bitfield declared as `int' forces `int' alignment for the struct. */
+#define PCC_BITFIELD_TYPE_MATTERS (! TARGET_VAXC_ALIGNMENT)
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT (TARGET_VAXC_ALIGNMENT ? 8 : 32)
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+/* #define STRICT_ALIGNMENT */
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+#define FIRST_PSEUDO_REGISTER 16
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the vax, these are the AP, FP, SP and PC. */
+#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you like. */
+#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+ On the vax, all registers are one word long. */
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
+ On the vax, all registers can hold all modes. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* Vax pc is overloaded on a register. */
+#define PC_REGNUM 15
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 14
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 13
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 1
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 12
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 0
+
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM 1
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+/* The vax has only one kind of registers, so NO_REGS and ALL_REGS
+ are the only classes. */
+
+enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Since GENERAL_REGS is the same class as ALL_REGS,
+ don't give it a different class number; just make it an alias. */
+
+#define GENERAL_REGS ALL_REGS
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "ALL_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS {0, 0xffff}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) ALL_REGS
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS ALL_REGS
+#define BASE_REG_CLASS ALL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) NO_REGS
+
+/* The letters I, J, K, L and M in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C. */
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) 0
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself. */
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+/* On the vax, this is always the size of MODE in words,
+ since all registers are the same size. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if longjmp restores from saved registers
+ rather than from what setjmp saved. */
+#define LONGJMP_RESTORE_FROM_STACK
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+#define STARTING_FRAME_OFFSET 0
+
+/* If we generate an insn to push BYTES bytes,
+ this says how many the stack pointer really advances by.
+ On the vax, -(sp) pushes only the bytes of the operands. */
+#define PUSH_ROUNDING(BYTES) (BYTES)
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 4
+
+/* Value is 1 if returning from a function call automatically
+ pops the arguments described by the number-of-args field in the call.
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+
+ On the Vax, the RET insn always pops all the args for any function. */
+
+#define RETURN_POPS_ARGS(FUNTYPE) 1
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+/* On the Vax the return value is in R0 regardless. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+/* On the Vax the return value is in R0 regardless. */
+
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0)
+
+/* Define this if PCC uses the nonreentrant convention for returning
+ structure and union values. */
+
+#define PCC_STATIC_STRUCT_RETURN
+
+/* 1 if N is a possible register number for a function value.
+ On the Vax, R0 is the only register thus used. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
+
+/* 1 if N is a possible register number for function argument passing.
+ On the Vax, no registers are used in this way. */
+
+#define FUNCTION_ARG_REGNO_P(N) 0
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On the vax, this is a single integer, which is a number of bytes
+ of arguments scanned so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0.
+
+ On the vax, the offset starts at 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE) \
+ ((CUM) = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM) += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
+ : (int_size_in_bytes (TYPE) + 3) & ~3))
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+/* On the vax all args are pushed. */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0
+
+/* This macro generates the assembly code for function entry.
+ FILE is a stdio stream to output the code to.
+ SIZE is an int: how many units of temporary storage to allocate.
+ Refer to the array `regs_ever_live' to determine which registers
+ to save; `regs_ever_live[I]' is nonzero if register number I
+ is ever used in the function. This macro is responsible for
+ knowing which registers should not be saved even if used. */
+
+#define FUNCTION_PROLOGUE(FILE, SIZE) \
+{ register int regno; \
+ register int mask = 0; \
+ extern char call_used_regs[]; \
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ if (regs_ever_live[regno] && !call_used_regs[regno]) \
+ mask |= 1 << regno; \
+ fprintf (FILE, "\t.word 0x%x\n", mask); \
+ MAYBE_VMS_FUNCTION_PROLOGUE(FILE) \
+ if ((SIZE) >= 64) fprintf (FILE, "\tmovab %d(sp),sp\n", -SIZE);\
+ else if (SIZE) fprintf (FILE, "\tsubl2 $%d,sp\n", (SIZE)); }
+
+/* tm-vms.h redefines this. */
+#define MAYBE_VMS_FUNCTION_PROLOGUE(FILE)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\tmovab LP%d,r0\n\tjsb mcount\n", (LABELNO));
+
+/* Output assembler code to FILE to initialize this source file's
+ basic block profiling info, if that has not already been done. */
+
+#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
+ fprintf (FILE, "\ttstl LPBX0\n\tjneq LPI%d\n\tpushal LPBX0\n\tcalls $1,__bb_init_func\nLPI%d:\n", \
+ LABELNO, LABELNO);
+
+/* Output assembler code to FILE to increment the entry-count for
+ the BLOCKNO'th basic block in this source file. This is a real pain in the
+ sphincter on a VAX, since we do not want to change any of the bits in the
+ processor status word. The way it is done here, it is pushed onto the stack
+ before any flags have changed, and then the stack is fixed up to account for
+ the fact that the instruction to restore the flags only reads a word.
+ It may seem a bit clumsy, but at least it works.
+*/
+
+#define BLOCK_PROFILER(FILE, BLOCKNO) \
+ fprintf (FILE, "\tmovpsl -(sp)\n\tmovw (sp),2(sp)\n\taddl2 $2,sp\n\taddl2 $1,LPBX2+%d\n\tbicpsw $255\n\tbispsw (sp)+\n", \
+ 4 * BLOCKNO)
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* This macro generates the assembly code for function exit,
+ on machines that need it. If FUNCTION_EPILOGUE is not defined
+ then individual return instructions are generated for each
+ return statement. Args are same as for FUNCTION_PROLOGUE. */
+
+/* #define FUNCTION_EPILOGUE(FILE, SIZE) */
+
+/* If the memory address ADDR is relative to the frame pointer,
+ correct it to be relative to the stack pointer instead.
+ This is for when we don't use a frame pointer.
+ ADDR should be a variable name. */
+
+#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) abort ();
+
+/* Addressing modes, and classification of registers for them. */
+
+#define HAVE_POST_INCREMENT
+/* #define HAVE_POST_DECREMENT */
+
+#define HAVE_PRE_DECREMENT
+/* #define HAVE_PRE_INCREMENT */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_INDEX_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+#define REGNO_OK_FOR_BASE_P(regno) \
+((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+/* 1 if X is an rtx for a constant that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X) && LEGITIMATE_CONSTANT_P (X))
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+#define LEGITIMATE_CONSTANT_P(X) \
+ (! (GET_CODE ((X)) == CONST \
+ && GET_CODE (XEXP ((X), 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \
+ && EXTERNAL_SYMBOL_P (XEXP (XEXP ((X), 0), 0))))
+#else
+#define LEGITIMATE_CONSTANT_P(X) 1
+#endif
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) 1
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) 1
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#endif
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is actually machine-independent. */
+
+/* 1 if X is an address that we could indirect through. */
+#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
+#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == SYMBOL_REF && !EXTERNAL_SYMBOL_P (X)) \
+ || (GET_CODE (X) == CONST && LEGITIMATE_CONSTANT_P(X)) \
+ || GET_CODE (X) == CONST_INT)
+
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (INDIRECTABLE_CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))))
+#else
+#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) CONSTANT_ADDRESS_P(X)
+#define INDIRECTABLE_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))))
+#endif
+
+/* Non-zero if this is a valid address without indexing or indirection. */
+#define NONINDIRECT_ADDRESS_P(X) \
+ (CONSTANT_ADDRESS_P (X) \
+ || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == PLUS \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1))))
+
+/* Go to ADDR if X is a valid address not using indexing.
+ (This much is the easy part.) */
+#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
+{ register rtx xfoob = (X); \
+ if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (NONINDIRECT_ADDRESS_P (xfoob)) goto ADDR; \
+ xfoob = XEXP (X, 0); \
+ if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \
+ goto ADDR; \
+ if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
+ && GET_CODE (xfoob) == REG && REG_OK_FOR_BASE_P (xfoob)) \
+ goto ADDR; }
+
+/* 1 if PROD is either a reg times size of mode MODE
+ or just a reg, if MODE is just one byte.
+ This macro's expansion uses the temporary variables xfoo0 and xfoo1
+ that must be declared in the surrounding context. */
+#define INDEX_TERM_P(PROD, MODE) \
+(GET_MODE_SIZE (MODE) == 1 \
+ ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \
+ : (GET_CODE (PROD) == MULT \
+ && \
+ (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
+ ((GET_CODE (xfoo0) == CONST_INT \
+ && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \
+ && GET_CODE (xfoo1) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo1)) \
+ || \
+ (GET_CODE (xfoo1) == CONST_INT \
+ && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \
+ && GET_CODE (xfoo0) == REG \
+ && REG_OK_FOR_INDEX_P (xfoo0))))))
+
+/* Go to ADDR if X is the sum of a register
+ and a valid index term for mode MODE. */
+#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \
+{ register rtx xfooa; \
+ if (GET_CODE (X) == PLUS) \
+ { if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && (xfooa = XEXP (X, 1), \
+ INDEX_TERM_P (xfooa, MODE))) \
+ goto ADDR; \
+ if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1)) \
+ && (xfooa = XEXP (X, 0), \
+ INDEX_TERM_P (xfooa, MODE))) \
+ goto ADDR; } }
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ register rtx xfoo, xfoo0, xfoo1; \
+ GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
+ if (GET_CODE (X) == PLUS) \
+ { /* Handle <address>[index] represented with index-sum outermost */\
+ xfoo = XEXP (X, 0); \
+ if (INDEX_TERM_P (xfoo, MODE)) \
+ { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \
+ xfoo = XEXP (X, 1); \
+ if (INDEX_TERM_P (xfoo, MODE)) \
+ { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \
+ /* Handle offset(reg)[index] with offset added outermost */ \
+ if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 0))) \
+ { if (GET_CODE (XEXP (X, 1)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 1))) \
+ goto ADDR; \
+ GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \
+ if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))) \
+ { if (GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0))) \
+ goto ADDR; \
+ GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } }
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output.
+
+ For the vax, nothing needs to be done. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+ On the VAX, the predecrement and postincrement address depend thus
+ (the amount of decrement or increment being the length of the operand)
+ and all indexed address depend thus (because the index scale factor
+ is the length of the operand). */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
+ { if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) \
+ goto LABEL; \
+ if (GET_CODE (ADDR) == PLUS) \
+ { if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \
+ && GET_CODE (XEXP (ADDR, 1)) == REG); \
+ else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \
+ && GET_CODE (XEXP (ADDR, 0)) == REG); \
+ else goto LABEL; }}
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE HImode
+
+/* Define this if the case instruction expects the table
+ to contain offsets from the address of the table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE
+
+/* Define this if the case instruction drops through after the table
+ when the index is out of range. Don't define it if the case insn
+ jumps to the default label instead. */
+#define CASE_DROPS_THROUGH
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* This flag, if defined, says the same insns that convert to a signed fixnum
+ also convert validly to an unsigned one. */
+#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 8
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+/* #define SLOW_ZERO_EXTEND */
+
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 0
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+/* #define SHIFT_COUNT_TRUNCATED */
+
+/* Shift counts can be negative. */
+#define NEGATIVE_SHIFT_COUNTS 1
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* Compute the cost of computing a constant rtl expression RTX
+ whose rtx-code is CODE. The body of this macro is a portion
+ of a switch statement. If the code is computed here,
+ return it with a return statement. Otherwise, break from the switch. */
+
+#define CONST_COSTS(RTX,CODE) \
+ case CONST_INT: \
+ /* Constant zero is super cheap due to clr instruction. */ \
+ if (RTX == const0_rtx) return 0; \
+ if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ return 3; \
+ case CONST_DOUBLE: \
+ return 5;
+
+/*
+ * We can use the BSD C library routines for the gnulib calls that are
+ * still generated, since that's what they boil down to anyways.
+ */
+
+#define UDIVSI3_LIBCALL "*udiv"
+#define UMODSI3_LIBCALL "*urem"
+
+/* Check a `double' value for validity for a particular machine mode. */
+
+/* note that it is very hard to accidently create a number that fits in a
+ double but not in a float, since their ranges are almost the same */
+#define CHECK_FLOAT_VALUE(mode, d) \
+ if ((mode) == SFmode) \
+ { \
+ if ((d) > 1.7014117331926444e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = 1.7014117331926444e+38; } \
+ else if ((d) < -1.7014117331926444e+38) \
+ { error ("magnitude of constant too large for `float'"); \
+ (d) = -1.7014117331926444e+38; } \
+ else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
+ { warning ("`float' constant truncated to zero"); \
+ (d) = 0.0; } \
+ }
+
+/* For future reference:
+ D Float: 9 bit, sign magnitude, excess 128 binary exponent
+ normalized 56 bit fraction, redundant bit not represented
+ approximately 16 decimal digits of precision
+
+ The values to use if we trust decimal to binary conversions:
+#define MAX_D_FLOAT 1.7014118346046923e+38
+#define MIN_D_FLOAT .29387358770557188e-38
+
+ G float: 12 bit, sign magnitude, excess 1024 binary exponent
+ normalized 53 bit fraction, redundant bit not represented
+ approximately 15 decimal digits precision
+
+ The values to use if we trust decimal to binary conversions:
+#define MAX_G_FLOAT .898846567431157e+308
+#define MIN_G_FLOAT .556268464626800e-308
+*/
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for the vax. */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (GET_CODE (EXP) == SET) \
+ { if (GET_CODE (SET_SRC (EXP)) == CALL) \
+ CC_STATUS_INIT; \
+ else if (GET_CODE (SET_DEST (EXP)) != PC) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (EXP); \
+ cc_status.value2 = SET_SRC (EXP); } } \
+ else if (GET_CODE (EXP) == PARALLEL \
+ && GET_CODE (XVECEXP (EXP, 0, 0)) == SET \
+ && GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) != PC) \
+ { cc_status.flags = 0; \
+ cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \
+ cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); } \
+ /* PARALLELs whose first element sets the PC are aob, sob insns. \
+ They do change the cc's. So drop through and forget the cc's. */ \
+ else CC_STATUS_INIT; \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \
+ && cc_status.value2 \
+ && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \
+ cc_status.value2 = 0; \
+ if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM \
+ && cc_status.value2 \
+ && GET_CODE (cc_status.value2) == MEM) \
+ cc_status.value2 = 0; }
+/* Actual condition, one line up, should be that value2's address
+ depends on value1, but that is too much of a pain. */
+
+#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
+{ if (cc_status.flags & CC_NO_OVERFLOW) \
+ return NO_OV; \
+ return NORMAL; }
+
+/* Control the assembler format that we output. */
+
+/* Output at beginning of assembler file. */
+
+#define ASM_FILE_START(FILE) fprintf (FILE, "#NO_APP\n");
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#define DATA_SECTION_ASM_OP ".data"
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \
+ "r9", "r10", "r11", "ap", "fp", "sp", "pc"}
+
+/* This is BSD, so it wants DBX format. */
+
+#define DBX_DEBUGGING_INFO
+
+/* How to renumber registers for dbx and gdb.
+ Vax needs no change in the numeration. */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* Do not break .stabs pseudos into continuations. */
+
+#define DBX_CONTIN_LENGTH 0
+
+/* This is the char to use for continuation (in case we need to turn
+ continuation back on). */
+
+#define DBX_CONTIN_CHAR '?'
+
+/* Don't use the `xsfoo;' construct in DBX output; this system
+ doesn't support it. */
+
+#define DBX_NO_XREFS
+
+/* Output the .stabs for a C `static' variable in the data section. */
+#define DBX_STATIC_STAB_DATA_SECTION
+
+/* Vax specific: which type character is used for type double? */
+
+#define ASM_DOUBLE_CHAR (TARGET_G_FLOAT ? 'g' : 'd')
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
+ do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ fprintf (FILE, "_%s", NAME)
+
+/* This is how to output an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class. */
+
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
+ fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf (LABEL, "*%s%d", PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant.
+ It is .dfloat or .gfloat, depending. */
+
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.%cfloat 0%c%.20e\n", ASM_DOUBLE_CHAR, \
+ ASM_DOUBLE_CHAR, (VALUE))
+
+/* This is how to output an assembler line defining a `float' constant. */
+
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE,VALUE) \
+( fprintf (FILE, "\t.word "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE,VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* This is how to output an insn to push a register on the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
+ fprintf (FILE, "\tpushl %s\n", reg_names[REGNO])
+
+/* This is how to output an insn to pop a register from the stack.
+ It need not be very fast code. */
+
+#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
+ fprintf (FILE, "\tmovl (sp)+,%s\n", reg_names[REGNO])
+
+/* This is how to output an element of a case-vector that is absolute.
+ (The Vax does not use such vectors,
+ but we must define this macro anyway.) */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
+ fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL)
+
+/* This is how to output an assembler line
+ that says to advance the location counter
+ to a multiple of 2**LOG bytes. */
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+/* This is how to output an assembler line
+ that says to advance the location counter by SIZE bytes. */
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %u\n", (SIZE))
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%d\n", (ROUNDED)))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Print an instruction operand X on file FILE.
+ CODE is the code from the %-spec that requested printing this operand;
+ if `%z3' was used to print operand 3, then CODE is 'z'.
+ On the Vax, the only code used is `#', indicating that either
+ `d' or `g' should be printed, depending on whether we're using dfloat
+ or gfloat. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '#')
+
+#define PRINT_OPERAND(FILE, X, CODE) \
+{ if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE); \
+ else if (GET_CODE (X) == REG) \
+ fprintf (FILE, "%s", reg_names[REGNO (X)]); \
+ else if (GET_CODE (X) == MEM) \
+ output_address (XEXP (X, 0)); \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
+ { union { double d; int i[2]; } u; \
+ u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
+ fprintf (FILE, "$0%c%.20e", ASM_DOUBLE_CHAR, u.d); } \
+ else { putc ('$', FILE); output_addr_const (FILE, X); }}
+
+/* Print a memory operand whose address is X, on file FILE.
+ This uses a function in output-vax.c. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
+ print_operand_address (FILE, ADDR)
diff --git a/gcc-1.40/config/tm-vaxv.h b/gcc-1.40/config/tm-vaxv.h
new file mode 100644
index 0000000..78fbf05
--- /dev/null
+++ b/gcc-1.40/config/tm-vaxv.h
@@ -0,0 +1,62 @@
+/* Definitions of target machine for GNU compiler. Vax sysV version.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-vax.h"
+
+/* Cope with these under SysV */
+
+#define SCCS_DIRECTIVE
+
+/* Output #ident as a .ident. */
+
+#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
+
+#undef DBX_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO
+
+/* The .file command should always begin the output. */
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) sdbout_filename ((FILE), main_input_filename)
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf(FILE, "\t.align %d\n", 1 << (LOG))
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_LOCAL(FILE,NAME,SIZE,ROUNDED) \
+( data_section (), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ":\n\t.space %u\n", (ROUNDED)))
+
+#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
+{ \
+ char *s; \
+ int i; \
+ for (i = 0, s = (PTR); i < (LEN); s++, i++) \
+ { \
+ if ((i % 8) == 0) \
+ fputs ("\n\t.byte\t", (FILE)); \
+ fprintf ((FILE), "%s0x%x", (i%8?",":""), (unsigned)*s); \
+ } \
+ fputs ("\n", (FILE)); \
+}
+
+#undef ASM_OUTPUT_DOUBLE
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
diff --git a/gcc-1.40/config/tm-vms.h b/gcc-1.40/config/tm-vms.h
new file mode 100644
index 0000000..2e91a73
--- /dev/null
+++ b/gcc-1.40/config/tm-vms.h
@@ -0,0 +1,117 @@
+/* Output variables, constants and external declarations, for GNU compiler.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define NO_EXTERNAL_INDIRECT_ADDRESS /* Alter some macro definitions. */
+#include "tm-vax.h"
+
+#undef CPP_PREDEFINES
+#undef TARGET_VERSION
+#undef TARGET_DEFAULT
+#undef CALL_USED_REGISTERS
+#undef MAYBE_VMS_FUNCTION_PROLOGUE
+
+/* Predefine this in CPP because VMS limits the size of command options
+ and GNU CPP is not used on VMS except with GNU C. */
+#define CPP_PREDEFINES "-Dvax -Dvms -DVMS -D__GNU__ -D__GNUC__"
+
+/* By default, allow $ to be part of an identifier. */
+#define DOLLARS_IN_IDENTIFIERS 1
+
+#define TARGET_DEFAULT 1
+#define TARGET_VERSION fprintf (stderr, " (vax vms)");
+
+#define CALL_USED_REGISTERS {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
+
+#define __MAIN_NAME " main ("
+/*
+ * The MAYBE_VMS_FUNCTION_PROLOGUE macro works for both gcc and g++. It
+ * first checks to see if the current routine is "main", which will only
+ * happen for GCC, and add the jsb if it is. If is not the case then try and
+ * see if __MAIN_NAME is part of current_function_name, which will only happen
+ * if we are running g++, and add the jsb if it is. In gcc there should never
+ * be a space in the function name, and in g++ there is always a "(" in the
+ * function name, thus there should never be any confusion.
+ */
+#define MAYBE_VMS_FUNCTION_PROLOGUE(FILE) \
+{ extern char *current_function_name; \
+ if (!strcmp ("main", current_function_name)) \
+ fprintf(FILE, "\tjsb _c$main_args\n"); \
+ else { \
+ char *p = current_function_name; \
+ while (*p != '\0') \
+ if (*p == *__MAIN_NAME) \
+ if (strncmp(p, __MAIN_NAME, (sizeof __MAIN_NAME)-1) == 0) {\
+ fprintf(FILE, "\tjsb _c$main_args\n");\
+ break; \
+ } else \
+ p++; \
+ else \
+ p++; \
+ }; \
+}
+
+#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) \
+{ if (DECL_INITIAL (DECL) == 0 && TREE_CODE (DECL) != FUNCTION_DECL) \
+ { \
+ if (TREE_READONLY (decl) && ! TREE_VOLATILE (decl)) \
+ const_section (); \
+ else \
+ data_section (); \
+ fputs (".comm ", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",0\n"); \
+ } \
+}
+
+#define NO_DOLLAR_IN_LABEL
+
+#define EXTRA_SECTIONS in_const
+
+#define EXTRA_SECTION_FUNCTIONS \
+const_section () \
+{ \
+ if (in_section != in_const) { \
+ fprintf(asm_out_file,".const\n"); \
+ in_section = in_const; \
+ } \
+}
+
+#define SELECT_SECTION(T) \
+{ \
+ if (TREE_CODE (T) == VAR_DECL) \
+ { \
+ if (TREE_READONLY (T) && ! TREE_VOLATILE (T)) \
+ { \
+ if (TREE_PUBLIC (T)) \
+ const_section (); \
+ else \
+ text_section (); \
+ } \
+ else \
+ data_section (); \
+ } \
+ if (*tree_code_type[(int) TREE_CODE (T)] == 'c') \
+ { \
+ if ((TREE_CODE (T) == STRING_CST && flag_writable_strings)) \
+ data_section (); \
+ else \
+ text_section (); \
+ } \
+}
+
diff --git a/gcc-1.40/config/vax.md b/gcc-1.40/config/vax.md
new file mode 100644
index 0000000..ae8611c
--- /dev/null
+++ b/gcc-1.40/config/vax.md
@@ -0,0 +1,2166 @@
+
+;;- Machine description for GNU compiler
+;;- Vax Version
+;; Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 1, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- Instruction patterns. When multiple patterns apply,
+;;- the first one in the file is chosen.
+;;-
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+;;-
+;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
+;;- updates for most instructions.
+
+; tstsi is first test insn so that it is the one to match
+; a constant argument.
+
+(define_insn "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "general_operand" "g"))]
+ ""
+ "tstl %0")
+
+(define_insn "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "general_operand" "g"))]
+ ""
+ "tstw %0")
+
+(define_insn "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "general_operand" "g"))]
+ ""
+ "tstb %0")
+
+(define_insn "tstdf"
+ [(set (cc0)
+ (match_operand:DF 0 "general_operand" "gF"))]
+ ""
+ "tst%# %0")
+
+(define_insn "tstsf"
+ [(set (cc0)
+ (match_operand:SF 0 "general_operand" "gF"))]
+ ""
+ "tstf %0")
+
+;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cmpl %0,%1")
+
+(define_insn "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "general_operand" "g")
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cmpw %0,%1")
+
+(define_insn "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "cmpb %0,%1")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "general_operand" "gF")
+ (match_operand:DF 1 "general_operand" "gF")))]
+ ""
+ "cmp%# %0,%1")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "general_operand" "gF")
+ (match_operand:SF 1 "general_operand" "gF")))]
+ ""
+ "cmpf %0,%1")
+
+(define_insn ""
+ [(set (cc0)
+ (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "bitl %0,%1")
+
+(define_insn ""
+ [(set (cc0)
+ (and:HI (match_operand:HI 0 "general_operand" "g")
+ (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "bitw %0,%1")
+
+(define_insn ""
+ [(set (cc0)
+ (and:QI (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "bitb %0,%1")
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (match_operand:DF 1 "general_operand" "gF"))]
+ ""
+ "*
+{
+ if (operands[1] == dconst0_rtx)
+ return \"clr%# %0\";
+ return \"mov%# %1,%0\";
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (match_operand:SF 1 "general_operand" "gF"))]
+ ""
+ "*
+{
+ if (operands[1] == fconst0_rtx)
+ return \"clrf %0\";
+ return \"movf %1,%0\";
+}")
+
+;; Some vaxes don't support this instruction.
+;;(define_insn "movti"
+;; [(set (match_operand:TI 0 "general_operand" "=g")
+;; (match_operand:TI 1 "general_operand" "g"))]
+;; ""
+;; "movh %1,%0")
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=g")
+ (match_operand:DI 1 "general_operand" "g"))]
+ ""
+ "movq %1,%0")
+
+;; This handles constants which are not legitimate
+;; for the sake of shared libraries on VMS.
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "" "i"))]
+ "CONSTANT_P (operands[1]) && ! LEGITIMATE_CONSTANT_P (operands[1])"
+ "*
+{
+ operands[2] = XEXP (XEXP (operands[1], 0), 0);
+ operands[1] = XEXP (XEXP (operands[1], 0), 1);
+ return \"movl %2,%0\;addl2 %1,%0\";
+}")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "supergeneral_operand" "g"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ /* Make sure the insn that stored the 0 is still present. */
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ /* Make sure cross jumping didn't happen here. */
+ && no_labels_between_p (XEXP (link, 0), insn))
+ /* Fastest way to change a 0 to a 1. */
+ return \"incl %0\";
+ if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST)
+ {
+ if (push_operand (operands[0], SImode))
+ return \"pushab %a1\";
+ return \"movab %a1,%0\";
+ }
+ /* this is slower than a movl, except when pushing an operand */
+ if (operands[1] == const0_rtx)
+ return \"clrl %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) >= 64)
+ {
+ int i = INTVAL (operands[1]);
+ if ((unsigned)(~i) < 64)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, ~i);
+ return \"mcoml %1,%0\";
+ }
+ if ((unsigned)i < 127)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, 63);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, i-63);
+ return \"addl3 %2,%1,%0\";
+ }
+ /* trading speed for space */
+ if ((unsigned)i < 0x100)
+ return \"movzbl %1,%0\";
+ if (i >= -0x80 && i < 0)
+ return \"cvtbl %1,%0\";
+ if ((unsigned)i < 0x10000)
+ return \"movzwl %1,%0\";
+ if (i >= -0x8000 && i < 0)
+ return \"cvtwl %1,%0\";
+ }
+ if (push_operand (operands[0], SImode))
+ return \"pushl %1\";
+ return \"movl %1,%0\";
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ rtx link;
+ if (operands[1] == const1_rtx
+ && (link = find_reg_note (insn, REG_WAS_0, 0))
+ /* Make sure the insn that stored the 0 is still present. */
+ && ! XEXP (link, 0)->volatil
+ && GET_CODE (XEXP (link, 0)) != NOTE
+ /* Make sure cross jumping didn't happen here. */
+ && no_labels_between_p (XEXP (link, 0), insn))
+ /* Fastest way to change a 0 to a 1. */
+ return \"incw %0\";
+ if (operands[1] == const0_rtx)
+ return \"clrw %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) >= 64)
+ {
+ int i = INTVAL (operands[1]);
+ if ((unsigned)((~i) & 0xffff) < 64)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, (~i) & 0xffff);
+ return \"mcomw %1,%0\";
+ }
+ if ((unsigned)(i & 0xffff) < 127)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, 63);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (i-63) & 0xffff);
+ return \"addw3 %2,%1,%0\";
+ }
+ /* this is a lot slower, and only saves 1 measly byte! */
+ /* if ((unsigned)i < 0x100)
+ return \"movzbw %1,%0\"; */
+ /* if (i >= -0x80 && i < 0)
+ return \"cvtbw %1,%0\"; */
+ }
+ return \"movw %1,%0\";
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+{
+ if (operands[1] == const0_rtx)
+ return \"clrb %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && (unsigned) INTVAL (operands[1]) >= 64)
+ {
+ int i = INTVAL (operands[1]);
+ if ((unsigned)((~i) & 0xff) < 64)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, (~i) & 0xff);
+ return \"mcomb %1,%0\";
+ }
+#if 0
+ /* ASCII alphabetics */
+ if (((unsigned) INTVAL (operands[1]) &0xff) < 127)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, 63);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, i-63);
+ return \"addb3 %2,%1,%0\";
+ }
+#endif
+ }
+ return \"movb %1,%0\";
+}")
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+(define_insn "movstrhi"
+ [(set (match_operand:BLK 0 "general_operand" "=g")
+ (match_operand:BLK 1 "general_operand" "g"))
+ (use (match_operand:HI 2 "general_operand" "g"))
+ (clobber (reg:SI 0))
+ (clobber (reg:SI 1))
+ (clobber (reg:SI 2))
+ (clobber (reg:SI 3))
+ (clobber (reg:SI 4))
+ (clobber (reg:SI 5))]
+ ""
+ "movc3 %2,%1,%0")
+
+;; Extension and truncation insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+(define_insn "truncsiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtlb %1,%0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (truncate:HI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtlw %1,%0")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (truncate:QI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cvtwb %1,%0")
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cvtwl %1,%0")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "cvtbw %1,%0")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (sign_extend:SI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "cvtbl %1,%0")
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (float_extend:DF (match_operand:SF 1 "general_operand" "gF")))]
+ ""
+ "cvtf%# %1,%0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))]
+ ""
+ "cvt%#f %1,%0")
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "movzwl %1,%0")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movzbw %1,%0")
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (zero_extend:SI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "movzbl %1,%0")
+
+;; Fix-to-float conversion insns.
+;; Note that the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (float:SF (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtlf %1,%0")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (float:DF (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "cvtl%# %1,%0")
+
+(define_insn "floathisf2"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (float:SF (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cvtwf %1,%0")
+
+(define_insn "floathidf2"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (float:DF (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "cvtw%# %1,%0")
+
+(define_insn "floatqisf2"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (float:SF (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "cvtbf %1,%0")
+
+(define_insn "floatqidf2"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (float:DF (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "cvtb%# %1,%0")
+
+;; Float-to-fix conversion insns.
+
+(define_insn "fix_truncsfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))]
+ ""
+ "cvtfb %1,%0")
+
+(define_insn "fix_truncsfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))]
+ ""
+ "cvtfw %1,%0")
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))]
+ ""
+ "cvtfl %1,%0")
+
+(define_insn "fix_truncdfqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))]
+ ""
+ "cvt%#b %1,%0")
+
+(define_insn "fix_truncdfhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))]
+ ""
+ "cvt%#w %1,%0")
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))]
+ ""
+ "cvt%#l %1,%0")
+
+;;- All kinds of add instructions.
+
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (plus:DF (match_operand:DF 1 "general_operand" "gF")
+ (match_operand:DF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"add%#2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"add%#2 %1,%0\";
+ return \"add%#3 %1,%2,%0\";
+}")
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (plus:SF (match_operand:SF 1 "general_operand" "gF")
+ (match_operand:SF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"addf2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addf2 %1,%0\";
+ return \"addf3 %1,%2,%0\";
+}")
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (plus:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incl %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == -1)
+ return \"decl %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subl2 $%n2,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) INTVAL (operands[2]) >= 64
+ && GET_CODE (operands[1]) == REG)
+ return \"movab %c2(%1),%0\";
+ return \"addl2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addl2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subl3 $%n2,%1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) INTVAL (operands[2]) >= 64
+ && GET_CODE (operands[1]) == REG)
+ {
+ if (push_operand (operands[0], SImode))
+ return \"pushab %c2(%1)\";
+ return \"movab %c2(%1),%0\";
+ }
+ return \"addl3 %1,%2,%0\";
+}")
+
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (plus:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incw %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ return \"decw %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subw2 $%n2,%0\";
+ return \"addw2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addw2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subw3 $%n2,%1,%0\";
+ return \"addw3 %1,%2,%0\";
+}")
+
+(define_insn "addqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (plus:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"incb %0\";
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) == -1)
+ return \"decb %0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subb2 $%n2,%0\";
+ return \"addb2 %2,%0\";
+ }
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"addb2 %1,%0\";
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (unsigned) (- INTVAL (operands[2])) < 64)
+ return \"subb3 $%n2,%1,%0\";
+ return \"addb3 %1,%2,%0\";
+}")
+
+;;- All kinds of subtract instructions.
+
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (minus:DF (match_operand:DF 1 "general_operand" "gF")
+ (match_operand:DF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"sub%#2 %2,%0\";
+ return \"sub%#3 %2,%1,%0\";
+}")
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (minus:SF (match_operand:SF 1 "general_operand" "gF")
+ (match_operand:SF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"subf2 %2,%0\";
+ return \"subf3 %2,%1,%0\";
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (minus:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decl %0\";
+ return \"subl2 %2,%0\";
+ }
+ return \"subl3 %2,%1,%0\";
+}")
+
+(define_insn "subhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (minus:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decw %0\";
+ return \"subw2 %2,%0\";
+ }
+ return \"subw3 %2,%1,%0\";
+}")
+
+(define_insn "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (minus:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ if (operands[2] == const1_rtx)
+ return \"decb %0\";
+ return \"subb2 %2,%0\";
+ }
+ return \"subb3 %2,%1,%0\";
+}")
+
+;;- Multiply instructions.
+
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (mult:DF (match_operand:DF 1 "general_operand" "gF")
+ (match_operand:DF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mul%#2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mul%#2 %1,%0\";
+ return \"mul%#3 %1,%2,%0\";
+}")
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (mult:SF (match_operand:SF 1 "general_operand" "gF")
+ (match_operand:SF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mulf2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mulf2 %1,%0\";
+ return \"mulf3 %1,%2,%0\";
+}")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (mult:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mull2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mull2 %1,%0\";
+ return \"mull3 %1,%2,%0\";
+}")
+
+(define_insn "mulhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (mult:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mulw2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mulw2 %1,%0\";
+ return \"mulw3 %1,%2,%0\";
+}")
+
+(define_insn "mulqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (mult:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"mulb2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"mulb2 %1,%0\";
+ return \"mulb3 %1,%2,%0\";
+}")
+
+;;- Divide instructions.
+
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (div:DF (match_operand:DF 1 "general_operand" "gF")
+ (match_operand:DF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"div%#2 %2,%0\";
+ return \"div%#3 %2,%1,%0\";
+}")
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (div:SF (match_operand:SF 1 "general_operand" "gF")
+ (match_operand:SF 2 "general_operand" "gF")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"divf2 %2,%0\";
+ return \"divf3 %2,%1,%0\";
+}")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (div:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"divl2 %2,%0\";
+ return \"divl3 %2,%1,%0\";
+}")
+
+(define_insn "divhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (div:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"divw2 %2,%0\";
+ return \"divw3 %2,%1,%0\";
+}")
+
+(define_insn "divqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (div:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"divb2 %2,%0\";
+ return \"divb3 %2,%1,%0\";
+}")
+
+;This is left out because it is very slow;
+;we are better off programming around the "lack" of this insn.
+;(define_insn "divmoddisi4"
+; [(set (match_operand:SI 0 "general_operand" "=g")
+; (div:SI (match_operand:DI 1 "general_operand" "g")
+; (match_operand:SI 2 "general_operand" "g")))
+; (set (match_operand:SI 3 "general_operand" "=g")
+; (mod:SI (match_operand:DI 1 "general_operand" "g")
+; (match_operand:SI 2 "general_operand" "g")))]
+; ""
+; "ediv %2,%1,%0,%3")
+
+;; Bit-and on the vax is done with a clear-bits insn.
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "g")
+ (not:SI (match_operand:SI 2 "general_operand" "g"))))]
+ ""
+ "
+{
+ extern rtx expand_unop ();
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ else
+ operands[2] = expand_unop (SImode, one_cmpl_optab, operands[2], 0, 1);
+}")
+
+(define_expand "andhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "g")
+ (not:HI (match_operand:HI 2 "general_operand" "g"))))]
+ ""
+ "
+{
+ extern rtx expand_unop ();
+ rtx op = operands[2];
+ if (GET_CODE (op) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ ((1 << 16) - 1) & ~INTVAL (op));
+ else
+ operands[2] = expand_unop (HImode, one_cmpl_optab, op, 0, 1);
+}")
+
+(define_expand "andqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "g")
+ (not:QI (match_operand:QI 2 "general_operand" "g"))))]
+ ""
+ "
+{
+ extern rtx expand_unop ();
+ rtx op = operands[2];
+ if (GET_CODE (op) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ ((1 << 8) - 1) & ~INTVAL (op));
+ else
+ operands[2] = expand_unop (QImode, one_cmpl_optab, op, 0, 1);
+}")
+
+(define_insn "andcbsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "g")
+ (not:SI (match_operand:SI 2 "general_operand" "g"))))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bicl2 %2,%0\";
+ return \"bicl3 %2,%1,%0\";
+}")
+
+(define_insn "andcbhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "g")
+ (not:HI (match_operand:HI 2 "general_operand" "g"))))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bicw2 %2,%0\";
+ return \"bicw3 %2,%1,%0\";
+}")
+
+(define_insn "andcbqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "g")
+ (not:QI (match_operand:QI 2 "general_operand" "g"))))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bicb2 %2,%0\";
+ return \"bicb3 %2,%1,%0\";
+}")
+
+;; The following are needed because constant propagation can
+;; create them starting from the bic insn patterns above.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (and:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{ operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ if (rtx_equal_p (operands[1], operands[0]))
+ return \"bicl2 %2,%0\";
+ return \"bicl3 %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (and:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{ operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff & ~INTVAL (operands[2]));
+ if (rtx_equal_p (operands[1], operands[0]))
+ return \"bicw2 %2,%0\";
+ return \"bicw3 %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (and:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT"
+ "*
+{ operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xff & ~INTVAL (operands[2]));
+ if (rtx_equal_p (operands[1], operands[0]))
+ return \"bicb2 %2,%0\";
+ return \"bicb3 %2,%1,%0\";
+}")
+
+;;- Bit set instructions.
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ior:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bisl2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"bisl2 %1,%0\";
+ return \"bisl3 %2,%1,%0\";
+}")
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (ior:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bisw2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"bisw2 %1,%0\";
+ return \"bisw3 %2,%1,%0\";
+}")
+
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (ior:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"bisb2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"bisb2 %1,%0\";
+ return \"bisb3 %2,%1,%0\";
+}")
+
+;;- xor instructions.
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (xor:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"xorl2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"xorl2 %1,%0\";
+ return \"xorl3 %2,%1,%0\";
+}")
+
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (xor:HI (match_operand:HI 1 "general_operand" "g")
+ (match_operand:HI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"xorw2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"xorw2 %1,%0\";
+ return \"xorw3 %2,%1,%0\";
+}")
+
+(define_insn "xorqi3"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (xor:QI (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (rtx_equal_p (operands[0], operands[1]))
+ return \"xorb2 %2,%0\";
+ if (rtx_equal_p (operands[0], operands[2]))
+ return \"xorb2 %1,%0\";
+ return \"xorb3 %2,%1,%0\";
+}")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "general_operand" "=g")
+ (neg:DF (match_operand:DF 1 "general_operand" "gF")))]
+ ""
+ "mneg%# %1,%0")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "general_operand" "=g")
+ (neg:SF (match_operand:SF 1 "general_operand" "gF")))]
+ ""
+ "mnegf %1,%0")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (neg:SI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "mnegl %1,%0")
+
+(define_insn "neghi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (neg:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "mnegw %1,%0")
+
+(define_insn "negqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (neg:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "mnegb %1,%0")
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (not:SI (match_operand:SI 1 "general_operand" "g")))]
+ ""
+ "mcoml %1,%0")
+
+(define_insn "one_cmplhi2"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (not:HI (match_operand:HI 1 "general_operand" "g")))]
+ ""
+ "mcomw %1,%0")
+
+(define_insn "one_cmplqi2"
+ [(set (match_operand:QI 0 "general_operand" "=g")
+ (not:QI (match_operand:QI 1 "general_operand" "g")))]
+ ""
+ "mcomb %1,%0")
+
+;; Arithmetic right shift on the vax works by negating the shift count.
+(define_expand "ashrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (QImode, operands[2]);
+}")
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (ashift:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+{
+ if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
+ return \"addl2 %0,%0\";
+ if (GET_CODE (operands[1]) == REG
+ && GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+ if (i == 1)
+ return \"addl3 %1,%1,%0\";
+ if (i == 2)
+ return \"moval 0[%1],%0\";
+ if (i == 3)
+ return \"movad 0[%1],%0\";
+ }
+ return \"ashl %2,%1,%0\";
+}")
+
+;; Arithmetic right shift on the vax works by negating the shift count.
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "general_operand" "=g")
+ (ashift:DI (match_operand:DI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (QImode, operands[2]);
+}")
+
+(define_insn "ashldi3"
+ [(set (match_operand:DI 0 "general_operand" "=g")
+ (ashift:DI (match_operand:DI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "ashq %2,%1,%0")
+
+;; Rotate right on the vax works by negating the shift count.
+(define_expand "rotrsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (rotate:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "
+{
+ operands[2] = negate_rtx (QImode, operands[2]);
+}")
+
+(define_insn "rotlsi3"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (rotate:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "rotl %2,%1,%0")
+
+;This insn is probably slower than a multiply and an add.
+;(define_insn ""
+; [(set (match_operand:SI 0 "general_operand" "=g")
+; (mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g")
+; (match_operand:SI 2 "general_operand" "g"))
+; (match_operand:SI 3 "general_operand" "g")))]
+; ""
+; "index %1,$0x80000000,$0x7fffffff,%3,%2,%0")
+
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+ro")
+ (match_operand:SI 1 "immediate_operand" "i")
+ (match_operand:SI 2 "immediate_operand" "i"))
+ (match_operand:SI 3 "general_operand" "g"))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+ && (GET_CODE (operands[0]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ if (REG_P (operands[0]))
+ {
+ if (INTVAL (operands[2]) != 0)
+ return \"insv %3,%2,%1,%0\";
+ }
+ else
+ operands[0]
+ = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+
+ if (INTVAL (operands[1]) == 8)
+ return \"movb %3,%0\";
+ return \"movw %3,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=&g")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "ro")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[3]) != 0)
+ return \"extzv %3,%2,%1,%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"movzbl %1,%0\";
+ return \"movzwl %1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "ro")
+ (match_operand:SI 2 "immediate_operand" "i")
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+ && GET_CODE (operands[3]) == CONST_INT
+ && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
+ && (GET_CODE (operands[1]) == REG
+ || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ "*
+{
+ if (REG_P (operands[1]))
+ {
+ if (INTVAL (operands[3]) != 0)
+ return \"extv %3,%2,%1,%0\";
+ }
+ else
+ operands[1]
+ = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+ if (INTVAL (operands[2]) == 8)
+ return \"cvtbl %1,%0\";
+ return \"cvtwl %1,%0\";
+}")
+
+;; Register-only SImode cases of bit-field insns.
+
+(define_insn ""
+ [(set (cc0)
+ (compare
+ (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "cmpv %2,%1,%0,%3")
+
+(define_insn ""
+ [(set (cc0)
+ (compare
+ (zero_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "cmpzv %2,%1,%0,%3")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "r")
+ (match_operand:SI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "extv %3,%2,%1,%0")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "r")
+ (match_operand:SI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "extzv %3,%2,%1,%0")
+
+;; Non-register cases.
+;; nonimmediate_operand is used to make sure that mode-ambiguous cases
+;; don't match these (and therefore match the cases above instead).
+
+(define_insn ""
+ [(set (cc0)
+ (compare
+ (sign_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "cmpv %2,%1,%0,%3")
+
+(define_insn ""
+ [(set (cc0)
+ (compare
+ (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "cmpzv %2,%1,%0,%3")
+
+(define_insn "extv"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "rm")
+ (match_operand:SI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "extv %3,%2,%1,%0")
+
+(define_insn "extzv"
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "rm")
+ (match_operand:SI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "g")))]
+ ""
+ "extzv %3,%2,%1,%0")
+
+(define_insn "insv"
+ [(set (zero_extract:SI (match_operand:QI 0 "general_operand" "+g")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g"))]
+ ""
+ "insv %3,%2,%1,%0")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+ (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g"))
+ (match_operand:SI 3 "general_operand" "g"))]
+ ""
+ "insv %3,%2,%1,%0")
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "jbr %l0")
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jeql %l0")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jneq %l0")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgtr %l0")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgtru %l0")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlss %l0")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlssu %l0")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgeq %l0")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jgequ %l0")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jleq %l0")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "jlequ %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jneq %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jeql %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jleq %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlequ %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgeq %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgequ %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlss %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jlssu %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgtr %l0")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "jgtru %l0")
+
+;; Recognize jlbs and jlbc insns.
+;; These come before the jbc and jbs recognizers so these will be preferred.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int 1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbs %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int 1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbc %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int 1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbc %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int 1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbs %0,%l1")
+
+;; These four entries allow a jlbc or jlbs to be made
+;; by combination with a bic.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbs %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbc %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbc %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (not:SI (const_int -2)))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jlbs %0,%l1")
+
+;; Recognize jbs and jbc instructions.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:QI 0 "general_operand" "g")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "jbs %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:QI 0 "general_operand" "g")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "jbc %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:QI 0 "general_operand" "g")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "jbc %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:QI 0 "general_operand" "g")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "jbs %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jbs %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jbc %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && exact_log2 (INTVAL (operands[1])) >= 0
+ && (GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"jbs %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && exact_log2 (INTVAL (operands[1])) >= 0
+ && (GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"jbc %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && exact_log2 (INTVAL (operands[1])) >= 0
+ && (GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"jbc %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (and:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && exact_log2 (INTVAL (operands[1])) >= 0
+ && (GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ "*
+{
+ operands[1]
+ = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1])));
+ return \"jbs %1,%0,%l2\";
+}")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jbc %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ "GET_CODE (operands[0]) != MEM
+ || ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ "jbs %1,%0,%l2")
+
+;; Subtract-and-jump and Add-and-jump insns.
+;; These are not used when output is for the Unix assembler
+;; because it does not know how to modify them to reach far.
+
+;; Normal sob insns.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (gt (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_UNIX_ASM"
+ "jsobgtr %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_UNIX_ASM"
+ "jsobgeq %0,%l1")
+
+;; Reversed sob insns.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (le (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_UNIX_ASM"
+ "jsobgtr %0,%l1")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (lt (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int -1))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ "!TARGET_UNIX_ASM"
+ "jsobgeq %0,%l1")
+
+;; Normal aob insns.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (lt (compare (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ "!TARGET_UNIX_ASM"
+ "jaoblss %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (le (compare (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ "!TARGET_UNIX_ASM"
+ "jaobleq %1,%0,%l2")
+
+;; Reverse aob insns.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ge (compare (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ "!TARGET_UNIX_ASM"
+ "jaoblss %1,%0,%l2")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (gt (compare (plus:SI (match_operand:SI 0 "general_operand" "+g")
+ (const_int 1))
+ (match_operand:SI 1 "general_operand" "g"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ "!TARGET_UNIX_ASM"
+ "jaobleq %1,%0,%l2")
+
+;; Something like a sob insn, but compares against -1.
+;; This finds `while (foo--)' which was changed to `while (--foo != -1)'.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (compare (plus:SI (match_operand:SI 0 "general_operand" "g")
+ (const_int -1))
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "decl %0\;jgequ %l1")
+
+;; Note that operand 1 is total size of args, in bytes,
+;; and what the call insn wants is the number of words.
+(define_insn "call"
+ [(call (match_operand:QI 0 "general_operand" "g")
+ (match_operand:QI 1 "general_operand" "g"))]
+ ""
+ "*
+ if (INTVAL (operands[1]) > 255 * 4)
+ /* Vax `calls' really uses only one byte of #args, so pop explicitly. */
+ return \"calls $0,%0\;addl2 %1,sp\";
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 3)/ 4);
+ return \"calls %1,%0\";
+")
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=g")
+ (call (match_operand:QI 1 "general_operand" "g")
+ (match_operand:QI 2 "general_operand" "g")))]
+ ""
+ "*
+ if (INTVAL (operands[2]) > 255 * 4)
+ /* Vax `calls' really uses only one byte of #args, so pop explicitly. */
+ return \"calls $0,%1\;addl2 %2,sp\";
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 3)/ 4);
+ return \"calls %2,%1\";
+")
+
+(define_insn "return"
+ [(return)]
+ ""
+ "ret")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+(define_insn "casesi"
+ [(set (pc)
+ (if_then_else (le (minus:SI (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (match_operand:SI 2 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (minus:SI (match_dup 0)
+ (match_dup 1)))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,%1,%2")
+
+;; This used to arise from the preceding by simplification
+;; if operand 1 is zero. Perhaps it is no longer necessary.
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (minus:SI (match_dup 0)
+ (const_int 0)))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,$0,%1")
+
+;; This arises from the preceding by simplification if operand 1 is zero.
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (match_operand:SI 0 "general_operand" "g")
+ (match_operand:SI 1 "general_operand" "g"))
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (match_dup 0))))
+ (label_ref:SI (match_operand 3 "" "")))
+ (pc)))]
+ ""
+ "casel %0,$0,%1")
+
+;; This arises from casesi if operand 0 is a constant, in range.
+(define_insn ""
+ [(set (pc)
+ (plus:SI (sign_extend:SI
+ (mem:HI (plus:SI (pc)
+ (match_operand:SI 0 "general_operand" "g"))))
+ (label_ref:SI (match_operand 3 "" ""))))]
+ ""
+ "casel %0,$0,%0")
+
+;; This arises from the above if both operands are the same.
+(define_insn ""
+ [(set (pc)
+ (plus:SI (sign_extend:SI (mem:HI (pc)))
+ (label_ref:SI (match_operand 3 "" ""))))]
+ ""
+ "casel $0,$0,$0")
+
+;;- load or push effective address
+;; These come after the move and add/sub patterns
+;; because we don't want pushl $1 turned into pushad 1.
+;; or addl3 r1,r2,r3 turned into movab 0(r1)[r2],r3.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:QI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushab %a1\";
+ return \"movab %a1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:HI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushaw %a1\";
+ return \"movaw %a1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SI 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushal %a1\";
+ return \"moval %a1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:SF 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushaf %a1\";
+ return \"movaf %a1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=g")
+ (match_operand:DF 1 "address_operand" "p"))]
+ ""
+ "*
+{
+ if (push_operand (operands[0], SImode))
+ return \"pushad %a1\";
+ return \"movad %a1,%0\";
+}")
+
+;; Optimize extzv ...,z; andl2 ...,z
+;; with other operands constant.
+(define_peephole
+ [(set (match_operand:SI 0 "general_operand" "g")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")
+ (match_operand:SI 3 "general_operand" "g")))
+ (set (match_operand:SI 4 "general_operand" "g")
+ (and:SI (match_dup 0)
+ (match_operand:SI 5 "general_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[3]) == CONST_INT
+ && (INTVAL (operands[2]) + INTVAL (operands[3])) == 32
+ && GET_CODE (operands[5]) == CONST_INT
+ && dead_or_set_p (insn, operands[0])"
+ "*
+{
+ unsigned long mask = INTVAL (operands[5]);
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[3]));
+
+ if ((floor_log2 (mask) + 1) >= INTVAL (operands[2]))
+ mask &= ((1 << INTVAL (operands[2])) - 1);
+
+ operands[5] = gen_rtx (CONST_INT, VOIDmode, ~mask);
+ if (push_operand (operands[4], SImode))
+ {
+ output_asm_insn (\"rotl %3,%1,%0\", operands);
+ return \"bicl3 %5,%0,%4\";
+ }
+ else
+ {
+ output_asm_insn (\"rotl %3,%1,%4\", operands);
+ return \"bicl2 %5,%4\";
+ }
+}")
+
+;; Optimize andl3 x,y,z; extzv z,....,z
+
+(define_peephole
+ [(set (match_operand:SI 0 "general_operand" "g")
+ (and:SI (match_operand:SI 1 "general_operand" "g")
+ (match_operand:SI 2 "general_operand" "g")))
+ (set (match_operand 3 "general_operand" "g")
+ (zero_extract:SI (match_dup 0)
+ (match_operand:SI 4 "general_operand" "g")
+ (match_operand:SI 5 "general_operand" "g")))]
+ "GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[4]) == CONST_INT
+ && GET_CODE (operands[5]) == CONST_INT
+ && (INTVAL (operands[4]) + INTVAL (operands[5])) == 32
+ && dead_or_set_p (insn, operands[0])"
+ "*
+{
+ unsigned long mask = INTVAL (operands[2]);
+
+ mask &= ~((1 << INTVAL (operands[5])) - 1);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, ~mask);
+
+ operands[5] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[5]));
+
+ if (rtx_equal_p (operands[0], operands[1]))
+ output_asm_insn (\"bicl2 %2,%0\", operands);
+ else
+ output_asm_insn (\"bicl3 %2,%1,%0\", operands);
+ return \"rotl %5,%0,%3\";
+}")
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End:
diff --git a/gcc-1.40/config/xm-3b1.h b/gcc-1.40/config/xm-3b1.h
new file mode 100644
index 0000000..2dc36fe
--- /dev/null
+++ b/gcc-1.40/config/xm-3b1.h
@@ -0,0 +1,7 @@
+#define USG
+
+#include "xm-m68k.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-aix386.h b/gcc-1.40/config/xm-aix386.h
new file mode 100644
index 0000000..500e29f
--- /dev/null
+++ b/gcc-1.40/config/xm-aix386.h
@@ -0,0 +1,53 @@
+/* Configuration for GNU C-compiler for IBM PS/2 running AIX/386.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#ifdef FALSE
+#undef FALSE
+#endif
+#ifdef TRUE
+#undef TRUE
+#endif
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+#define USG
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
+
+#ifdef __GNUC__
+#define alloca(n) __builtin_alloca(n)
+#endif
diff --git a/gcc-1.40/config/xm-alliant.h b/gcc-1.40/config/xm-alliant.h
new file mode 100644
index 0000000..2028c62
--- /dev/null
+++ b/gcc-1.40/config/xm-alliant.h
@@ -0,0 +1,48 @@
+/* Configuration for GNU C-compiler for Alliant FX computers.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
+
+/* Make the linker remove temporary labels, since the Alliant assembler
+ doesn't. */
+
+#define LINK_SPEC "-X"
+
diff --git a/gcc-1.40/config/xm-altos3068.h b/gcc-1.40/config/xm-altos3068.h
new file mode 100644
index 0000000..2dc36fe
--- /dev/null
+++ b/gcc-1.40/config/xm-altos3068.h
@@ -0,0 +1,7 @@
+#define USG
+
+#include "xm-m68k.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-convex.h b/gcc-1.40/config/xm-convex.h
new file mode 100644
index 0000000..bddbef2
--- /dev/null
+++ b/gcc-1.40/config/xm-convex.h
@@ -0,0 +1,61 @@
+/* Configuration for GNU C-compiler for Convex.
+ Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
+
+#ifdef _POSIX_SOURCE
+
+/* Un-hide names hidden in Posix include files. */
+
+#define S_IFMT _S_IFMT
+#define S_IFREG _S_IFREG
+
+#else
+
+/* This definition is to prevent 8.0 include files from declaring prototypes.
+ Those include files ANSIfied, but the prototypes sometimes do not match.
+ There is no effect on pre-8.0 OS versions. */
+
+#ifndef _PROTO
+#define _PROTO(X) ()
+#endif
+
+#endif /* _POSIX_SOURCE */
+
diff --git a/gcc-1.40/config/xm-delta68k.h b/gcc-1.40/config/xm-delta68k.h
new file mode 100644
index 0000000..0decc16
--- /dev/null
+++ b/gcc-1.40/config/xm-delta68k.h
@@ -0,0 +1,8 @@
+#define USG
+#define USE_C_ALLOCA
+
+#include "xm-m68k.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-genix.h b/gcc-1.40/config/xm-genix.h
new file mode 100644
index 0000000..11d31de
--- /dev/null
+++ b/gcc-1.40/config/xm-genix.h
@@ -0,0 +1,9 @@
+/* Config file for ns32k running system V. */
+
+#include "xm-ns32k.h"
+
+#define USG
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-hp9k320.h b/gcc-1.40/config/xm-hp9k320.h
new file mode 100644
index 0000000..0974ac8
--- /dev/null
+++ b/gcc-1.40/config/xm-hp9k320.h
@@ -0,0 +1,13 @@
+#define USG
+
+#include "xm-m68k.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
+
+/* If compiling with HPUX compiler, we are probably using alloca.c,
+ so help it work right. */
+#ifndef __GNUC__
+#define USE_C_ALLOCA
+#endif
diff --git a/gcc-1.40/config/xm-i386.h b/gcc-1.40/config/xm-i386.h
new file mode 100644
index 0000000..e883f47
--- /dev/null
+++ b/gcc-1.40/config/xm-i386.h
@@ -0,0 +1,42 @@
+/* Configuration for GNU C-compiler for Intel 80386 running Sequent Symmetry
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+
+#include "tm.h"
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
diff --git a/gcc-1.40/config/xm-i386v.h b/gcc-1.40/config/xm-i386v.h
new file mode 100644
index 0000000..60d4ce9
--- /dev/null
+++ b/gcc-1.40/config/xm-i386v.h
@@ -0,0 +1,47 @@
+/* Configuration for GNU C-compiler for Intel 80386 running System V.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+#define USG
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
+
+#ifdef __GNUC__
+#define alloca(n) __builtin_alloca(n)
+#endif
diff --git a/gcc-1.40/config/xm-i860.h b/gcc-1.40/config/xm-i860.h
new file mode 100644
index 0000000..61fa8be
--- /dev/null
+++ b/gcc-1.40/config/xm-i860.h
@@ -0,0 +1,38 @@
+/* Configuration for GNU C-compiler for Intel i860.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+
+#include "tm.h"
diff --git a/gcc-1.40/config/xm-iris.h b/gcc-1.40/config/xm-iris.h
new file mode 100644
index 0000000..fddef9e
--- /dev/null
+++ b/gcc-1.40/config/xm-iris.h
@@ -0,0 +1,7 @@
+#include "xm-mips.h"
+
+#define USG
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-m68k.h b/gcc-1.40/config/xm-m68k.h
new file mode 100644
index 0000000..0165b58
--- /dev/null
+++ b/gcc-1.40/config/xm-m68k.h
@@ -0,0 +1,43 @@
+/* Configuration for GNU C-compiler for Motorola 68000 family.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+#define HOST_WORDS_BIG_ENDIAN
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
diff --git a/gcc-1.40/config/xm-m88k.h b/gcc-1.40/config/xm-m88k.h
new file mode 100644
index 0000000..ea98030
--- /dev/null
+++ b/gcc-1.40/config/xm-m88k.h
@@ -0,0 +1,37 @@
+/* Configuration for GNU C-compiler for Motorola 88000 family.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
diff --git a/gcc-1.40/config/xm-mips.h b/gcc-1.40/config/xm-mips.h
new file mode 100644
index 0000000..e73e992
--- /dev/null
+++ b/gcc-1.40/config/xm-mips.h
@@ -0,0 +1,44 @@
+/* Configuration for GNU C-compiler for MIPS Rx000 family
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#define USE_C_ALLOCA
+#endif
diff --git a/gcc-1.40/config/xm-ns32k.h b/gcc-1.40/config/xm-ns32k.h
new file mode 100644
index 0000000..a19dcb6
--- /dev/null
+++ b/gcc-1.40/config/xm-ns32k.h
@@ -0,0 +1,41 @@
+/* Configuration for GNU C-compiler for Vax.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
diff --git a/gcc-1.40/config/xm-pyr.h b/gcc-1.40/config/xm-pyr.h
new file mode 100644
index 0000000..063829a
--- /dev/null
+++ b/gcc-1.40/config/xm-pyr.h
@@ -0,0 +1,43 @@
+/* Configuration for GNU compiler for Pyramid 90 Series.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* xm-pyr.h -- based on xm-vax.h */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
diff --git a/gcc-1.40/config/xm-sparc.h b/gcc-1.40/config/xm-sparc.h
new file mode 100644
index 0000000..84a5984
--- /dev/null
+++ b/gcc-1.40/config/xm-sparc.h
@@ -0,0 +1,44 @@
+/* Configuration for GNU C-compiler for Sun Sparc.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Place any machine-dependent include files here, in case we
+ are bootstrapping. */
+#ifndef alloca
+#include "alloca.h"
+#endif
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
diff --git a/gcc-1.40/config/xm-spur.h b/gcc-1.40/config/xm-spur.h
new file mode 100644
index 0000000..a9db436
--- /dev/null
+++ b/gcc-1.40/config/xm-spur.h
@@ -0,0 +1,37 @@
+/* Configuration for GNU C-compiler for Berkeley SPUR processor.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
diff --git a/gcc-1.40/config/xm-sun386i.h b/gcc-1.40/config/xm-sun386i.h
new file mode 100644
index 0000000..48ca9a0
--- /dev/null
+++ b/gcc-1.40/config/xm-sun386i.h
@@ -0,0 +1,48 @@
+/* Configuration for GNU C-compiler for Intel 80386 running SunOS 4.0.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+#define USG
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
+
+#ifdef __GNUC__
+#define alloca(n) __builtin_alloca(n)
+#endif
+
diff --git a/gcc-1.40/config/xm-tahoe.h b/gcc-1.40/config/xm-tahoe.h
new file mode 100644
index 0000000..e52ebe3
--- /dev/null
+++ b/gcc-1.40/config/xm-tahoe.h
@@ -0,0 +1,57 @@
+/* Configuration for GNU C-compiler for Tahoe.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * File: xm-tahoe.h
+ *
+ * This port made at the University of Buffalo by Devon Bowen,
+ * Dale Wiles and Kevin Zachmann.
+ *
+ * Mail bugs reports or fixes to: gcc@cs.buffalo.edu
+ */
+
+
+/* This file has the same stuff the vax version does */
+
+/* defines that need visibility everywhere */
+
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies */
+
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* use built in alloca if gcc compiled */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
diff --git a/gcc-1.40/config/xm-tower.h b/gcc-1.40/config/xm-tower.h
new file mode 100644
index 0000000..1dc01ef
--- /dev/null
+++ b/gcc-1.40/config/xm-tower.h
@@ -0,0 +1,8 @@
+#include "xm-m68k.h"
+
+#define USG
+#define HAVE_VPRINTF
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-umips.h b/gcc-1.40/config/xm-umips.h
new file mode 100644
index 0000000..bed8022
--- /dev/null
+++ b/gcc-1.40/config/xm-umips.h
@@ -0,0 +1,44 @@
+/* Configuration for GNU C-compiler for UMIPS operating system
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Notes for compiling gcc on umips (v3.0)
+ * - change the -g in the CFLAGS to a -g3 or take it out all together.
+ * - do not define DBX_DEBUGGING_INFO in tm.h, it doesn't exist (unless
+ * you get one from a bsd system)
+ */
+#include "xm-mips.h"
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
+
+#define USG
+
+/* for the emacs version of alloca */
+#define STACK_DIRECTION -1
+
+#define bcopy(a,b,c) memcpy((b),(a),(c))
+#define bzero(a,b) memset((a),0,(b))
+#define bcmp(a,b,c) memcmp((a),(b),(c))
diff --git a/gcc-1.40/config/xm-vax.h b/gcc-1.40/config/xm-vax.h
new file mode 100644
index 0000000..0057ae6
--- /dev/null
+++ b/gcc-1.40/config/xm-vax.h
@@ -0,0 +1,42 @@
+/* Configuration for GNU C-compiler for Vax.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
+
diff --git a/gcc-1.40/config/xm-vaxv.h b/gcc-1.40/config/xm-vaxv.h
new file mode 100644
index 0000000..d347694
--- /dev/null
+++ b/gcc-1.40/config/xm-vaxv.h
@@ -0,0 +1,9 @@
+/* Config file for Vax running system V. */
+
+#include "xm-vax.h"
+
+#define USG
+
+#define bcopy(a,b,c) memcpy (b,a,c)
+#define bzero(a,b) memset (a,0,b)
+#define bcmp(a,b,c) memcmp (a,b,c)
diff --git a/gcc-1.40/config/xm-vms.h b/gcc-1.40/config/xm-vms.h
new file mode 100644
index 0000000..368c167
--- /dev/null
+++ b/gcc-1.40/config/xm-vms.h
@@ -0,0 +1,61 @@
+/* Configuration for GNU C-compiler for Vax.
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+#include "tm.h"
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+
+#define SUCCESS_EXIT_CODE 1
+#define FATAL_EXIT_CODE (44 | 0x10000000) /* Failure, and no DCL message. */
+
+
+/* A couple of conditionals for execution machine are controlled here. */
+#ifndef VMS
+#define VMS
+#endif
+
+#ifndef __GNUC__
+/* not present, at least in VAX-11 C (VMS) v2.2 */
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+
+#define unlink delete
+#endif
+
+/* global const variables don't work,
+ so turn off const-ness to prevent trouble with insn-output.c. */
+#define const
+
+/* If compiled with GNU C, use the built-in alloca */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#endif
+