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