Initial revision
authorRichard Stallman <rms@gnu.org>
Sat, 14 Mar 1992 05:16:55 +0000 (05:16 +0000)
committerRichard Stallman <rms@gnu.org>
Sat, 14 Mar 1992 05:16:55 +0000 (05:16 +0000)
From-SVN: r477

gcc/config/tahoe/tahoe.h [new file with mode: 0644]

diff --git a/gcc/config/tahoe/tahoe.h b/gcc/config/tahoe/tahoe.h
new file mode 100644 (file)
index 0000000..aec2c4b
--- /dev/null
@@ -0,0 +1,1018 @@
+/* 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 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * File: tahoe.h
+ *
+ * Original port made at the University of Buffalo by Devon Bowen,
+ * Dale Wiles and Kevin Zachmann.
+ *
+ * HCX/UX version by Piet van Oostrum (piet@cs.ruu.nl)
+ *
+ * Performance hacking by Michael Tiemann (tiemann@lurch.stanford.edu)
+ *
+ * Mail bugs reports or fixes to:      gcc@cs.buffalo.edu
+ */
+
+/* define this for the HCX/UX version */
+
+/* #define HCX_UX */
+
+/*
+ * Run-time Target Specification
+ */
+
+#ifdef HCX_UX
+/* no predefines, see Makefile and hcx-universe.c */
+/* have cc1 print that this is the hcx version */
+#define TARGET_VERSION printf (" (hcx)");
+#else
+/* we want "tahoe" and "unix" defined for all future compilations */
+#define CPP_PREDEFINES "-Dtahoe -Dunix"
+/* have cc1 print that this is the tahoe version */
+#define TARGET_VERSION printf (" (tahoe)");
+#endif
+
+/* 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} }
+\f
+
+/*
+ * Storage Layout
+ */
+
+/* This symbol was previously not mentioned, so apparently the tahoe
+   is little-endian for bits, or else doesn't care.  */
+#define BITS_BIG_ENDIAN 0
+
+/* tahoe uses a big endian byte order */
+
+#define BYTES_BIG_ENDIAN 1
+
+/* tahoe uses a big endian word order */
+
+#define WORDS_BIG_ENDIAN 1
+
+/* 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
+
+/* 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
+
+#ifdef HCX_UX
+/* structures must be made of full words */
+
+#define STRUCTURE_SIZE_BOUNDARY 32
+#else
+/* structures must be made of full bytes */
+
+#define STRUCTURE_SIZE_BOUNDARY 8
+#endif
+
+/* tahoe is picky about data alignment */
+
+#define STRICT_ALIGNMENT 1
+
+/* 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 guaranteed 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}
+
+/* A single fp reg can handle any type of float.
+   CPU regs hold just 32 bits.  */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ (REGNO != 16 ? ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD)  \
+  : GET_MODE_NUNITS ((MODE)))
+
+/* 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_UNIT_SIZE (MODE) <= 4 ? 1 : (REGNO % 2 - 1))     \
+  : ((MODE) == SFmode || (MODE) == DFmode                      \
+     || (MODE) == SCmode || (MODE) == DCmode))
+
+/* if mode1 or mode2, but not both, are doubles then modes cannot be tied */
+
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (((MODE1) == DFmode || (MODE1) == DCmode)     \
+  == ((MODE2) == DFmode || (MODE2) == DCmode))
+
+/* return nonzero if register variable of mode MODE is not
+   a priori a bad idea.  Used only if defined.  */
+#define MODE_OK_FOR_USERVAR(MODE)      \
+  ((MODE) == SImode)
+
+/* 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. GENERAL_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 constraint 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,SIZE) (SIZE)
+
+/* 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,LIBNAME)       \
+ ((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); }
+
+/* Zero out global variable in case it was used in this function.  */
+#define FUNCTION_EPILOGUE(FILE, SIZE)  \
+{ extern rtx tahoe_reg_conversion_loc;                         \
+  tahoe_reg_conversion_loc = 0;                                        \
+}
+
+#ifdef HCX_UX
+
+/* to call the profiler, the address of the counter var is placed */
+/* on the stack and then passed into mcount this way                     */
+
+#define FUNCTION_PROFILER(FILE, LABELNO)  \
+   fprintf (FILE, "\tpushal LP%d\n\tcallf $8,mcount\n", (LABELNO));
+
+#else
+
+/* 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));
+
+#endif
+
+/* all stack handling at the end of a function is handled by the */
+/* return command.                                              */
+
+#define EXIT_IGNORE_STACK 1
+
+/*
+ * 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 */
+/* but not so on hcx/ux */
+
+#ifdef HCX_UX
+#undef UMODSI3_LIBCALL
+#else
+#define UMODSI3_LIBCALL "*urem"
+#endif
+
+
+/*
+ * 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 identical.              */
+
+/* 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 address */
+
+#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
+
+/* Define this if addresses of constant functions
+   shouldn't be put through pseudo regs where they can be cse'd.
+   On the tahoe a call with a constant address is much faster than one with a
+   register. */
+
+#define NO_FUNCTION_CSE
+
+/* specify the costs of various sorts of constants,
+   and also indicate that multiplication is cheap on this machine.  */
+
+#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;               \
+    if (INTVAL (RTX) <= 127 && INTVAL (RTX) >= -128) return 2; \
+  case CONST:                                                  \
+  case LABEL_REF:                                              \
+  case SYMBOL_REF:                                             \
+    return 3;                                                  \
+  case CONST_DOUBLE:                                           \
+    return 5;                                                  \
+  case MULT:                                                   \
+    total = 2;
+
+
+/*
+ * Condition Code Information
+ */
+
+/* Nonzero if the results of the previous comparison are
+   in the floating point condition code register.  */
+
+#define CC_UNCHANGED 04000
+
+
+#define NOTICE_UPDATE_CC(EXP, INSN) \
+{ if (cc_status.flags & CC_UNCHANGED)                          \
+    /* Happens for cvtld and a few other insns.  */            \
+    cc_status.flags &= ~CC_UNCHANGED;                          \
+  else 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.  */
+
+
+/*
+ * Output of Assembler Code
+ */
+
+/* print which tahoe version compiled this code and print a directive */
+/* to the gnu assembler to say that the following is normal assembly  */
+
+#ifdef HCX_UX
+#define ASM_FILE_START(FILE)           \
+{ fprintf (FILE, "#gcc hcx 1.0\n\n");  \
+  output_file_directive ((FILE), main_input_filename);} while (0)
+#else
+#define ASM_FILE_START(FILE) fprintf (FILE, "#gcc tahoe 1.0\n#NO_APP\n");
+#endif
+
+/* 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"}
+
+#ifdef HCX_UX
+/* allow generation of sdb info in the assembly */
+#define SDB_DEBUGGING_INFO
+#else
+/* 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 '?'
+
+#endif /* HCX_UX */
+
+/* registers are called the same thing in dbx anything else */
+/* This is necessary even if we generate SDB output */
+
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* 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)
+
+/* outputting a double is easy cause we only have one kind */
+
+#ifdef HCX_UX
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE)  \
+  fprintf (FILE, "\t.double 0d%.20e\n", (VALUE))
+#else
+#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);     \
+}
+#endif
+
+/* This is how to output an assembler line defining a `float' constant.  */
+
+#ifdef HCX_UX
+#define ASM_OUTPUT_FLOAT(FILE,VALUE)  \
+  fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+#else
+#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);      \
+}
+#endif
+
+/* 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"))
+
+#ifdef HCX_UX
+/* This is how to output an assembler line for an ASCII string.  */
+
+#define ASM_OUTPUT_ASCII(FILE, p, size)                \
+{      register int i;                                 \
+         fprintf ((FILE), "\t.ascii \"");              \
+         for (i = 0; i < (size); i++)                  \
+           {                                           \
+             register int c = (p)[i];                  \
+             if (c == '\'' || c == '\\')               \
+               putc ('\\', (FILE));                    \
+             if (c >= ' ' && c < 0177 && c != '\"')    \
+               putc (c, (FILE));                       \
+             else                                      \
+               {                                       \
+                 fprintf ((FILE), "\\%03o", c);        \
+               }                                       \
+           }                                           \
+         fprintf ((FILE), "\"\n"); }
+#endif
+
+/* 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 is how to output an assembler line
+   that says to advance the location counter
+   to a multiple of 2**LOG bytes.  */
+
+#ifdef HCX_UX
+#define CASE_ALIGNMENT 2
+#define ASM_OUTPUT_ALIGN(FILE,LOG)  \
+    if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+#else
+#define CASE_ALIGNMENT 1
+#define ASM_OUTPUT_ALIGN(FILE,LOG)  \
+  LOG ? fprintf (FILE, "\t.align %d\n", (LOG)) : 0
+#endif
+
+/* 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 */
+
+#ifdef HCX_UX
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
+( fputs (".comm ", (FILE)),                    \
+  assemble_name ((FILE), (NAME)),              \
+  fprintf ((FILE), ",%u\n", (SIZE)))
+#else
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)  \
+( fputs (".comm ", (FILE)),                    \
+  assemble_name ((FILE), (NAME)),              \
+  fprintf ((FILE), ",%u\n", (ROUNDED)))
+#endif
+
+/* This says how to output an assembler line
+   to define a local common symbol.  */
+
+#ifdef HCX_UX
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
+( fputs ("\t.bss ", (FILE)),                   \
+  assemble_name ((FILE), (NAME)),              \
+  fprintf ((FILE), ",%u,4\n", (SIZE),(ROUNDED)))
+#else
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)  \
+( fputs (".lcomm ", (FILE)),                   \
+  assemble_name ((FILE), (NAME)),              \
+  fprintf ((FILE), ",%u\n", (ROUNDED)))
+#endif
+
+/* 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)))
+
+/* 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.  */
+/* 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.
+
+   %s means the number given is supposed to be a shift value, but on
+   the tahoe it should be converted to a number that can be used as a
+   multiplicative constant (cause multiplication is a whole lot faster
+   than shifting). So make the number 2^n instead. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE)                              \
+  ((CODE) == '@')
+
+#define PRINT_OPERAND(FILE, X, CODE)  \
+{ if (CODE == '@')                                                     \
+    putc ('0' + CASE_ALIGNMENT, FILE);                                 \
+  else if (CODE == 's')                                                        \
+    fprintf (FILE, "$%d", 1 << INTVAL(X));                             \
+  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)
+
+/* This is for G++ */
+
+#define CRT0_DUMMIES
+#define DOT_GLOBAL_START
+#ifdef HCX_UX
+#define NO_GNU_LD /* because of COFF format */
+#define LINK_SPEC "-L/usr/staff/lib"
+#endif