1 /* Definitions of target machine for GNU compiler; 2 Charles River Data Systems UNiverse/32. 3 Copyright (C) 1987, 1993, 1994, 1996, 1997, 1998, 1999, 2000 4 Free Software Foundation, Inc. 5 Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com) 6 7 This file is part of GNU CC. 8 9 GNU CC is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 GNU CC is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GNU CC; see the file COPYING. If not, write to 21 the Free Software Foundation, 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. */ 23 24 #define MOTOROLA /* Use Motorola syntax rather than "MIT" */ 25 #define SGS /* Uses SGS assembler */ 26 #define SGS_SWITCH_TABLES /* Different switch table handling */ 27 #define SGS_NO_LI /* Suppress jump table label usage */ 28 #define CRDS /* Charles River Data Systems assembler */ 29 30 #include "m68k/m68k.h" 31 32 /* Without STRUCTURE_SIZE_BOUNDARY, we can't ensure that structures are 33 aligned such that we can correctly extract bitfields from them. 34 Someone should check whether the usual compiler on the crds machine 35 provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY. */ 36 /* Set to 16 because all other m68k targets have it so */ 37 #define STRUCTURE_SIZE_BOUNDARY 16 38 39 /* See m68k.h. 0 means 680[01]0 with no 68881. */ 40 41 #undef TARGET_DEFAULT 42 #define TARGET_DEFAULT 0 43 44 /* Don't try using XFmode. */ 45 #undef LONG_DOUBLE_TYPE_SIZE 46 #define LONG_DOUBLE_TYPE_SIZE 64 47 48 /* special flags to the unos assembler. */ 49 50 #undef ASM_SPEC 51 #define ASM_SPEC "-g" 52 53 #undef LIB_SPEC 54 #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}" 55 56 #undef STARTFILE_SPEC 57 #define STARTFILE_SPEC \ 58 "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}" 59 60 /* CC1 spec */ 61 #if 0 62 /* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */ 63 /* so we do not need to bother ! */ 64 #define CC1_SPEC "-fpcc-struct-return" 65 #endif 66 67 /* -O2 for MAX optimization */ 68 #undef CC1_SPEC 69 #define CC1_SPEC "%{O2:-fstrength-reduce}" 70 71 /* Make output for SDB. */ 72 73 /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */ 74 75 /* UNOS need stack probe :-( */ 76 77 #if 0 78 #define HAVE_probe 1 79 #define gen_probe() gen_rtx_ASM_INPUT (VOIDmode, "tstb -2048(sp)\t;probe\n") 80 #else 81 #undef NEED_PROBE 82 #define NEED_PROBE (-2048) 83 #endif 84 85 /* use memcpy, memset instead of bcopy, etc. */ 86 87 #define TARGET_MEM_FUNCTIONS 88 89 /* Define __HAVE_68881__ in preprocessor if -m68881 is specified. 90 This will control the use of inline 68881 insns in certain macros. */ 91 92 #undef CPP_SPEC 93 #define CPP_SPEC "%{m68881:-D__HAVE_68881__}" 94 95 /* Names to predefine in the preprocessor for this target machine. */ 96 97 #undef CPP_PREDEFINES 98 #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix -D__motorola__ -Asystem=unix -Acpu=m68k -Amachine=m68k" 99 100 /* Register in which address to store a structure value 101 is passed to a function. */ 102 /* unos uses ".comm c.sac" returns &c.sac in d0 */ 103 /* make pointer to c.sac ? 104 #undef STRUCT_VALUE_REGNUM 105 #define STRUCT_VALUE gen_rtx_MEM (Pmode, gen_rtx( , , ) ) 106 */ 107 108 #define BSS_SECTION_ASM_OP "\t.bss" 109 110 /* Specify how to pad function arguments. 111 Value should be `upward', `downward' or `none'. 112 Same as the default, except no padding for large or variable-size args. */ 113 114 #define FUNCTION_ARG_PADDING(MODE, TYPE) \ 115 (((MODE) == BLKmode \ 116 ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ 117 && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \ 118 : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \ 119 ? downward : none) 120 121 /* Override parts of m68k.h to fit the CRuDS assembler. */ 122 123 #undef TARGET_VERSION 124 #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)"); 125 126 /* Specify extra dir to search for include files. */ 127 #define SYSTEM_INCLUDE_DIR "/include" 128 129 /* Control the assembler format that we output. */ 130 131 /* Output at beginning of assembler file. */ 132 133 #undef ASM_FILE_START 134 #define ASM_FILE_START(FILE) \ 135 fprintf (FILE, ";#NO_APP\n"); 136 137 /* Output to assembler file text saying following lines 138 may contain character constants, extra white space, comments, etc. */ 139 140 #undef ASM_APP_ON 141 #define ASM_APP_ON ";#APP\n" 142 143 /* Output to assembler file text saying following lines 144 no longer contain unusual constructs. */ 145 146 #undef ASM_APP_OFF 147 #define ASM_APP_OFF ";#NO_APP\n" 148 149 /* The prefix for immediate operands. */ 150 151 #undef IMMEDIATE_PREFIX 152 #define IMMEDIATE_PREFIX "$" 153 154 /*unos has no .skip :-( */ 155 #undef ASM_OUTPUT_SKIP 156 #define ASM_OUTPUT_SKIP(FILE,SIZE) \ 157 fprintf (FILE, "\t. = . + %u\n", (SIZE)); 158 159 /* This says how to output an assembler line 160 to define a local common symbol. */ 161 /* should use bss_section instead of data_section but this makes casm die ? */ 162 163 #undef ASM_OUTPUT_LOCAL 164 #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ 165 { data_section (); \ 166 if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \ 167 assemble_name ((FILE), (NAME)); \ 168 fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));} 169 170 /* This is how to output an insn to push a register on the stack. 171 It need not be very fast code. */ 172 173 #undef ASM_OUTPUT_REG_PUSH 174 #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ 175 fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO]) 176 177 /* This is how to output an insn to pop a register from the stack. 178 It need not be very fast code. */ 179 180 #undef ASM_OUTPUT_REG_POP 181 #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ 182 fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO]) 183 184 #undef ASM_OUTPUT_ASCII 185 #define ASM_OUTPUT_ASCII(FILE, P , SIZE) \ 186 do { size_t i, limit = (SIZE); \ 187 fprintf ((FILE), "\t.ascii \""); \ 188 for (i = 0; i < limit; i++) \ 189 { \ 190 register int c = (P)[i]; \ 191 if (i != 0 && (i / 200) * 200 == i) \ 192 fprintf ((FILE), "\"\n\t.ascii \""); \ 193 if (c >= ' ' && c < 0177) { \ 194 if (c != '\"' && c != '\\') { \ 195 putc (c, (FILE)); \ 196 continue; \ 197 } \ 198 } \ 199 /* brain dead asm doesn't understand char escapes */ \ 200 fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \ 201 } \ 202 fprintf ((FILE), "\"\n"); \ 203 } while (0) 204 205 206 /* Change all JBxx to Bxx. Also change all DBRA to DBF. 207 Also change divs.l, etc., to divs, etc. But don't change divsl.l. */ 208 209 #define ASM_OUTPUT_OPCODE(FILE, PTR) \ 210 { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ 211 { ++(PTR); } \ 212 else if ((PTR)[0] == 'd') \ 213 { \ 214 if (!strncmp ((PTR), "dbra", 4)) \ 215 { fprintf ((FILE), "dbf"); (PTR) += 4; } \ 216 else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \ 217 { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \ 218 } \ 219 } 220 221 222 #if 0 223 /* Print operand X (an rtx) in assembler syntax to file FILE. 224 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. 225 For `%' followed by punctuation, CODE is the punctuation and X is null. 226 227 On the 68000, we use several CODE characters: 228 '.' for dot needed in Motorola-style opcode names. 229 '-' for an operand pushing on the stack: 230 sp@-, -(sp) or -(%sp) depending on the style of syntax. 231 '+' for an operand pushing on the stack: 232 sp@+, (sp)+ or (%sp)+ depending on the style of syntax. 233 '@' for a reference to the top word on the stack: 234 sp@, (sp) or (%sp) depending on the style of syntax. 235 '#' for an immediate operand prefix (# in MIT and Motorola syntax 236 but & in SGS syntax, $ in unos syntax). 237 '!' for the fpcr register (used in some float-to-fixed conversions). 238 239 'b' for byte insn (no effect, on the Sun; this is for the ISI). 240 'd' to force memory addressing to be absolute, not relative. 241 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) 242 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather 243 than directly). Second part of 'y' below. 244 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), 245 or print pair of registers as rx:ry. 246 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs 247 CONST_DOUBLE's as SunFPA constant RAM registers if 248 possible, so it should not be used except for the SunFPA. */ 249 250 #undef PRINT_OPERAND_PUNCT_VALID_P 251 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ 252 ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \ 253 || (CODE) == '+' || (CODE) == '@' || (CODE) == '!') 254 255 #undef PRINT_OPERAND 256 #define PRINT_OPERAND(FILE, X, CODE) \ 257 { int i; \ 258 if (CODE == '.') ; \ 259 else if (CODE == '#') fprintf (FILE, "$"); \ 260 else if (CODE == '-') fprintf (FILE, "-(sp)"); \ 261 else if (CODE == '+') fprintf (FILE, "(sp)+"); \ 262 else if (CODE == '@') fprintf (FILE, "(sp)"); \ 263 else if (CODE == '!') fprintf (FILE, "fpcr"); \ 264 else if (CODE == '/') \ 265 ; \ 266 else if (GET_CODE (X) == REG) \ 267 { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \ 268 fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \ 269 else \ 270 fprintf (FILE, "%s", reg_names[REGNO (X)]); \ 271 } \ 272 else if (GET_CODE (X) == MEM) \ 273 { \ 274 output_address (XEXP (X, 0)); \ 275 if (CODE == 'd' && ! TARGET_68020 \ 276 && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ 277 /* fprintf (FILE, ".l") */; \ 278 } \ 279 else if ((CODE == 'y' || CODE == 'w') \ 280 && GET_CODE(X) == CONST_DOUBLE \ 281 && (i = standard_sun_fpa_constant_p (X))) \ 282 fprintf (FILE, "%%%d", i & 0x1ff); \ 283 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ 284 { REAL_VALUE_TYPE r; long l; \ 285 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \ 286 if (CODE == 'f') \ 287 ASM_OUTPUT_FLOAT_OPERAND (CODE, FILE, r); \ 288 else \ 289 { REAL_VALUE_TO_TARGET_SINGLE (r, l); \ 290 fprintf (FILE, "$0x%lx", l); } } \ 291 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \ 292 { REAL_VALUE_TYPE r; \ 293 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \ 294 ASM_OUTPUT_DOUBLE_OPERAND (FILE, r); } \ 295 else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == XFmode) \ 296 { REAL_VALUE_TYPE r; \ 297 REAL_VALUE_FROM_CONST_DOUBLE (r, X); \ 298 ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \ 299 else { putc ('$', FILE); output_addr_const (FILE, X); }} 300 #endif 301 302 /* Note that this contains a kludge that knows that the only reason 303 we have an address (plus (label_ref...) (reg...)) 304 is in the insn before a tablejump, and we know that m68k.md 305 generates a label LInnn: on such an insn. */ 306 #undef PRINT_OPERAND_ADDRESS 307 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ 308 { register rtx reg1, reg2, breg, ireg; \ 309 register rtx addr = ADDR; \ 310 rtx offset; \ 311 switch (GET_CODE (addr)) \ 312 { \ 313 case REG: \ 314 fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \ 315 break; \ 316 case PRE_DEC: \ 317 fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \ 318 break; \ 319 case POST_INC: \ 320 fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \ 321 break; \ 322 case PLUS: \ 323 reg1 = 0; reg2 = 0; \ 324 ireg = 0; breg = 0; \ 325 offset = 0; \ 326 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \ 327 { \ 328 offset = XEXP (addr, 0); \ 329 addr = XEXP (addr, 1); \ 330 } \ 331 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \ 332 { \ 333 offset = XEXP (addr, 1); \ 334 addr = XEXP (addr, 0); \ 335 } \ 336 if (GET_CODE (addr) != PLUS) ; \ 337 else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \ 338 { \ 339 reg1 = XEXP (addr, 0); \ 340 addr = XEXP (addr, 1); \ 341 } \ 342 else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \ 343 { \ 344 reg1 = XEXP (addr, 1); \ 345 addr = XEXP (addr, 0); \ 346 } \ 347 else if (GET_CODE (XEXP (addr, 0)) == MULT) \ 348 { \ 349 reg1 = XEXP (addr, 0); \ 350 addr = XEXP (addr, 1); \ 351 } \ 352 else if (GET_CODE (XEXP (addr, 1)) == MULT) \ 353 { \ 354 reg1 = XEXP (addr, 1); \ 355 addr = XEXP (addr, 0); \ 356 } \ 357 else if (GET_CODE (XEXP (addr, 0)) == REG) \ 358 { \ 359 reg1 = XEXP (addr, 0); \ 360 addr = XEXP (addr, 1); \ 361 } \ 362 else if (GET_CODE (XEXP (addr, 1)) == REG) \ 363 { \ 364 reg1 = XEXP (addr, 1); \ 365 addr = XEXP (addr, 0); \ 366 } \ 367 if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \ 368 || GET_CODE (addr) == SIGN_EXTEND) \ 369 { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \ 370 if (offset != 0) { if (addr != 0) abort (); addr = offset; } \ 371 if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \ 372 || GET_CODE (reg1) == MULT)) \ 373 || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \ 374 { breg = reg2; ireg = reg1; } \ 375 else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \ 376 { breg = reg1; ireg = reg2; } \ 377 if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \ 378 { int scale = 1; \ 379 if (GET_CODE (ireg) == MULT) \ 380 { scale = INTVAL (XEXP (ireg, 1)); \ 381 ireg = XEXP (ireg, 0); } \ 382 if (GET_CODE (ireg) == SIGN_EXTEND) \ 383 fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \ 384 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 385 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 386 reg_names[REGNO (XEXP (ireg, 0))]); \ 387 else \ 388 fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ 389 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 390 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 391 reg_names[REGNO (ireg)]); \ 392 if (scale != 1) fprintf (FILE, ":%d", scale); \ 393 putc (')', FILE); \ 394 break; } \ 395 if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \ 396 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ 397 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 398 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 399 reg_names[REGNO (breg)]); \ 400 putc (')', FILE); \ 401 break; } \ 402 if (ireg != 0 || breg != 0) \ 403 { int scale = 1; \ 404 if (breg == 0) \ 405 abort (); \ 406 if (addr && GET_CODE (addr) == LABEL_REF) abort (); \ 407 if (addr != 0) \ 408 output_addr_const (FILE, addr); \ 409 fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \ 410 if (breg != 0 && ireg != 0) \ 411 putc (',', FILE); \ 412 if (ireg != 0 && GET_CODE (ireg) == MULT) \ 413 { scale = INTVAL (XEXP (ireg, 1)); \ 414 ireg = XEXP (ireg, 0); } \ 415 if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \ 416 fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \ 417 else if (ireg != 0) \ 418 fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \ 419 if (scale != 1) fprintf (FILE, ":%d", scale); \ 420 putc (')', FILE); \ 421 break; \ 422 } \ 423 else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \ 424 { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \ 425 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 426 CODE_LABEL_NUMBER (XEXP (addr, 0)), \ 427 reg_names[REGNO (reg1)]); \ 428 break; } \ 429 default: \ 430 if (GET_CODE (addr) == CONST_INT \ 431 && INTVAL (addr) < 0x8000 \ 432 && INTVAL (addr) >= -0x8000) \ 433 fprintf (FILE, "%d", INTVAL (addr)); \ 434 else \ 435 output_addr_const (FILE, addr); \ 436 }} 437 438 #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \ 439 do { fprintf (FILE, "\t; file\t"); \ 440 output_quoted_string (FILE, FILENAME); \ 441 fprintf (FILE, "\n"); \ 442 } while (0) 443 444 #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \ 445 fprintf (FILE, "\t; ln\t%d\n", \ 446 (sdb_begin_function_line \ 447 ? (LINENO) - sdb_begin_function_line : 1)) 448 449 /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */ 450 /* UNOS ?? */ 451 #undef FUNCTION_PROFILER 452 #define FUNCTION_PROFILER(FILE, LABEL_NO) \ 453 fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO)) 454