/* see @@ for unresolved issues.  */
/* @@ check against tm-vax.h for completeness.  */

/* Definitions of target machine characteristics for GNU compiler.
   Motorola 68000 version.
   Copyright (C) 1986 by Free Software Foundation.

   This will be free software eventually, but not until it is finished.  */

/* Define this if most significant byte of a word is the lowest numbered.  */
#define BIG_ENDIAN

/* target machine register layout */
#define FIRST_PSEUDO_REGISTER 16

/* Registers available for general temporary use.  */
#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}

/* Registers available for use that are not clobbered by calls.  */
#define CALL_USED_REGISTERS {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}

/* Order in which registers should be allocated.  */
/* @@?? This doesn't distinguish between data and address registers.  */
#define ALLOCATE_REGISTERS {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}

#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",	\
 "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp"}

/* target machine storage layout */
/* @@ Source should be checked to see if all of these are still used. */
#define BITS_PER_UNIT	8
	/* number of bits in an addressible storage unit */
#define BITS_PER_HALF_WORD	16
#define BITS_PER_WORD	32
         /* number of bits in a word, preferred allocation boundary */
#define BITS_PER_DOUBLE_WORD	64
#define BITS_PER_TETRA_WORD	128

/* @@ Source should be checked to see if all of these are still used. */
#define POINTER_SIZE	BITS_PER_WORD
	/* size and allocation boundary of a pointer */
#define DOUBLE_POINTER_SIZE	BITS_PER_DOUBLE_WORD
#define POINTER_BOUNDARY	32

/* All function parameters must appear on at least this boundary
   within the parameter list.  */
#define PARM_BOUNDARY		32

/* There is no point aligning anything to a rounder boundary than this.  */
#define BIGGEST_ALIGNMENT	32


#define CASE_VECTOR_MODE HImode

#define CASE_VECTOR_PC_RELATIVE

/* m68000 pc isn't overloaded on a register.  */
/* #define PC_REGNUM  */

#define STACK_POINTER_REGNUM 15

#define FRAME_POINTER_REGNUM 14

#define ARG_POINTER_REGNUM 14

#define STATIC_CHAIN_REGNUM 8

/* FUNCTION_VALUE_REGNUM implicitly points at more than one register.  */
#define FUNCTION_VALUE_REGNUM 0

/* 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

/* Offset of first parameter from the argument pointer register value.  */
#define FIRST_PARM_OFFSET 8

#define REGNO_OK_FOR_INDEX_P(REGNO) ((REGNO) < FIRST_PSEUDO_REGISTER)
#define REGNO_OK_FOR_BASE_P(REGNO) (((REGNO) ^ 010) < 8)

/* 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 used in constant_address_p().
   CONSTANT_ADDRESS_P is actually machine-independent.  */

/* This is a subroutine for the caller to redefine, if appropriate,
   to return nonzero only for REG rtx's that will map into a hard register,
   and zero for those that are relegated to memory.
   You can assume that the argument to this macro has code REG.  */
#define REG_OK_FOR_INDEX_P(X) 1
#define REG_OK_FOR_BASE_P(X) 1

#define CONSTANT_ADDRESS_P(X)   \
  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF		\
   || GET_CODE (X) == CONST_INT						\
   || ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS)			\
       && constant_address_p (FORMAT_e (X, 0))				\
       && constant_address_p (FORMAT_e (X, 1))))

#define REG_P(X)	\
  (GET_CODE (X) == REG)

#define DATA_REG_P(X)	\
  (GET_CODE (X) == REG && (FORMAT_i (X, 0) <= 7))

#define ADDRESS_REG_P(X)	\
  (GET_CODE (X) == REG && REGNO_OK_FOR_BASE_P (FORMAT_i (X, 0)))

#define REG_INDIRECT_OR_PC_WITH_OFFSET_ADDRESS_P(X) \
(CONSTANT_ADDRESS_P (X)							\
 || (GET_CODE (X) == PLUS						\
     && REG_P (FORMAT_e (X, 0)) && REG_OK_FOR_BASE_P (FORMAT_e (X, 0))	\
     && CONSTANT_ADDRESS_P (FORMAT_e (X, 1))))

#define INDIRECTABLE_1_ADDRESS_P(X)  \
  (CONSTANT_ADDRESS_P (X)						\
   || GET_CODE (X) == REG						\
   || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC)		\
       && REG_P (FORMAT_e (X, 0))					\
       && REG_OK_FOR_ADDRESS_P (FORMAT_e (X, 0))))

#define GO_IF_NONINDEXED_ADDRESS(X, ADDR)  \
{ if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }

#define GO_IF_INDEXABLE_ADDRESS(X, ADDR)   \
{ if (GET_CODE (X) == PLUS						  \
      && ((REG_P (FORMAT_e (X, 0)) && REG_OK_FOR_BASE_P (FORMAT_e (X, 0)) \
	   && GET_CODE (FORMAT_e (X, 1)) == CONST_INT			  \
	   && ((unsigned) FORMAT_i (FORMAT_e (X, 1), 0) + 0x80) < 0x100)  \
	  ||								  \
	  (REG_P (FORMAT_e (X, 1)) && REG_OK_FOR_BASE_P (FORMAT_e (X, 1)) \
	   && GET_CODE (FORMAT_e (X, 0)) == CONST_INT			  \
	   && ((unsigned) FORMAT_i (FORMAT_e (X, 0), 0) + 0x80) < 0x100)))\
     goto ADDR; }

#define INDIRECTABLE_2_ADDRESS_P(X)  \
  (GET_CODE (X) == PLUS							\
   && ((ADDRESS_REG_P (FORMAT_e (X, 0))					\
	&& REG_OK_FOR_ADDRESS_P (FORMAT_e (X, 0)))			\
       || GET_CODE (FORMAT_e (X, 0)) == PC)				\
   && (CONSTANT_ADDRESS_P (FORMAT_e (X, 1))				\
       || (GET_CODE (FORMAT_e (X, 1)) == PLUS				\
	   && GET_CODE (FORMAT_e (FORMAT_e (X, 1), 0)) == REG		\
	   && REG_OK_FOR_ADDRESS_P (FORMAT_e (FORMAT_e (X, 1), 0))	\
	   && constant_address_p (FORMAT_e (FORMAT_e (X, 1), 1)))))

#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)  \
{ GO_IF_NONINDEXED_ADDRESS (X, ADDR);					\
  if (GET_CODE (X) == PLUS						\
      && GET_CODE (FORMAT_e (X, 0)) == REG				\
      && REG_OK_FOR_INDEX_P (FORMAT_e (X, 0)))				\
    { GO_IF_INDEXABLE_ADDRESS (FORMAT_e (X, 1), ADDR); }		\
  else if (GET_CODE (X) == PLUS						\
	   && GET_CODE (FORMAT_e (X, 1)) == REG				\
	   && REG_OK_FOR_INDEX_P (FORMAT_e (X, 1)))			\
    { GO_IF_INDEXABLE_ADDRESS (FORMAT_e (X, 0), ADDR); } }


/* Define this macro if insn operands need to be constrained (i.e.
   if the machine description has a match-operand insn with a
   non-null third string argument).
   Note: genflags.c should be emitting: "#define REGISTER_CONSTRAINTS".  */
#define GO_IF_VALID_CONSTRAINED_OP(OP, MODE, CLASS, ADDR)		\
{ switch (CLASS) {							\
  case 'g': if (general_operand (OP, MODE)) goto ADDR; break;		\
  case 'i': if (immeadiate_data_operand (OP, MODE)) goto ADDR; break;	\
  case 'r': if (register_operand (OP, MODE)) goto ADDR; break;		\
  case 'm': if (address_operand (OP, MODE)) goto ADDR; break;		\
  /* #ifdef BIG_ENDIAN */						\
  case 'o': if (offsetable_address_operand (OP, MODE)) goto ADDR; break;\
  /* #ifdef ADDRESS_REG_P */						\
  case 'a': if (address_register_operand (OP, MODE)) goto ADDR; break;	\
  /* #ifdef DATA_REG_P */						\
  case 'd': if (data_register_operand (OP, MODE)) goto ADDR; break;	\
  default: abort(); } }

#define HAVE_POST_INCREMENT
/* #define HAVE_POST_DECREMENT */

#define HAVE_PRE_DECREMENT
/* #define HAVE_PRE_INCREMENT */

#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR

/* A pointer is the same size as a word,
   and the conversion between them is a no-op.  */
#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 if returning from a function call automatically
   pops the arguments described by the number-of-args field in the call.  */

/* #define RETURN_POPS_ARGS   On the 68000, the caller must pop them.  */

/* @@ not clear that 14 and 15 need to be saved */
/* @@ might be able to use movem.w if we can check that all registers
   @@ are only using a word (2 bytes). */
#define FUNCTION_PROLOGUE(FILE, SIZE)     \
{ register int regno;						\
  register int mask = 0;					\
  fprintf (FILE, "\tlink a6,$%d\n", - (SIZE));			\
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++, mask <<= 1)	\
    if (regs_ever_live[regno]) mask |= 1;			\
  fprintf (FILE, "\tmovem.l $0x%x,-(sp)\n", mask & 0x3ffc); }


#define FUNCTION_EPILOGUE(FILE, SIZE) \
{ register int regno;						\
  register int mask = 0;					\
  register int nregs = 0;					\
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)	\
    if (regs_ever_live[regno]) { nregs++; mask |= 1 << regno; }	\
  fprintf (FILE, "\tmovem.l -%d(fp),$0x%x\n",			\
           nregs*4, mask & 0x3ffc);				\
  fprintf (FILE, "\tunlk a6\n\trts\n"); }


/* Number of bytes of boundary to align beginnings of functions on.  */

#define FUNCTION_ALIGN 2

/* Store in CCVAR0 and CCVAR1 the expressions
   that the condition codes will describe
   after execution of an instruction whose pattern is EXP.
   Two variables are provided so two different equivalent expressions
   can be stored (they have the same value, so either could be tested).
   Set CCVAR0 and CCVAR1 to zero if the CC's will be undefined then.
   Do not alter them if the instruction would not alter the cc's.  */
				/* @@?? */
#define NOTICE_UPDATE_CC(CCVAR0,CCVAR1,EXP) \
{ if (GET_CODE (EXP) == SET)					\
    { if (GET_CODE (FORMAT_e (EXP, 0)) != PC)			\
	{ CCVAR0 = FORMAT_e (EXP, 0);				\
	  CCVAR1 = FORMAT_e (EXP, 1); } }			\
  else if (GET_CODE (EXP) == PARALLEL				\
	   && GET_CODE (FORMAT_E (EXP, 0, 0)) == SET)		\
    { if (GET_CODE (FORMAT_e (FORMAT_E (EXP, 0, 0), 0)) != PC)	\
	{ CCVAR0 = FORMAT_e (FORMAT_E (EXP, 0, 0), 0);		\
	  CCVAR1 = FORMAT_e (FORMAT_E (EXP, 0, 0), 1); } }	\
  else CCVAR0 = 0, CCVAR1 = 0; }

/* Define the classes of registers.
   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 none of the registers.

   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, and therefore four classes.  */

enum reg_class { NO_REGS, DATA_REGS, ADDR_REGS, ALL_REGS, LIM_REG_CLASSES };

#define N_REG_CLASSES (int) LIM_REG_CLASSES

/* 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, 0xff, 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) ((REGNO) < 8 ? DATA_REGS : ADDR_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 a -1.  */
   
/* We don't need the first element, which is for NO_REGS.  */
#define REG_CLASS_SUPERCLASSES \
 {{0}, {ALL_REGS, (enum reg_class) -1}, {ALL_REGS, (enum reg_class) -1}, \
  {(enum reg_class) -1}}

/* 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, DATA_REGS, ADDR_REGS, ALL_REGS}, \
 {DATA_REGS, DATA_REGS, ALL_REGS, ALL_REGS}, \
 {ADDR_REGS, ADDR_REGS, ALL_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 ALL_REGS
#define BASE_REG_CLASS ADDR_REGS

/*
Local variables:
version-control: t
End:
*/
