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