|
|
1.1 ! root 1: /* Definitions of target machine for GNU compiler. Tahoe version. ! 2: Copyright (C) 1989 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: /* ! 21: * File: tahoe.h ! 22: * ! 23: * Original port made at the University of Buffalo by Devon Bowen, ! 24: * Dale Wiles and Kevin Zachmann. ! 25: * ! 26: * HCX/UX version by Piet van Oostrum ([email protected]) ! 27: * ! 28: * Performance hacking by Michael Tiemann ([email protected]) ! 29: * ! 30: * Mail bugs reports or fixes to: [email protected] ! 31: */ ! 32: ! 33: /* define this for the HCX/UX version */ ! 34: ! 35: /* #define HCX_UX */ ! 36: ! 37: /* ! 38: * Run-time Target Specification ! 39: */ ! 40: ! 41: #ifdef HCX_UX ! 42: /* no predefines, see Makefile and hcx-universe.c */ ! 43: /* have cc1 print that this is the hcx version */ ! 44: #define TARGET_VERSION printf (" (hcx)"); ! 45: #else ! 46: /* we want "tahoe" and "unix" defined for all future compilations */ ! 47: #define CPP_PREDEFINES "-Dtahoe -Dunix -Asystem(unix) -Acpu(tahoe) -Amachine(tahoe)" ! 48: /* have cc1 print that this is the tahoe version */ ! 49: #define TARGET_VERSION printf (" (tahoe)"); ! 50: #endif ! 51: ! 52: /* this is required in all tm files to hold flags */ ! 53: ! 54: extern int target_flags; ! 55: ! 56: /* Zero if it is safe to output .dfloat and .float pseudos. */ ! 57: #define TARGET_HEX_FLOAT (target_flags & 1) ! 58: ! 59: #define TARGET_DEFAULT 1 ! 60: ! 61: #define TARGET_SWITCHES \ ! 62: { {"hex-float", 1}, \ ! 63: {"no-hex-float", -1}, \ ! 64: { "", TARGET_DEFAULT} } ! 65: ! 66: ! 67: /* ! 68: * Storage Layout ! 69: */ ! 70: ! 71: /* This symbol was previously not mentioned, so apparently the tahoe ! 72: is little-endian for bits, or else doesn't care. */ ! 73: #define BITS_BIG_ENDIAN 0 ! 74: ! 75: /* tahoe uses a big endian byte order */ ! 76: ! 77: #define BYTES_BIG_ENDIAN 1 ! 78: ! 79: /* tahoe uses a big endian word order */ ! 80: ! 81: #define WORDS_BIG_ENDIAN 1 ! 82: ! 83: /* standard byte size is usable on tahoe */ ! 84: ! 85: #define BITS_PER_UNIT 8 ! 86: ! 87: /* longs on the tahoe are 4 byte groups */ ! 88: ! 89: #define BITS_PER_WORD 32 ! 90: ! 91: /* from the last two params we get 4 bytes per word */ ! 92: ! 93: #define UNITS_PER_WORD 4 ! 94: ! 95: /* addresses are 32 bits (one word) */ ! 96: ! 97: #define POINTER_SIZE 32 ! 98: ! 99: /* all parameters line up on 32 boundaries */ ! 100: ! 101: #define PARM_BOUNDARY 32 ! 102: ! 103: /* stack should line up on 32 boundaries */ ! 104: ! 105: #define STACK_BOUNDARY 32 ! 106: ! 107: /* line functions up on 32 bits */ ! 108: ! 109: #define FUNCTION_BOUNDARY 32 ! 110: ! 111: /* the biggest alignment the tahoe needs in 32 bits */ ! 112: ! 113: #define BIGGEST_ALIGNMENT 32 ! 114: ! 115: /* we have to align after an 'int : 0' in a structure */ ! 116: ! 117: #define EMPTY_FIELD_BOUNDARY 32 ! 118: ! 119: #ifdef HCX_UX ! 120: /* structures must be made of full words */ ! 121: ! 122: #define STRUCTURE_SIZE_BOUNDARY 32 ! 123: #else ! 124: /* structures must be made of full bytes */ ! 125: ! 126: #define STRUCTURE_SIZE_BOUNDARY 8 ! 127: #endif ! 128: ! 129: /* tahoe is picky about data alignment */ ! 130: ! 131: #define STRICT_ALIGNMENT 1 ! 132: ! 133: /* keep things standard with pcc */ ! 134: ! 135: #define PCC_BITFIELD_TYPE_MATTERS 1 ! 136: ! 137: /* this section is borrowed from the vax version since the */ ! 138: /* formats are the same in both of the architectures */ ! 139: ! 140: #define CHECK_FLOAT_VALUE(mode, d) \ ! 141: if ((mode) == SFmode) \ ! 142: { \ ! 143: if ((d) > 1.7014117331926443e+38) \ ! 144: { error ("magnitude of constant too large for `float'"); \ ! 145: (d) = 1.7014117331926443e+38; } \ ! 146: else if ((d) < -1.7014117331926443e+38) \ ! 147: { error ("magnitude of constant too large for `float'"); \ ! 148: (d) = -1.7014117331926443e+38; } \ ! 149: else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \ ! 150: { warning ("`float' constant truncated to zero"); \ ! 151: (d) = 0.0; } \ ! 152: else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \ ! 153: { warning ("`float' constant truncated to zero"); \ ! 154: (d) = 0.0; } \ ! 155: } ! 156: ! 157: ! 158: /* ! 159: * Register Usage ! 160: */ ! 161: ! 162: /* define 15 general regs plus one for the floating point reg (FPP) */ ! 163: ! 164: #define FIRST_PSEUDO_REGISTER 17 ! 165: ! 166: /* let the compiler know what the fp, sp and pc are */ ! 167: ! 168: #define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0} ! 169: ! 170: /* lots of regs aren't guaranteed to return from a call. The FPP reg */ ! 171: /* must be included in these since it can't be saved by the reg mask */ ! 172: ! 173: #define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1} ! 174: ! 175: /* A single fp reg can handle any type of float. ! 176: CPU regs hold just 32 bits. */ ! 177: ! 178: #define HARD_REGNO_NREGS(REGNO, MODE) \ ! 179: (REGNO != 16 ? ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) \ ! 180: : GET_MODE_NUNITS ((MODE))) ! 181: ! 182: /* any mode greater than 4 bytes (doubles) can only go in an even regs */ ! 183: /* and the FPP can only hold SFmode and DFmode */ ! 184: ! 185: #define HARD_REGNO_MODE_OK(REGNO, MODE) \ ! 186: (REGNO != 16 \ ! 187: ? (GET_MODE_UNIT_SIZE (MODE) <= 4 ? 1 : (REGNO % 2 - 1)) \ ! 188: : ((MODE) == SFmode || (MODE) == DFmode \ ! 189: || (MODE) == SCmode || (MODE) == DCmode)) ! 190: ! 191: /* if mode1 or mode2, but not both, are doubles then modes cannot be tied */ ! 192: ! 193: #define MODES_TIEABLE_P(MODE1, MODE2) \ ! 194: (((MODE1) == DFmode || (MODE1) == DCmode) \ ! 195: == ((MODE2) == DFmode || (MODE2) == DCmode)) ! 196: ! 197: /* return nonzero if register variable of mode MODE is not ! 198: a priori a bad idea. Used only if defined. */ ! 199: #define MODE_OK_FOR_USERVAR(MODE) \ ! 200: ((MODE) == SImode) ! 201: ! 202: /* the program counter is reg 15 */ ! 203: ! 204: #define PC_REGNUM 15 ! 205: ! 206: /* the stack pointer is reg 14 */ ! 207: ! 208: #define STACK_POINTER_REGNUM 14 ! 209: ! 210: /* the frame pointer is reg 13 */ ! 211: ! 212: #define FRAME_POINTER_REGNUM 13 ! 213: ! 214: /* tahoe does require an fp */ ! 215: ! 216: #define FRAME_POINTER_REQUIRED 1 ! 217: ! 218: /* since tahoe doesn't have a argument pointer, make it the fp */ ! 219: ! 220: #define ARG_POINTER_REGNUM 13 ! 221: ! 222: /* this isn't currently used since C doesn't support this feature */ ! 223: ! 224: #define STATIC_CHAIN_REGNUM 0 ! 225: ! 226: /* we'll use reg 1 for structure passing cause the destination */ ! 227: /* of the eventual movblk requires it to be there anyway. */ ! 228: ! 229: #define STRUCT_VALUE_REGNUM 1 ! 230: ! 231: ! 232: /* ! 233: * Register Classes ! 234: */ ! 235: ! 236: /* tahoe has two types of regs. GENERAL_REGS are all the regs up */ ! 237: /* to number 15. FPP_REG is the special floating point processor */ ! 238: /* register class (only one reg). */ ! 239: ! 240: enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES}; ! 241: ! 242: /* defines the number of reg classes. */ ! 243: ! 244: #define N_REG_CLASSES (int) LIM_REG_CLASSES ! 245: ! 246: /* this defines what the classes are officially named for debugging */ ! 247: ! 248: #define REG_CLASS_NAMES \ ! 249: {"NO_REGS","GENERAL_REGS","FPP_REG","ALL_REGS"} ! 250: ! 251: /* set general regs to be the first 16 regs and the fpp reg to be 17th */ ! 252: ! 253: #define REG_CLASS_CONTENTS {0,0xffff,0x10000,0x1ffff} ! 254: ! 255: /* register class for the fpp reg is FPP_REG, all others are GENERAL_REGS */ ! 256: ! 257: #define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS) ! 258: ! 259: /* only general registers can be used as a base reg */ ! 260: ! 261: #define BASE_REG_CLASS GENERAL_REGS ! 262: ! 263: /* only general registers can be used to index */ ! 264: ! 265: #define INDEX_REG_CLASS GENERAL_REGS ! 266: ! 267: /* 'a' as a constraint in the md file means the FFP_REG class */ ! 268: ! 269: #define REG_CLASS_FROM_LETTER(C) (C == 'a' ? FPP_REG : NO_REGS) ! 270: ! 271: /* any general reg but the fpp can be a base reg */ ! 272: ! 273: #define REGNO_OK_FOR_BASE_P(regno) \ ! 274: ((regno) < FIRST_PSEUDO_REGISTER - 1 || reg_renumber[regno] >= 0) ! 275: ! 276: /* any general reg except the pc and fpp can be an index reg */ ! 277: ! 278: #define REGNO_OK_FOR_INDEX_P(regno) \ ! 279: ((regno) < FIRST_PSEUDO_REGISTER - 2 || reg_renumber[regno] >= 0) ! 280: ! 281: /* if your loading a floating point constant, it can't be done */ ! 282: /* through a register. Force it to be a memory constant. */ ! 283: ! 284: #define PREFERRED_RELOAD_CLASS(X,CLASS) \ ! 285: ((GET_CODE (X) == CONST_DOUBLE) ? NO_REGS : CLASS) ! 286: ! 287: /* for the fpp reg, all modes fit; for any others, you need two for doubles */ ! 288: ! 289: #define CLASS_MAX_NREGS(CLASS, MODE) \ ! 290: (CLASS != FPP_REG ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : 1) ! 291: ! 292: /* we don't define any special constant sizes so all should fail */ ! 293: ! 294: #define CONST_OK_FOR_LETTER_P(VALUE, C) 0 ! 295: ! 296: /* we don't define any special double sizes so all should fail */ ! 297: ! 298: #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 ! 299: ! 300: ! 301: /* ! 302: * Describing Stack Layout ! 303: */ ! 304: ! 305: /* tahoe stack grows from high to low memory */ ! 306: ! 307: #define STACK_GROWS_DOWNWARD ! 308: ! 309: /* Define this if longjmp restores from saved registers ! 310: rather than from what setjmp saved. */ ! 311: #define LONGJMP_RESTORE_FROM_STACK ! 312: ! 313: /* tahoe call frames grow from high to low memory on the stack */ ! 314: ! 315: #define FRAME_GROWS_DOWNWARD ! 316: ! 317: /* the tahoe fp points to the *top* of the frame instead of the */ ! 318: /* bottom, so we have to make this offset a constant large enough */ ! 319: /* to jump over the biggest frame possible. */ ! 320: ! 321: #define STARTING_FRAME_OFFSET -52 ! 322: ! 323: /* tahoe always pushes 4 bytes unless it's a double in which case */ ! 324: /* it pushes a full 8 bytes. */ ! 325: ! 326: #define PUSH_ROUNDING(BYTES) (BYTES <= 4 ? 4 : 8) ! 327: ! 328: /* the first parameter in a function is at the fp + 4 */ ! 329: ! 330: #define FIRST_PARM_OFFSET(FNDECL) 4 ! 331: ! 332: /* the tahoe return function takes care of everything on the stack */ ! 333: ! 334: #define RETURN_POPS_ARGS(FUNTYPE,SIZE) (SIZE) ! 335: ! 336: /* function values for all types are returned in register 0 */ ! 337: ! 338: #define FUNCTION_VALUE(VALTYPE, FUNC) \ ! 339: gen_rtx (REG, TYPE_MODE (VALTYPE), 0) ! 340: ! 341: /* library routines also return things in reg 0 */ ! 342: ! 343: #define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) ! 344: ! 345: /* Tahoe doesn't return structures in a reentrant way */ ! 346: ! 347: #define PCC_STATIC_STRUCT_RETURN ! 348: ! 349: /* we only return values from a function in reg 0 */ ! 350: ! 351: #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) ! 352: ! 353: /* we never pass args through a register */ ! 354: ! 355: #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 ! 356: ! 357: /* int is fine to hold the argument summary in FUNCTION_ARG */ ! 358: ! 359: #define CUMULATIVE_ARGS int ! 360: ! 361: /* we just set CUM to 0 before the FUNCTION_ARG call. No matter what */ ! 362: /* we make it, FUNCTION_ARG will return 0 anyway */ ! 363: ! 364: #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \ ! 365: ((CUM) = 0) ! 366: ! 367: /* all modes push their size rounded to the nearest word boundary */ ! 368: /* except block which is the size of the block rounded up */ ! 369: ! 370: #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ ! 371: ((CUM) += ((MODE) != BLKmode \ ! 372: ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ ! 373: : (int_size_in_bytes (TYPE) + 3) & ~3)) ! 374: ! 375: /* this is always false since we never pass params in regs */ ! 376: ! 377: #define FUNCTION_ARG_REGNO_P(N) 0 ! 378: ! 379: /* this code calculates the register entry mask and sets up */ ! 380: /* the stack pointer for the function. The stack is set down */ ! 381: /* far enough from the fp to jump over any push regs and local */ ! 382: /* vars. This is a problem since the tahoe has the fp pointing */ ! 383: /* to the top of the frame and the compiler must know the off- */ ! 384: /* set off the fp to the local vars. */ ! 385: ! 386: #define FUNCTION_PROLOGUE(FILE, SIZE) \ ! 387: { register int regno; \ ! 388: register int mask = 0; \ ! 389: extern char call_used_regs[]; \ ! 390: for (regno = 0; regno < FIRST_PSEUDO_REGISTER-1; regno++) \ ! 391: if (regs_ever_live[regno] && !call_used_regs[regno]) \ ! 392: mask |= 1 << regno; \ ! 393: fprintf (FILE, "\t.word 0x%x\n", mask); \ ! 394: if (SIZE != 0) fprintf (FILE, "\tsubl3 $%d,fp,sp\n", (SIZE) - STARTING_FRAME_OFFSET); } ! 395: ! 396: /* Zero out global variable in case it was used in this function. */ ! 397: #define FUNCTION_EPILOGUE(FILE, SIZE) \ ! 398: { extern rtx tahoe_reg_conversion_loc; \ ! 399: tahoe_reg_conversion_loc = 0; \ ! 400: } ! 401: ! 402: #ifdef HCX_UX ! 403: ! 404: /* to call the profiler, the address of the counter var is placed */ ! 405: /* on the stack and then passed into mcount this way */ ! 406: ! 407: #define FUNCTION_PROFILER(FILE, LABELNO) \ ! 408: fprintf (FILE, "\tpushal LP%d\n\tcallf $8,mcount\n", (LABELNO)); ! 409: ! 410: #else ! 411: ! 412: /* to call the profiler, push the variable value onto the stack */ ! 413: /* and call mcount like a regular function. */ ! 414: ! 415: #define FUNCTION_PROFILER(FILE, LABELNO) \ ! 416: fprintf (FILE, "\tpushl $LP%d\n\tcallf $8,mcount\n", (LABELNO)); ! 417: ! 418: #endif ! 419: ! 420: /* all stack handling at the end of a function is handled by the */ ! 421: /* return command. */ ! 422: ! 423: #define EXIT_IGNORE_STACK 1 ! 424: ! 425: /* ! 426: * Library Subroutine Names ! 427: */ ! 428: ! 429: /* udiv is a valid C library routine in libc.a, so we call that */ ! 430: ! 431: #define UDIVSI3_LIBCALL "*udiv" ! 432: ! 433: /* urem is a valid C library routine in libc.a, so we call that */ ! 434: /* but not so on hcx/ux */ ! 435: ! 436: #ifdef HCX_UX ! 437: #undef UMODSI3_LIBCALL ! 438: #else ! 439: #define UMODSI3_LIBCALL "*urem" ! 440: #endif ! 441: ! 442: ! 443: /* ! 444: * Addressing Modes ! 445: */ ! 446: ! 447: /* constant addresses can be treated exactly the same as normal constants */ ! 448: ! 449: #define CONSTANT_ADDRESS_P(X) \ ! 450: (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ ! 451: || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ ! 452: || GET_CODE (X) == HIGH) ! 453: ! 454: /* we can have as many as two regs in any given address */ ! 455: ! 456: #define MAX_REGS_PER_ADDRESS 2 ! 457: ! 458: /* The following is all the code for GO_IF_LEGITIMATE_ADDRESS */ ! 459: /* most of this taken directly from the vax tm file since the */ ! 460: /* tahoe and vax addressing modes are nearly identical. */ ! 461: ! 462: /* Is x an indirectable address? */ ! 463: ! 464: #define INDIRECTABLE_ADDRESS_P(X) \ ! 465: (CONSTANT_ADDRESS_P (X) \ ! 466: || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ ! 467: || (GET_CODE (X) == PLUS \ ! 468: && GET_CODE (XEXP (X, 0)) == REG \ ! 469: && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ ! 470: && CONSTANT_ADDRESS_P (XEXP (X, 1)))) ! 471: ! 472: /* If x is a non-indexed-address, go to ADDR. */ ! 473: ! 474: #define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ ! 475: { register rtx xfoob = (X); \ ! 476: if (GET_CODE (xfoob) == REG) goto ADDR; \ ! 477: if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \ ! 478: xfoob = XEXP (X, 0); \ ! 479: if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \ ! 480: goto ADDR; \ ! 481: if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ ! 482: && GET_CODE (xfoob) == REG && REGNO (xfoob) == 14) \ ! 483: goto ADDR; } ! 484: ! 485: /* Is PROD an index term in mode MODE. */ ! 486: ! 487: #define INDEX_TERM_P(PROD, MODE) \ ! 488: (GET_MODE_SIZE (MODE) == 1 \ ! 489: ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \ ! 490: : (GET_CODE (PROD) == MULT \ ! 491: && \ ! 492: (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \ ! 493: ((GET_CODE (xfoo0) == CONST_INT \ ! 494: && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \ ! 495: && GET_CODE (xfoo1) == REG \ ! 496: && REG_OK_FOR_INDEX_P (xfoo1)) \ ! 497: || \ ! 498: (GET_CODE (xfoo1) == CONST_INT \ ! 499: && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \ ! 500: && GET_CODE (xfoo0) == REG \ ! 501: && REG_OK_FOR_INDEX_P (xfoo0)))))) ! 502: ! 503: /* Is the addition to the index a reg? */ ! 504: ! 505: #define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \ ! 506: { register rtx xfooa; \ ! 507: if (GET_CODE (X) == PLUS) \ ! 508: { if (GET_CODE (XEXP (X, 0)) == REG \ ! 509: && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ ! 510: && (xfooa = XEXP (X, 1), \ ! 511: INDEX_TERM_P (xfooa, MODE))) \ ! 512: goto ADDR; \ ! 513: if (GET_CODE (XEXP (X, 1)) == REG \ ! 514: && REG_OK_FOR_BASE_P (XEXP (X, 1)) \ ! 515: && (xfooa = XEXP (X, 0), \ ! 516: INDEX_TERM_P (xfooa, MODE))) \ ! 517: goto ADDR; } } ! 518: ! 519: /* Is the rtx X a valid memory address for operand of mode MODE? */ ! 520: /* If it is, go to ADDR */ ! 521: ! 522: #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ ! 523: { register rtx xfoo, xfoo0, xfoo1; \ ! 524: GO_IF_NONINDEXED_ADDRESS (X, ADDR); \ ! 525: if (GET_CODE (X) == PLUS) \ ! 526: { xfoo = XEXP (X, 0); \ ! 527: if (INDEX_TERM_P (xfoo, MODE)) \ ! 528: { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \ ! 529: xfoo = XEXP (X, 1); \ ! 530: if (INDEX_TERM_P (xfoo, MODE)) \ ! 531: { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \ ! 532: if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \ ! 533: { if (GET_CODE (XEXP (X, 1)) == REG \ ! 534: && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ ! 535: goto ADDR; \ ! 536: GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \ ! 537: if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \ ! 538: { if (GET_CODE (XEXP (X, 0)) == REG \ ! 539: && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ ! 540: goto ADDR; \ ! 541: GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } } ! 542: ! 543: /* Register 16 can never be used for index or base */ ! 544: ! 545: #ifndef REG_OK_STRICT ! 546: #define REG_OK_FOR_INDEX_P(X) (REGNO(X) != 16) ! 547: #define REG_OK_FOR_BASE_P(X) (REGNO(X) != 16) ! 548: #else ! 549: #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) ! 550: #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) ! 551: #endif ! 552: ! 553: /* Addressing is too simple to allow optimizing here */ ! 554: ! 555: #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} ! 556: ! 557: /* Post_inc and pre_dec always adds 4 */ ! 558: ! 559: #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ ! 560: { if (GET_CODE(ADDR) == POST_INC || GET_CODE(ADDR) == PRE_DEC) \ ! 561: goto LABEL; \ ! 562: if (GET_CODE (ADDR) == PLUS) \ ! 563: { if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \ ! 564: && GET_CODE (XEXP (ADDR, 1)) == REG); \ ! 565: else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \ ! 566: && GET_CODE (XEXP (ADDR, 0)) == REG); \ ! 567: else goto LABEL; }} ! 568: ! 569: /* Double's are not legitimate as immediate operands */ ! 570: ! 571: #define LEGITIMATE_CONSTANT_P(X) \ ! 572: (GET_CODE (X) != CONST_DOUBLE) ! 573: ! 574: ! 575: /* ! 576: * Miscellaneous Parameters ! 577: */ ! 578: ! 579: /* the elements in the case jump table are all words */ ! 580: ! 581: #define CASE_VECTOR_MODE HImode ! 582: ! 583: /* each of the table elements in a case are relative to the jump address */ ! 584: ! 585: #define CASE_VECTOR_PC_RELATIVE ! 586: ! 587: /* tahoe case instructions just fall through to the next instruction */ ! 588: /* if not satisfied. It doesn't support a default action */ ! 589: ! 590: #define CASE_DROPS_THROUGH ! 591: ! 592: /* the standard answer is given here and work ok */ ! 593: ! 594: #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR ! 595: ! 596: /* in a general div case, it's easiest to use TRUNC_DIV_EXPR */ ! 597: ! 598: #define EASY_DIV_EXPR TRUNC_DIV_EXPR ! 599: ! 600: /* the standard seems to be leaving char's as signed so we left it */ ! 601: /* this way even though we think they should be unsigned! */ ! 602: ! 603: #define DEFAULT_SIGNED_CHAR 1 ! 604: ! 605: /* the most we can move without cutting down speed is 4 bytes */ ! 606: ! 607: #define MOVE_MAX 4 ! 608: ! 609: /* our int is 32 bits */ ! 610: ! 611: #define INT_TYPE_SIZE 32 ! 612: ! 613: /* byte access isn't really slower than anything else */ ! 614: ! 615: #define SLOW_BYTE_ACCESS 0 ! 616: ! 617: /* zero extension is more than one instruction so try to avoid it */ ! 618: ! 619: #define SLOW_ZERO_EXTEND ! 620: ! 621: /* any bits higher than the low 4 are ignored in the shift count */ ! 622: /* so don't bother zero extending or sign extending them */ ! 623: ! 624: #define SHIFT_COUNT_TRUNCATED 1 ! 625: ! 626: /* we don't need to officially convert from one fixed type to another */ ! 627: /* in order to use it as that type. We can just assume it's the same */ ! 628: ! 629: #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 ! 630: ! 631: /* pass chars as ints */ ! 632: ! 633: #define PROMOTE_PROTOTYPES ! 634: ! 635: /* pointers can be represented by an si mode expression */ ! 636: ! 637: #define Pmode SImode ! 638: ! 639: /* function addresses are made by specifying a byte address */ ! 640: ! 641: #define FUNCTION_MODE QImode ! 642: ! 643: /* Define this if addresses of constant functions ! 644: shouldn't be put through pseudo regs where they can be cse'd. ! 645: On the tahoe a call with a constant address is much faster than one with a ! 646: register. */ ! 647: ! 648: #define NO_FUNCTION_CSE ! 649: ! 650: /* specify the costs of various sorts of constants, ! 651: and also indicate that multiplication is cheap on this machine. */ ! 652: ! 653: #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ ! 654: case CONST_INT: \ ! 655: /* Constant zero is super cheap due to clr instruction. */ \ ! 656: if (RTX == const0_rtx) return 0; \ ! 657: if ((unsigned) INTVAL (RTX) < 077) return 1; \ ! 658: if (INTVAL (RTX) <= 127 && INTVAL (RTX) >= -128) return 2; \ ! 659: case CONST: \ ! 660: case LABEL_REF: \ ! 661: case SYMBOL_REF: \ ! 662: return 3; \ ! 663: case CONST_DOUBLE: \ ! 664: return 5; \ ! 665: case MULT: \ ! 666: total = 2; ! 667: ! 668: ! 669: /* ! 670: * Condition Code Information ! 671: */ ! 672: ! 673: /* Nonzero if the results of the previous comparison are ! 674: in the floating point condition code register. */ ! 675: ! 676: #define CC_UNCHANGED 04000 ! 677: ! 678: ! 679: #define NOTICE_UPDATE_CC(EXP, INSN) \ ! 680: { if (cc_status.flags & CC_UNCHANGED) \ ! 681: /* Happens for cvtld and a few other insns. */ \ ! 682: cc_status.flags &= ~CC_UNCHANGED; \ ! 683: else if (GET_CODE (EXP) == SET) \ ! 684: { if (GET_CODE (SET_SRC (EXP)) == CALL) \ ! 685: CC_STATUS_INIT; \ ! 686: else if (GET_CODE (SET_DEST (EXP)) != PC) \ ! 687: { cc_status.flags = 0; \ ! 688: cc_status.value1 = SET_DEST (EXP); \ ! 689: cc_status.value2 = SET_SRC (EXP); } } \ ! 690: else if (GET_CODE (EXP) == PARALLEL \ ! 691: && GET_CODE (XVECEXP (EXP, 0, 0)) == SET \ ! 692: && GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) != PC) \ ! 693: { cc_status.flags = 0; \ ! 694: cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \ ! 695: cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); } \ ! 696: /* PARALLELs whose first element sets the PC are aob, sob insns. \ ! 697: They do change the cc's. So drop through and forget the cc's. */ \ ! 698: else CC_STATUS_INIT; \ ! 699: if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \ ! 700: && cc_status.value2 \ ! 701: && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ ! 702: cc_status.value2 = 0; \ ! 703: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM \ ! 704: && cc_status.value2 \ ! 705: && GET_CODE (cc_status.value2) == MEM) \ ! 706: cc_status.value2 = 0; } ! 707: /* Actual condition, one line up, should be that value2's address ! 708: depends on value1, but that is too much of a pain. */ ! 709: ! 710: ! 711: /* ! 712: * Output of Assembler Code ! 713: */ ! 714: ! 715: /* print which tahoe version compiled this code and print a directive */ ! 716: /* to the gnu assembler to say that the following is normal assembly */ ! 717: ! 718: #ifdef HCX_UX ! 719: #define ASM_FILE_START(FILE) \ ! 720: { fprintf (FILE, "#gcc hcx 1.0\n\n"); \ ! 721: output_file_directive ((FILE), main_input_filename);} while (0) ! 722: #else ! 723: #define ASM_FILE_START(FILE) fprintf (FILE, "#gcc tahoe 1.0\n#NO_APP\n"); ! 724: #endif ! 725: ! 726: /* the instruction that turns on the APP for the gnu assembler */ ! 727: ! 728: #define ASM_APP_ON "#APP\n" ! 729: ! 730: /* the instruction that turns off the APP for the gnu assembler */ ! 731: ! 732: #define ASM_APP_OFF "#NO_APP\n" ! 733: ! 734: /* what to output before read-only data. */ ! 735: ! 736: #define TEXT_SECTION_ASM_OP ".text" ! 737: ! 738: /* what to output before writable data. */ ! 739: ! 740: #define DATA_SECTION_ASM_OP ".data" ! 741: ! 742: /* this is what we call each of the regs. notice that the FPP reg is */ ! 743: /* called "ac". This should never get used due to the way we've set */ ! 744: /* up FPP instructions in the md file. But we call it "ac" here to */ ! 745: /* fill the list. */ ! 746: ! 747: #define REGISTER_NAMES \ ! 748: {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ ! 749: "r9", "r10", "r11", "r12", "fp", "sp", "pc", "ac"} ! 750: ! 751: #ifdef HCX_UX ! 752: /* allow generation of sdb info in the assembly */ ! 753: #define SDB_DEBUGGING_INFO ! 754: #else ! 755: /* allow generation of dbx info in the assembly */ ! 756: ! 757: #define DBX_DEBUGGING_INFO ! 758: ! 759: /* our dbx doesn't support this */ ! 760: ! 761: #define DBX_NO_XREFS ! 762: ! 763: /* we don't want symbols broken up */ ! 764: ! 765: #define DBX_CONTIN_LENGTH 0 ! 766: ! 767: /* this'll really never be used, but we'll leave it at this */ ! 768: ! 769: #define DBX_CONTIN_CHAR '?' ! 770: ! 771: #endif /* HCX_UX */ ! 772: ! 773: /* registers are called the same thing in dbx anything else */ ! 774: /* This is necessary even if we generate SDB output */ ! 775: ! 776: #define DBX_REGISTER_NUMBER(REGNO) (REGNO) ! 777: ! 778: /* labels are the label followed by a colon and a newline */ ! 779: /* must be a statement, so surround it in a null loop */ ! 780: ! 781: #define ASM_OUTPUT_LABEL(FILE,NAME) \ ! 782: do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) ! 783: ! 784: /* use the .globl directive to make labels global for the linker */ ! 785: ! 786: #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ ! 787: do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) ! 788: ! 789: /* output a label by appending an underscore to it */ ! 790: ! 791: #define ASM_OUTPUT_LABELREF(FILE,NAME) \ ! 792: fprintf (FILE, "_%s", NAME) ! 793: ! 794: /* use the standard format for printing internal labels */ ! 795: ! 796: #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ ! 797: fprintf (FILE, "%s%d:\n", PREFIX, NUM) ! 798: ! 799: /* a * is used for label indirection in unix assembly */ ! 800: ! 801: #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ ! 802: sprintf (LABEL, "*%s%d", PREFIX, NUM) ! 803: ! 804: /* outputting a double is easy cause we only have one kind */ ! 805: ! 806: #ifdef HCX_UX ! 807: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ ! 808: fprintf (FILE, "\t.double 0d%.20e\n", (VALUE)) ! 809: #else ! 810: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ ! 811: { \ ! 812: union { int i[2]; double d;} temp; \ ! 813: temp.d = (VALUE); \ ! 814: if (TARGET_HEX_FLOAT) \ ! 815: fprintf ((FILE), "\t.long 0x%x,0x%x # %.20e\n", \ ! 816: temp.i[0], temp.i[1], temp.d); \ ! 817: else \ ! 818: fprintf (FILE, "\t.dfloat 0d%.20e\n", temp.d); \ ! 819: } ! 820: #endif ! 821: ! 822: /* This is how to output an assembler line defining a `float' constant. */ ! 823: ! 824: #ifdef HCX_UX ! 825: #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ ! 826: fprintf (FILE, "\t.float 0f%.20e\n", (VALUE)) ! 827: #else ! 828: #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ ! 829: { \ ! 830: union { int i; float f;} temp; \ ! 831: temp.f = (float) (VALUE); \ ! 832: if (TARGET_HEX_FLOAT) \ ! 833: fprintf ((FILE), "\t.long 0x%x # %.20e\n", \ ! 834: temp.i, temp.f); \ ! 835: else \ ! 836: fprintf (FILE, "\t.float 0f%.20e\n", temp.f); \ ! 837: } ! 838: #endif ! 839: ! 840: /* This is how to output an assembler line defining an `int' constant. */ ! 841: ! 842: #define ASM_OUTPUT_INT(FILE,VALUE) \ ! 843: ( fprintf (FILE, "\t.long "), \ ! 844: output_addr_const (FILE, (VALUE)), \ ! 845: fprintf (FILE, "\n")) ! 846: ! 847: /* Likewise for `char' and `short' constants. */ ! 848: ! 849: #define ASM_OUTPUT_SHORT(FILE,VALUE) \ ! 850: ( fprintf (FILE, "\t.word "), \ ! 851: output_addr_const (FILE, (VALUE)), \ ! 852: fprintf (FILE, "\n")) ! 853: ! 854: #define ASM_OUTPUT_CHAR(FILE,VALUE) \ ! 855: ( fprintf (FILE, "\t.byte "), \ ! 856: output_addr_const (FILE, (VALUE)), \ ! 857: fprintf (FILE, "\n")) ! 858: ! 859: #ifdef HCX_UX ! 860: /* This is how to output an assembler line for an ASCII string. */ ! 861: ! 862: #define ASM_OUTPUT_ASCII(FILE, p, size) \ ! 863: { register int i; \ ! 864: fprintf ((FILE), "\t.ascii \""); \ ! 865: for (i = 0; i < (size); i++) \ ! 866: { \ ! 867: register int c = (p)[i]; \ ! 868: if (c == '\'' || c == '\\') \ ! 869: putc ('\\', (FILE)); \ ! 870: if (c >= ' ' && c < 0177 && c != '\"') \ ! 871: putc (c, (FILE)); \ ! 872: else \ ! 873: { \ ! 874: fprintf ((FILE), "\\%03o", c); \ ! 875: } \ ! 876: } \ ! 877: fprintf ((FILE), "\"\n"); } ! 878: #endif ! 879: ! 880: /* This is how to output an assembler line for a numeric constant byte. */ ! 881: ! 882: #define ASM_OUTPUT_BYTE(FILE,VALUE) \ ! 883: fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) ! 884: ! 885: /* this is the insn to push a register onto the stack */ ! 886: ! 887: #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ ! 888: fprintf (FILE, "\tpushl %s\n", reg_names[REGNO]) ! 889: ! 890: /* this is the insn to pop a register from the stack */ ! 891: ! 892: #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ ! 893: fprintf (FILE, "\tmovl (sp)+,%s\n", reg_names[REGNO]) ! 894: ! 895: /* this is required even thought tahoe doesn't support it */ ! 896: /* cause the C code expects it to be defined */ ! 897: ! 898: #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ ! 899: fprintf (FILE, "\t.long L%d\n", VALUE) ! 900: ! 901: /* This is how to output an element of a case-vector that is relative. */ ! 902: ! 903: #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ ! 904: fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL) ! 905: ! 906: /* This is how to output an assembler line ! 907: that says to advance the location counter ! 908: to a multiple of 2**LOG bytes. */ ! 909: ! 910: #ifdef HCX_UX ! 911: #define CASE_ALIGNMENT 2 ! 912: #define ASM_OUTPUT_ALIGN(FILE,LOG) \ ! 913: if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) ! 914: #else ! 915: #define CASE_ALIGNMENT 1 ! 916: #define ASM_OUTPUT_ALIGN(FILE,LOG) \ ! 917: LOG ? fprintf (FILE, "\t.align %d\n", (LOG)) : 0 ! 918: #endif ! 919: ! 920: /* This is how to skip over some space */ ! 921: ! 922: #define ASM_OUTPUT_SKIP(FILE,SIZE) \ ! 923: fprintf (FILE, "\t.space %u\n", (SIZE)) ! 924: ! 925: /* This defines common variables across files */ ! 926: ! 927: #ifdef HCX_UX ! 928: #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! 929: ( fputs (".comm ", (FILE)), \ ! 930: assemble_name ((FILE), (NAME)), \ ! 931: fprintf ((FILE), ",%u\n", (SIZE))) ! 932: #else ! 933: #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! 934: ( fputs (".comm ", (FILE)), \ ! 935: assemble_name ((FILE), (NAME)), \ ! 936: fprintf ((FILE), ",%u\n", (ROUNDED))) ! 937: #endif ! 938: ! 939: /* This says how to output an assembler line ! 940: to define a local common symbol. */ ! 941: ! 942: #ifdef HCX_UX ! 943: #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! 944: ( fputs ("\t.bss ", (FILE)), \ ! 945: assemble_name ((FILE), (NAME)), \ ! 946: fprintf ((FILE), ",%u,4\n", (SIZE),(ROUNDED))) ! 947: #else ! 948: #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! 949: ( fputs (".lcomm ", (FILE)), \ ! 950: assemble_name ((FILE), (NAME)), \ ! 951: fprintf ((FILE), ",%u\n", (ROUNDED))) ! 952: #endif ! 953: ! 954: /* code to generate a label */ ! 955: ! 956: #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ ! 957: ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ ! 958: sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) ! 959: ! 960: /* Define the parentheses used to group arithmetic operations ! 961: in assembler code. */ ! 962: ! 963: #define ASM_OPEN_PAREN "(" ! 964: #define ASM_CLOSE_PAREN ")" ! 965: ! 966: /* Define results of standard character escape sequences. */ ! 967: ! 968: #define TARGET_BELL 007 ! 969: #define TARGET_BS 010 ! 970: #define TARGET_TAB 011 ! 971: #define TARGET_NEWLINE 012 ! 972: #define TARGET_VT 013 ! 973: #define TARGET_FF 014 ! 974: #define TARGET_CR 015 ! 975: ! 976: /* Print an instruction operand X on file FILE. ! 977: CODE is the code from the %-spec that requested printing this operand; ! 978: if `%z3' was used to print operand 3, then CODE is 'z'. ! 979: On the Vax, the only code used is `#', indicating that either ! 980: `d' or `g' should be printed, depending on whether we're using dfloat ! 981: or gfloat. */ ! 982: /* Print an operand. Some difference from the vax code, ! 983: since the tahoe can't support immediate floats and doubles. ! 984: ! 985: %@ means print the proper alignment operand for aligning after a casesi. ! 986: This depends on the assembler syntax. ! 987: This is 1 for our assembler, since .align is logarithmic. ! 988: ! 989: %s means the number given is supposed to be a shift value, but on ! 990: the tahoe it should be converted to a number that can be used as a ! 991: multiplicative constant (cause multiplication is a whole lot faster ! 992: than shifting). So make the number 2^n instead. */ ! 993: ! 994: #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ! 995: ((CODE) == '@') ! 996: ! 997: #define PRINT_OPERAND(FILE, X, CODE) \ ! 998: { if (CODE == '@') \ ! 999: putc ('0' + CASE_ALIGNMENT, FILE); \ ! 1000: else if (CODE == 's') \ ! 1001: fprintf (FILE, "$%d", 1 << INTVAL(X)); \ ! 1002: else if (GET_CODE (X) == REG) \ ! 1003: fprintf (FILE, "%s", reg_names[REGNO (X)]); \ ! 1004: else if (GET_CODE (X) == MEM) \ ! 1005: output_address (XEXP (X, 0)); \ ! 1006: else { putc ('$', FILE); output_addr_const (FILE, X); }} ! 1007: ! 1008: /* When the operand is an address, call print_operand_address to */ ! 1009: /* do the work from output-tahoe.c. */ ! 1010: ! 1011: #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ ! 1012: print_operand_address (FILE, ADDR) ! 1013: ! 1014: /* This is for G++ */ ! 1015: ! 1016: #define CRT0_DUMMIES ! 1017: #define DOT_GLOBAL_START ! 1018: #ifdef HCX_UX ! 1019: #define NO_GNU_LD /* because of COFF format */ ! 1020: #define LINK_SPEC "-L/usr/staff/lib" ! 1021: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.