1/* Definitions of target machine for GNU compiler.  Genix ns32000 version.
2   Copyright (C) 1987, 1988, 1994 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING.  If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21#include "ns32k/encore.h"
22
23/* We don't want the one Encore needs.  */
24#undef ASM_SPEC
25
26/* The following defines override ones in ns32k.h and prevent any attempts
27   to explicitly or implicitly make references to the SB register in the GCC
28   generated code.  It is necessary to avoid such references under Genix V.3.1
29   because this OS doesn't even save/restore the SB on context switches!  */
30
31#define IS_OK_REG_FOR_BASE_P(X)						\
32  ( (GET_CODE (X) == REG) && REG_OK_FOR_BASE_P (X) )
33
34#undef INDIRECTABLE_1_ADDRESS_P
35#define INDIRECTABLE_1_ADDRESS_P(X)					\
36  (CONSTANT_ADDRESS_NO_LABEL_P (X)					\
37   || IS_OK_REG_FOR_BASE_P (X)						\
38   || (GET_CODE (X) == PLUS						\
39       && IS_OK_REG_FOR_BASE_P (XEXP (X, 0))				\
40       && CONSTANT_ADDRESS_P (XEXP (X, 1))  )  )
41
42/* Note that for double indirects, only FP, SP, and SB are allowed
43   as the inner-most base register.  But we are avoiding use of SB.  */
44
45#undef MEM_REG
46#define MEM_REG(X)							\
47  ( (GET_CODE (X) == REG)						\
48  && ( (REGNO (X) == FRAME_POINTER_REGNUM)				\
49    || (REGNO (X) == STACK_POINTER_REGNUM) ) )
50
51#undef INDIRECTABLE_2_ADDRESS_P
52#define INDIRECTABLE_2_ADDRESS_P(X)					\
53  (GET_CODE (X) == MEM							\
54   && (((xfoo0 = XEXP (X, 0), MEM_REG (xfoo0))				\
55       || (GET_CODE (xfoo0) == PLUS					\
56	   && MEM_REG (XEXP (xfoo0, 0))					\
57	   && CONSTANT_ADDRESS_NO_LABEL_P (XEXP (xfoo0, 1))))		\
58       || CONSTANT_ADDRESS_NO_LABEL_P (xfoo0)))
59
60/* Go to ADDR if X is a valid address not using indexing.
61   (This much is the easy part.)  */
62#undef GO_IF_NONINDEXED_ADDRESS
63#define GO_IF_NONINDEXED_ADDRESS(X, ADDR)				\
64{ register rtx xfoob = (X);						\
65  if (GET_CODE (xfoob) == REG) goto ADDR;				\
66  if (INDIRECTABLE_1_ADDRESS_P(X)) goto ADDR;				\
67  if (CONSTANT_P(X)) goto ADDR;						\
68  if (INDIRECTABLE_2_ADDRESS_P (X)) goto ADDR;				\
69  if (GET_CODE (X) == PLUS)						\
70    if (CONSTANT_ADDRESS_NO_LABEL_P (XEXP (X, 1)))			\
71      if (INDIRECTABLE_2_ADDRESS_P (XEXP (X, 0)))			\
72	goto ADDR;							\
73}
74
75/* A bug in the GNX 3.X assembler causes references to external symbols to
76   be mishandled if the symbol is also used as the name of a function-local
77   variable or as the name of a struct or union field.  The problem only
78   appears when you are also using the -g option so that SDB debugging
79   directives are also being produced by GCC.  In such cases, the assembler
80   gets the external entity confused with the local entity and addressing
81   havoc ensues.  The solution is to get GCC to produce .global directives
82   for all external entities which are actually referenced within the current
83   source file.  The following macro does this.  */
84
85#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME)				\
86    ASM_GLOBALIZE_LABEL(FILE,NAME);
87
88/* Genix wants 0l instead of 0f.  */
89
90#undef ASM_OUTPUT_DOUBLE
91#define ASM_OUTPUT_DOUBLE(FILE,VALUE)				\
92 fprintf (FILE, "\t.long 0l%.20e\n", (VALUE))
93
94/*  A bug in the GNX 3.X linker prevents symbol-table entries with a storage-
95    class field of C_EFCN (-1) from being accepted. */
96
97#ifdef PUT_SDB_EPILOGUE_END
98#undef PUT_SDB_EPILOGUE_END
99#endif
100#define PUT_SDB_EPILOGUE_END(NAME)
101
102#undef TARGET_VERSION
103#define TARGET_VERSION fprintf (stderr, " (32000, National syntax)");
104
105/* Same as the encore definition except
106   * Different syntax for double constants.
107   * Don't output `?' before external regs.
108   * Output `(sb)' in certain indirect refs.  */
109
110#error this has not been updated since version 1.
111#error it is certainly wrong.
112
113#undef PRINT_OPERAND
114#define PRINT_OPERAND(FILE, X, CODE)					\
115{ if (CODE == '$') putc ('$', FILE);					\
116  else if (CODE == '?');						\
117  else if (GET_CODE (X) == REG)						\
118    fprintf (FILE, "%s", reg_names[REGNO (X)]);				\
119  else if (GET_CODE (X) == MEM)						\
120    {									\
121      rtx xfoo;								\
122      xfoo = XEXP (X, 0);						\
123      switch (GET_CODE (xfoo))						\
124	{								\
125	case MEM:							\
126	  if (GET_CODE (XEXP (xfoo, 0)) == REG)				\
127	    if (REGNO (XEXP (xfoo, 0)) == STACK_POINTER_REGNUM)		\
128	      fprintf (FILE, "0(0(sp))");				\
129	    else fprintf (FILE, "0(0(%s))",				\
130			  reg_names[REGNO (XEXP (xfoo, 0))]);		\
131	  else								\
132	    {								\
133	      extern int paren_base_reg_printed;			\
134	      fprintf (FILE, "0(");					\
135	      paren_base_reg_printed = 0;				\
136	      output_address (xfoo);					\
137	      if (!paren_base_reg_printed)				\
138		fprintf (FILE, "(sb)");					\
139	      putc (')', FILE);						\
140	    }								\
141	  break;							\
142	case REG:							\
143	  fprintf (FILE, "0(%s)", reg_names[REGNO (xfoo)]);		\
144	  break;							\
145	case PRE_DEC:							\
146	case POST_INC:							\
147	  fprintf (FILE, "tos");					\
148	  break;							\
149	case CONST_INT:							\
150	  fprintf (FILE, "@%d", INTVAL (xfoo));				\
151	  break;							\
152	default:							\
153	  output_address (xfoo);					\
154	  break;							\
155	}								\
156    }									\
157  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode)	\
158    if (GET_MODE (X) == DFmode)						\
159      { union { double d; int i[2]; } u;				\
160        u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);	\
161	fprintf (FILE, "$0l%.20e", u.d); }				\
162    else { union { double d; int i[2]; } u;				\
163	   u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
164	   fprintf (FILE, "$0f%.20e", u.d); }				\
165  else if (GET_CODE (X) == CONST)					\
166    output_addr_const (FILE, X);					\
167  else { putc ('$', FILE); output_addr_const (FILE, X); }}
168