|
|
1.1 ! root 1: /* Definitions of target machine for GNU compiler. ! 2: Charles River Data Systems UNiverse/32 ! 3: ! 4: Written by Gary E. Miller ! 5: bug reports to [email protected] ! 6: ! 7: Copyright (C) 1987 Free Software Foundation, Inc. ! 8: ! 9: This file is part of GNU CC. ! 10: ! 11: GNU CC is free software; you can redistribute it and/or modify ! 12: it under the terms of the GNU General Public License as published by ! 13: the Free Software Foundation; either version 2, or (at your option) ! 14: any later version. ! 15: ! 16: GNU CC is distributed in the hope that it will be useful, ! 17: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 19: GNU General Public License for more details. ! 20: ! 21: You should have received a copy of the GNU General Public License ! 22: along with GNU CC; see the file COPYING. If not, write to ! 23: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 24: ! 25: #define MOTOROLA /* Use Motorola syntax rather than "MIT" */ ! 26: #define SGS /* Uses SGS assembler */ ! 27: #define SGS_SWITCH_TABLES /* Different switch table handling */ ! 28: #define CRDS /* Charles River Data Systems assembler */ ! 29: ! 30: #include "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: #error This doesn't define STRUCTURE_SIZE_BOUNDARY ! 37: ! 38: /* See m68k.h. 0 means 680[01]0 with no 68881. */ ! 39: ! 40: #undef TARGET_DEFAULT ! 41: #define TARGET_DEFAULT 0 ! 42: ! 43: /* special flags to the unos assembler. */ ! 44: ! 45: #undef ASM_SPEC ! 46: #define ASM_SPEC "-g" ! 47: ! 48: #undef LIB_SPEC ! 49: #define LIB_SPEC "%{!p:%{!pg:-lunos}}%{p:-lc_p}%{pg:-lc_p}" ! 50: ! 51: #undef STARTFILE_SPEC ! 52: #define STARTFILE_SPEC \ ! 53: "%{pg:gcrt0.o%s}%{!pg:%{p:mc68rt0.o%s}%{!p:c68rt0.o%s}}" ! 54: ! 55: /* CC1 spec */ ! 56: #if 0 ! 57: /* c.sac only used in _s_call_r() in libunos.a and malloc() in libmalloc.a */ ! 58: /* so we do not need to bother ! */ ! 59: #define CC1_SPEC "-fpcc-struct-return" ! 60: #endif ! 61: ! 62: /* -O2 for MAX optimization */ ! 63: #undef CC1_SPEC ! 64: #define CC1_SPEC "%{O2:-fstrength-reduce}" ! 65: ! 66: /* cpp has to support a #sccs directive for the /usr/include files */ ! 67: ! 68: #define SCCS_DIRECTIVE ! 69: ! 70: /* Make output for SDB. */ ! 71: ! 72: /* #define SDB_DEBUGGING_INFO UNOS casm has no debugging :-( */ ! 73: ! 74: /* UNOS has vprintf() */ ! 75: ! 76: #define HAVE_VPRINTF ! 77: ! 78: /* UNOS need stack probe :-( */ ! 79: ! 80: #define HAVE_probe 1 ! 81: #define gen_probe() gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n") ! 82: ! 83: /* use memcpy, memset instead of bcopy, etc. */ ! 84: ! 85: #define TARGET_MEM_FUNCTIONS ! 86: ! 87: /* Don't try to define `gcc_compiled.' since the assembler might not ! 88: accept symbols with periods and GDB doesn't run on this machine anyway. */ ! 89: #define ASM_IDENTIFY_GCC(FILE) ! 90: ! 91: /* Define __HAVE_68881__ in preprocessor if -m68881 is specified. ! 92: This will control the use of inline 68881 insns in certain macros. */ ! 93: ! 94: #undef CPP_SPEC ! 95: #define CPP_SPEC "%{m68881:-D__HAVE_68881__}" ! 96: ! 97: /* Names to predefine in the preprocessor for this target machine. */ ! 98: ! 99: #undef CPP_PREDEFINES ! 100: #define CPP_PREDEFINES "-Dmc68k -DM68000 -Dmc68000 -Dunos -Dunix" ! 101: ! 102: /* Register in which address to store a structure value ! 103: is passed to a function. */ ! 104: /* unos uses ".comm c.sac" returns &c.sac in d0 */ ! 105: /* make pointer to c.sac ? ! 106: #undef STRUCT_VALUE_REGNUM ! 107: #define STRUCT_VALUE gen_rtx(MEM, Pmode, gen_rtx( , , ) ) ! 108: */ ! 109: ! 110: #define EXTRA_SECTIONS in_bss ! 111: ! 112: #define EXTRA_SECTION_FUNCTIONS \ ! 113: void \ ! 114: bss_section () \ ! 115: { \ ! 116: if (in_section != in_bss) \ ! 117: { \ ! 118: fprintf (asm_out_file, ".bss\n"); \ ! 119: in_section = in_bss; \ ! 120: } \ ! 121: } ! 122: ! 123: /* Specify how to pad function arguments. ! 124: Value should be `upward', `downward' or `none'. ! 125: Same as the default, except no padding for large or variable-size args. */ ! 126: ! 127: #define FUNCTION_ARG_PADDING(MODE, TYPE) \ ! 128: (((MODE) == BLKmode \ ! 129: ? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ ! 130: && int_size_in_bytes (TYPE) < PARM_BOUNDARY / BITS_PER_UNIT) \ ! 131: : GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY) \ ! 132: ? downward : none) ! 133: ! 134: /* Override part of the obstack macros. */ ! 135: ! 136: #define __PTR_TO_INT(P) ((int)(P)) ! 137: #define __INT_TO_PTR(P) ((char *)(P)) ! 138: ! 139: /* Override parts of m68k.h to fit the CRuDS assembler. */ ! 140: ! 141: #undef TARGET_VERSION ! 142: #define TARGET_VERSION fprintf (stderr, " (68k, CRDS/UNOS)"); ! 143: ! 144: /* Specify extra dir to search for include files. */ ! 145: #define SYSTEM_INCLUDE_DIR "/include" ! 146: ! 147: /* Control the assembler format that we output. */ ! 148: ! 149: /* Output at beginning of assembler file. */ ! 150: ! 151: #undef ASM_FILE_START ! 152: #define ASM_FILE_START(FILE) \ ! 153: fprintf (FILE, ";#NO_APP\n"); ! 154: ! 155: /* Output to assembler file text saying following lines ! 156: may contain character constants, extra white space, comments, etc. */ ! 157: ! 158: #undef ASM_APP_ON ! 159: #define ASM_APP_ON ";#APP\n" ! 160: ! 161: /* Output to assembler file text saying following lines ! 162: no longer contain unusual constructs. */ ! 163: ! 164: #undef ASM_APP_OFF ! 165: #define ASM_APP_OFF ";#NO_APP\n" ! 166: ! 167: /* This is how to output an assembler line defining a `double' constant. */ ! 168: ! 169: #undef ASM_OUTPUT_DOUBLE ! 170: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ ! 171: do { union { double f; long l[2];} tem; \ ! 172: tem.f = (VALUE); \ ! 173: fprintf (FILE, "\t.long 0x%x, 0x%x\n", tem.l[0], tem.l[1]); \ ! 174: } while (0) ! 175: ! 176: /*unos has no .skip :-( */ ! 177: #undef ASM_OUTPUT_SKIP ! 178: #define ASM_OUTPUT_SKIP(FILE,SIZE) \ ! 179: fprintf (FILE, "\t. = . + %u\n", (SIZE)); ! 180: ! 181: /* This says how to output an assembler line ! 182: to define a local common symbol. */ ! 183: /* should use bss_section instead of data_section but this makes casm die ? */ ! 184: ! 185: #undef ASM_OUTPUT_LOCAL ! 186: #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! 187: { data_section (); \ ! 188: if ((SIZE) > 1) fprintf (FILE, "\t.even\n"); \ ! 189: assemble_name ((FILE), (NAME)); \ ! 190: fprintf ((FILE), ":\t. = . + %u\n", (ROUNDED));} ! 191: ! 192: /* This is how to output an insn to push a register on the stack. ! 193: It need not be very fast code. */ ! 194: ! 195: #undef ASM_OUTPUT_REG_PUSH ! 196: #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ ! 197: fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[REGNO]) ! 198: ! 199: /* This is how to output an insn to pop a register from the stack. ! 200: It need not be very fast code. */ ! 201: ! 202: #undef ASM_OUTPUT_REG_POP ! 203: #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ ! 204: fprintf (FILE, "\tmovel (sp)+,%s\n", reg_names[REGNO]) ! 205: ! 206: #undef ASM_OUTPUT_ASCII ! 207: #define ASM_OUTPUT_ASCII(FILE, P , SIZE) \ ! 208: { int i; \ ! 209: fprintf ((FILE), "\t.ascii \""); \ ! 210: for (i = 0; i < (SIZE); i++) \ ! 211: { \ ! 212: register int c = (P)[i]; \ ! 213: if (i != 0 && (i / 200) * 200 == i) \ ! 214: fprintf ((FILE), "\"\n\t.ascii \""); \ ! 215: if (c >= ' ' && c < 0177) { \ ! 216: if (c != '\"' && c != '\\') { \ ! 217: putc (c, (FILE)); \ ! 218: continue; \ ! 219: } \ ! 220: } \ ! 221: /* brain dead asm doesn't understand char escapes */ \ ! 222: fprintf ((FILE), "\"\n\t.byte\t%d\n\t.ascii \"", c); \ ! 223: } \ ! 224: fprintf ((FILE), "\"\n"); \ ! 225: } ! 226: ! 227: ! 228: /* Change all JBxx to Bxx. Also change all DBRA to DBF. ! 229: Also change divs.l, etc., to divs, etc. But don't change divsl.l. */ ! 230: ! 231: #define ASM_OUTPUT_OPCODE(FILE, PTR) \ ! 232: { if ((PTR)[0] == 'j' && (PTR)[1] == 'b') \ ! 233: { ++(PTR); } \ ! 234: else if ((PTR)[0] == 'd') \ ! 235: { \ ! 236: if (!strncmp ((PTR), "dbra", 4)) \ ! 237: { fprintf ((FILE), "dbf"); (PTR) += 4; } \ ! 238: else if (!strncmp ((PTR), "div", 3) && (PTR)[5] == ' ') \ ! 239: { fprintf ((FILE), "div%c", (PTR)[3]); (PTR) += 6; } \ ! 240: } \ ! 241: } ! 242: ! 243: ! 244: /* Print operand X (an rtx) in assembler syntax to file FILE. ! 245: CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. ! 246: For `%' followed by punctuation, CODE is the punctuation and X is null. ! 247: ! 248: On the 68000, we use several CODE characters: ! 249: '.' for dot needed in Motorola-style opcode names. ! 250: '-' for an operand pushing on the stack: ! 251: sp@-, -(sp) or -(%sp) depending on the style of syntax. ! 252: '+' for an operand pushing on the stack: ! 253: sp@+, (sp)+ or (%sp)+ depending on the style of syntax. ! 254: '@' for a reference to the top word on the stack: ! 255: sp@, (sp) or (%sp) depending on the style of syntax. ! 256: '#' for an immediate operand prefix (# in MIT and Motorola syntax ! 257: but & in SGS syntax, $ in unos syntax). ! 258: '!' for the cc register (used in an `and to cc' insn). ! 259: ! 260: 'b' for byte insn (no effect, on the Sun; this is for the ISI). ! 261: 'd' to force memory addressing to be absolute, not relative. ! 262: 'f' for float insn (print a CONST_DOUBLE as a float rather than in hex) ! 263: 'w' for FPA insn (print a CONST_DOUBLE as a SunFPA constant rather ! 264: than directly). Second part of 'y' below. ! 265: 'x' for float insn (print a CONST_DOUBLE as a float rather than in hex), ! 266: or print pair of registers as rx:ry. ! 267: 'y' for a FPA insn (print pair of registers as rx:ry). This also outputs ! 268: CONST_DOUBLE's as SunFPA constant RAM registers if ! 269: possible, so it should not be used except for the SunFPA. */ ! 270: ! 271: #undef PRINT_OPERAND_PUNCT_VALID_P ! 272: #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ! 273: ((CODE) == '.' || (CODE) == '#' || (CODE) == '-' \ ! 274: || (CODE) == '+' || (CODE) == '@' || (CODE) == '!') ! 275: ! 276: #undef PRINT_OPERAND ! 277: #define PRINT_OPERAND(FILE, X, CODE) \ ! 278: { int i; \ ! 279: if (CODE == '.') ; \ ! 280: else if (CODE == '#') fprintf (FILE, "$"); \ ! 281: else if (CODE == '-') fprintf (FILE, "-(sp)"); \ ! 282: else if (CODE == '+') fprintf (FILE, "(sp)+"); \ ! 283: else if (CODE == '@') fprintf (FILE, "(sp)"); \ ! 284: else if (CODE == '!') fprintf (FILE, "cc"); \ ! 285: else if (GET_CODE (X) == REG) \ ! 286: { if (REGNO (X) < 16 && (CODE == 'y' || CODE == 'x') && GET_MODE (X) == DFmode) \ ! 287: fprintf (FILE, "%s:%s", reg_names[REGNO (X)], reg_names[REGNO (X)+1]); \ ! 288: else \ ! 289: fprintf (FILE, "%s", reg_names[REGNO (X)]); \ ! 290: } \ ! 291: else if (GET_CODE (X) == MEM) \ ! 292: { \ ! 293: output_address (XEXP (X, 0)); \ ! 294: if (CODE == 'd' && ! TARGET_68020 \ ! 295: && CONSTANT_ADDRESS_P (XEXP (X, 0))) \ ! 296: /* fprintf (FILE, ".l") */; \ ! 297: } \ ! 298: else if ((CODE == 'y' || CODE == 'w') \ ! 299: && GET_CODE(X) == CONST_DOUBLE \ ! 300: && (i = standard_sun_fpa_constant_p (X))) \ ! 301: fprintf (FILE, "%%%d", i & 0x1ff); \ ! 302: else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \ ! 303: { union { double d; int i[2]; } u; \ ! 304: union { float f; int i; } u1; \ ! 305: u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ ! 306: u1.f = u.d; \ ! 307: if (CODE == 'f') \ ! 308: ASM_OUTPUT_FLOAT_OPERAND (FILE, u1.f); \ ! 309: else \ ! 310: fprintf (FILE, "$0x%x", u1.i); } \ ! 311: else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \ ! 312: { union { double d; int i[2]; } u; \ ! 313: u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \ ! 314: ASM_OUTPUT_DOUBLE_OPERAND (FILE, u.d); } \ ! 315: else { putc ('$', FILE); output_addr_const (FILE, X); }} ! 316: ! 317: /* Note that this contains a kludge that knows that the only reason ! 318: we have an address (plus (label_ref...) (reg...)) ! 319: is in the insn before a tablejump, and we know that m68k.md ! 320: generates a label LInnn: on such an insn. */ ! 321: #undef PRINT_OPERAND_ADDRESS ! 322: #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ ! 323: { register rtx reg1, reg2, breg, ireg; \ ! 324: register rtx addr = ADDR; \ ! 325: rtx offset; \ ! 326: switch (GET_CODE (addr)) \ ! 327: { \ ! 328: case REG: \ ! 329: fprintf (FILE, "(%s)", reg_names[REGNO (addr)]); \ ! 330: break; \ ! 331: case PRE_DEC: \ ! 332: fprintf (FILE, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); \ ! 333: break; \ ! 334: case POST_INC: \ ! 335: fprintf (FILE, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); \ ! 336: break; \ ! 337: case PLUS: \ ! 338: reg1 = 0; reg2 = 0; \ ! 339: ireg = 0; breg = 0; \ ! 340: offset = 0; \ ! 341: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) \ ! 342: { \ ! 343: offset = XEXP (addr, 0); \ ! 344: addr = XEXP (addr, 1); \ ! 345: } \ ! 346: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) \ ! 347: { \ ! 348: offset = XEXP (addr, 1); \ ! 349: addr = XEXP (addr, 0); \ ! 350: } \ ! 351: if (GET_CODE (addr) != PLUS) ; \ ! 352: else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) \ ! 353: { \ ! 354: reg1 = XEXP (addr, 0); \ ! 355: addr = XEXP (addr, 1); \ ! 356: } \ ! 357: else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) \ ! 358: { \ ! 359: reg1 = XEXP (addr, 1); \ ! 360: addr = XEXP (addr, 0); \ ! 361: } \ ! 362: else if (GET_CODE (XEXP (addr, 0)) == MULT) \ ! 363: { \ ! 364: reg1 = XEXP (addr, 0); \ ! 365: addr = XEXP (addr, 1); \ ! 366: } \ ! 367: else if (GET_CODE (XEXP (addr, 1)) == MULT) \ ! 368: { \ ! 369: reg1 = XEXP (addr, 1); \ ! 370: addr = XEXP (addr, 0); \ ! 371: } \ ! 372: else if (GET_CODE (XEXP (addr, 0)) == REG) \ ! 373: { \ ! 374: reg1 = XEXP (addr, 0); \ ! 375: addr = XEXP (addr, 1); \ ! 376: } \ ! 377: else if (GET_CODE (XEXP (addr, 1)) == REG) \ ! 378: { \ ! 379: reg1 = XEXP (addr, 1); \ ! 380: addr = XEXP (addr, 0); \ ! 381: } \ ! 382: if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT \ ! 383: || GET_CODE (addr) == SIGN_EXTEND) \ ! 384: { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; } \ ! 385: if (offset != 0) { if (addr != 0) abort (); addr = offset; } \ ! 386: if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND \ ! 387: || GET_CODE (reg1) == MULT)) \ ! 388: || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) \ ! 389: { breg = reg2; ireg = reg1; } \ ! 390: else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) \ ! 391: { breg = reg1; ireg = reg2; } \ ! 392: if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF) \ ! 393: { int scale = 1; \ ! 394: if (GET_CODE (ireg) == MULT) \ ! 395: { scale = INTVAL (XEXP (ireg, 1)); \ ! 396: ireg = XEXP (ireg, 0); } \ ! 397: if (GET_CODE (ireg) == SIGN_EXTEND) \ ! 398: fprintf (FILE, "L%d-LI%d-2(pc,%s.w", \ ! 399: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 400: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 401: reg_names[REGNO (XEXP (ireg, 0))]); \ ! 402: else \ ! 403: fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ ! 404: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 405: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 406: reg_names[REGNO (ireg)]); \ ! 407: if (scale != 1) fprintf (FILE, ":%d", scale); \ ! 408: putc (')', FILE); \ ! 409: break; } \ ! 410: if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF) \ ! 411: { fprintf (FILE, "L%d-LI%d-2(pc,%s.l", \ ! 412: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 413: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 414: reg_names[REGNO (breg)]); \ ! 415: putc (')', FILE); \ ! 416: break; } \ ! 417: if (ireg != 0 || breg != 0) \ ! 418: { int scale = 1; \ ! 419: if (breg == 0) \ ! 420: abort (); \ ! 421: if (addr && GET_CODE (addr) == LABEL_REF) abort (); \ ! 422: if (addr != 0) \ ! 423: output_addr_const (FILE, addr); \ ! 424: fprintf (FILE, "(%s", reg_names[REGNO (breg)]); \ ! 425: if (breg != 0 && ireg != 0) \ ! 426: putc (',', FILE); \ ! 427: if (ireg != 0 && GET_CODE (ireg) == MULT) \ ! 428: { scale = INTVAL (XEXP (ireg, 1)); \ ! 429: ireg = XEXP (ireg, 0); } \ ! 430: if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) \ ! 431: fprintf (FILE, "%s.w", reg_names[REGNO (XEXP (ireg, 0))]); \ ! 432: else if (ireg != 0) \ ! 433: fprintf (FILE, "%s.l", reg_names[REGNO (ireg)]); \ ! 434: if (scale != 1) fprintf (FILE, ":%d", scale); \ ! 435: putc (')', FILE); \ ! 436: break; \ ! 437: } \ ! 438: else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF) \ ! 439: { fprintf (FILE, "L%d-LI%d-2(pc,%s.l)", \ ! 440: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 441: CODE_LABEL_NUMBER (XEXP (addr, 0)), \ ! 442: reg_names[REGNO (reg1)]); \ ! 443: break; } \ ! 444: default: \ ! 445: if (GET_CODE (addr) == CONST_INT \ ! 446: && INTVAL (addr) < 0x8000 \ ! 447: && INTVAL (addr) >= -0x8000) \ ! 448: fprintf (FILE, "%d", INTVAL (addr)); \ ! 449: else \ ! 450: output_addr_const (FILE, addr); \ ! 451: }} ! 452: ! 453: #define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \ ! 454: fprintf (FILE, "\t; file\t\"%s\"\n", FILENAME) ! 455: ! 456: #define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO) \ ! 457: fprintf (FILE, "\t; ln\t%d\n", \ ! 458: (sdb_begin_function_line \ ! 459: ? last_linenum - sdb_begin_function_line : 1)) ! 460: ! 461: /* This macro generates the assembly code for function entry. ! 462: FILE is a stdio stream to output the code to. ! 463: SIZE is an int: how many units of temporary storage to allocate. ! 464: Refer to the array `regs_ever_live' to determine which registers ! 465: to save; `regs_ever_live[I]' is nonzero if register number I ! 466: is ever used in the function. This macro is responsible for ! 467: knowing which registers should not be saved even if used. */ ! 468: ! 469: /* Note that the order of the bit mask for fmovem is the opposite ! 470: of the order for movem! */ ! 471: ! 472: #undef FUNCTION_PROLOGUE ! 473: #define FUNCTION_PROLOGUE(FILE, SIZE) \ ! 474: { register int regno; \ ! 475: register int mask = 0; \ ! 476: extern char call_used_regs[]; \ ! 477: int fsize = ((SIZE) + 3) & -4; \ ! 478: /* unos stack probe */ \ ! 479: if ( fsize > 30000 ) { \ ! 480: fprintf (FILE, "\tmovel sp,a0\n"); \ ! 481: fprintf (FILE, "\taddl $-%d,a0\n", 2048 + fsize); \ ! 482: fprintf (FILE, "\ttstb (a0)\n"); \ ! 483: } else { \ ! 484: fprintf (FILE, "\ttstb -%d(sp)\n", 2048 + fsize); \ ! 485: } \ ! 486: if (frame_pointer_needed) \ ! 487: { if (TARGET_68020 || fsize < 0x8000) \ ! 488: fprintf (FILE, "\tlink a6,$%d\n", -fsize); \ ! 489: else \ ! 490: fprintf (FILE, "\tlink a6,$0\n\tsubl $%d,sp\n", fsize); } \ ! 491: for (regno = 24; regno < 56; regno++) \ ! 492: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 493: fprintf(FILE, "\tfpmoved %s, sp@-\n", \ ! 494: reg_names[regno]); \ ! 495: for (regno = 16; regno < 24; regno++) \ ! 496: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 497: mask |= 1 << (regno - 16); \ ! 498: if ((mask & 0xff) != 0) \ ! 499: fprintf (FILE, "\tfmovem $0x%x,-(sp)\n", mask & 0xff); \ ! 500: mask = 0; \ ! 501: for (regno = 0; regno < 16; regno++) \ ! 502: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 503: mask |= 1 << (15 - regno); \ ! 504: if (frame_pointer_needed) \ ! 505: mask &= ~ (1 << (15-FRAME_POINTER_REGNUM)); \ ! 506: if (exact_log2 (mask) >= 0) \ ! 507: fprintf (FILE, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]); \ ! 508: else if (mask) fprintf (FILE, "\tmovem $0x%x,-(sp)\n", mask); } ! 509: ! 510: /* Must put address in %a0 , not %d0 . -- LGM, 7/15/88 */ ! 511: /* UNOS ?? */ ! 512: #undef FUNCTION_PROFILER ! 513: #define FUNCTION_PROFILER(FILE, LABEL_NO) \ ! 514: fprintf (FILE, "\tmovl &LP%%%d,%%a0\n\tjsr mcount\n", (LABEL_NO)) ! 515: ! 516: /* This macro generates the assembly code for function exit, ! 517: on machines that need it. If FUNCTION_EPILOGUE is not defined ! 518: then individual return instructions are generated for each ! 519: return statement. Args are same as for FUNCTION_PROLOGUE. ! 520: ! 521: The function epilogue should not depend on the current stack pointer! ! 522: It should use the frame pointer only. This is mandatory because ! 523: of alloca; we also take advantage of it to omit stack adjustments ! 524: before returning. */ ! 525: ! 526: #undef FUNCTION_EPILOGUE ! 527: #define FUNCTION_EPILOGUE(FILE, SIZE) \ ! 528: { register int regno; \ ! 529: register int mask, fmask; \ ! 530: register int nregs; \ ! 531: int offset, foffset, fpoffset; \ ! 532: extern char call_used_regs[]; \ ! 533: int fsize = ((SIZE) + 3) & -4; \ ! 534: int big = 0; \ ! 535: nregs = 0; fmask = 0; fpoffset = 0; \ ! 536: for (regno = 24 ; regno < 56 ; regno++) \ ! 537: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 538: nregs++; \ ! 539: fpoffset = nregs*8; \ ! 540: nregs = 0; \ ! 541: for (regno = 16; regno < 24; regno++) \ ! 542: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 543: { nregs++; fmask |= 1 << (23 - regno); } \ ! 544: foffset = fpoffset + nregs * 12; \ ! 545: nregs = 0; mask = 0; \ ! 546: if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; \ ! 547: for (regno = 0; regno < 16; regno++) \ ! 548: if (regs_ever_live[regno] && ! call_used_regs[regno]) \ ! 549: { nregs++; mask |= 1 << regno; } \ ! 550: offset = foffset + nregs * 4; \ ! 551: if (offset + fsize >= 0x8000 \ ! 552: && frame_pointer_needed \ ! 553: && (mask || fmask || fpoffset)) \ ! 554: { fprintf (FILE, "\tmovel $%d,a0\n", -fsize); \ ! 555: fsize = 0, big = 1; } \ ! 556: if (exact_log2 (mask) >= 0) { \ ! 557: if (big) \ ! 558: fprintf (FILE, "\tmovel -%d(a6,a0.l),%s\n", \ ! 559: offset + fsize, reg_names[exact_log2 (mask)]); \ ! 560: else if (! frame_pointer_needed) \ ! 561: fprintf (FILE, "\tmovel (sp)+,%s\n", \ ! 562: reg_names[exact_log2 (mask)]); \ ! 563: else \ ! 564: fprintf (FILE, "\tmovel -%d(a6),%s\n", \ ! 565: offset + fsize, reg_names[exact_log2 (mask)]); } \ ! 566: else if (mask) { \ ! 567: if (big) \ ! 568: fprintf (FILE, "\tmovem -%d(a6,a0.l),$0x%x\n", \ ! 569: offset + fsize, mask); \ ! 570: else if (! frame_pointer_needed) \ ! 571: fprintf (FILE, "\tmovem (sp)+,$0x%x\n", mask); \ ! 572: else \ ! 573: fprintf (FILE, "\tmovem -%d(a6),$0x%x\n", \ ! 574: offset + fsize, mask); } \ ! 575: if (fmask) { \ ! 576: if (big) \ ! 577: fprintf (FILE, "\tfmovem -%d(a6,a0.l),$0x%x\n", \ ! 578: foffset + fsize, fmask); \ ! 579: else if (! frame_pointer_needed) \ ! 580: fprintf (FILE, "\tfmovem (sp)+,$0x%x\n", fmask); \ ! 581: else \ ! 582: fprintf (FILE, "\tfmovem -%d(a6),$0x%x\n", \ ! 583: foffset + fsize, fmask); } \ ! 584: if (fpoffset != 0) \ ! 585: for (regno = 55; regno >= 24; regno--) \ ! 586: if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ ! 587: if (big) \ ! 588: fprintf(FILE, "\tfpmoved -%d(a6,a0.l), %s\n", \ ! 589: fpoffset + fsize, reg_names[regno]); \ ! 590: else if (! frame_pointer_needed) \ ! 591: fprintf(FILE, "\tfpmoved (sp)+, %s\n", \ ! 592: reg_names[regno]); \ ! 593: else \ ! 594: fprintf(FILE, "\tfpmoved -%d(a6), %s\n", \ ! 595: fpoffset + fsize, reg_names[regno]); \ ! 596: fpoffset -= 8; \ ! 597: } \ ! 598: if (frame_pointer_needed) \ ! 599: fprintf (FILE, "\tunlk a6\n"); \ ! 600: if (current_function_pops_args) \ ! 601: fprintf (FILE, "\trtd $%d\n", current_function_pops_args); \ ! 602: else fprintf (FILE, "\trts\n"); } ! 603:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.