|
|
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" ! 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 ! 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 guarenteed 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 gereral registers can be used as a base reg */ ! 260: ! 261: #define BASE_REG_CLASS GENERAL_REGS ! 262: ! 263: /* only gereral registers can be used to index */ ! 264: ! 265: #define INDEX_REG_CLASS GENERAL_REGS ! 266: ! 267: /* 'a' as a contraint 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: /* libarary 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) CONSTANT_P (X) ! 450: ! 451: /* we can have as many as two regs in any given address */ ! 452: ! 453: #define MAX_REGS_PER_ADDRESS 2 ! 454: ! 455: /* The following is all the code for GO_IF_LEGITIMATE_ADDRESS */ ! 456: /* most of this taken directly from the vax tm file since the */ ! 457: /* tahoe and vax addressing modes are nearly identicle. */ ! 458: ! 459: /* Is x an indirectable address? */ ! 460: ! 461: #define INDIRECTABLE_ADDRESS_P(X) \ ! 462: (CONSTANT_ADDRESS_P (X) \ ! 463: || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ ! 464: || (GET_CODE (X) == PLUS \ ! 465: && GET_CODE (XEXP (X, 0)) == REG \ ! 466: && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ ! 467: && CONSTANT_ADDRESS_P (XEXP (X, 1)))) ! 468: ! 469: /* If x is a non-indexed-address, go to ADDR. */ ! 470: ! 471: #define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ ! 472: { register rtx xfoob = (X); \ ! 473: if (GET_CODE (xfoob) == REG) goto ADDR; \ ! 474: if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \ ! 475: xfoob = XEXP (X, 0); \ ! 476: if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \ ! 477: goto ADDR; \ ! 478: if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ ! 479: && GET_CODE (xfoob) == REG && REGNO (xfoob) == 14) \ ! 480: goto ADDR; } ! 481: ! 482: /* Is PROD an index term in mode MODE. */ ! 483: ! 484: #define INDEX_TERM_P(PROD, MODE) \ ! 485: (GET_MODE_SIZE (MODE) == 1 \ ! 486: ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \ ! 487: : (GET_CODE (PROD) == MULT \ ! 488: && \ ! 489: (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \ ! 490: ((GET_CODE (xfoo0) == CONST_INT \ ! 491: && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \ ! 492: && GET_CODE (xfoo1) == REG \ ! 493: && REG_OK_FOR_INDEX_P (xfoo1)) \ ! 494: || \ ! 495: (GET_CODE (xfoo1) == CONST_INT \ ! 496: && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \ ! 497: && GET_CODE (xfoo0) == REG \ ! 498: && REG_OK_FOR_INDEX_P (xfoo0)))))) ! 499: ! 500: /* Is the addition to the index a reg? */ ! 501: ! 502: #define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \ ! 503: { register rtx xfooa; \ ! 504: if (GET_CODE (X) == PLUS) \ ! 505: { if (GET_CODE (XEXP (X, 0)) == REG \ ! 506: && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ ! 507: && (xfooa = XEXP (X, 1), \ ! 508: INDEX_TERM_P (xfooa, MODE))) \ ! 509: goto ADDR; \ ! 510: if (GET_CODE (XEXP (X, 1)) == REG \ ! 511: && REG_OK_FOR_BASE_P (XEXP (X, 1)) \ ! 512: && (xfooa = XEXP (X, 0), \ ! 513: INDEX_TERM_P (xfooa, MODE))) \ ! 514: goto ADDR; } } ! 515: ! 516: /* Is the rtx X a valid memoy address for operand of mode MODE? */ ! 517: /* If it is, go to ADDR */ ! 518: ! 519: #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ ! 520: { register rtx xfoo, xfoo0, xfoo1; \ ! 521: GO_IF_NONINDEXED_ADDRESS (X, ADDR); \ ! 522: if (GET_CODE (X) == PLUS) \ ! 523: { xfoo = XEXP (X, 0); \ ! 524: if (INDEX_TERM_P (xfoo, MODE)) \ ! 525: { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \ ! 526: xfoo = XEXP (X, 1); \ ! 527: if (INDEX_TERM_P (xfoo, MODE)) \ ! 528: { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \ ! 529: if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \ ! 530: { if (GET_CODE (XEXP (X, 1)) == REG \ ! 531: && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ ! 532: goto ADDR; \ ! 533: GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \ ! 534: if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \ ! 535: { if (GET_CODE (XEXP (X, 0)) == REG \ ! 536: && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ ! 537: goto ADDR; \ ! 538: GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } } ! 539: ! 540: /* Register 16 can never be used for index or base */ ! 541: ! 542: #ifndef REG_OK_STRICT ! 543: #define REG_OK_FOR_INDEX_P(X) (REGNO(X) != 16) ! 544: #define REG_OK_FOR_BASE_P(X) (REGNO(X) != 16) ! 545: #else ! 546: #define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) ! 547: #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) ! 548: #endif ! 549: ! 550: /* Addressing is too simple to allow optimizing here */ ! 551: ! 552: #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} ! 553: ! 554: /* Post_inc and pre_dec always adds 4 */ ! 555: ! 556: #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ ! 557: { if (GET_CODE(ADDR) == POST_INC || GET_CODE(ADDR) == PRE_DEC) \ ! 558: goto LABEL; \ ! 559: if (GET_CODE (ADDR) == PLUS) \ ! 560: { if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \ ! 561: && GET_CODE (XEXP (ADDR, 1)) == REG); \ ! 562: else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \ ! 563: && GET_CODE (XEXP (ADDR, 0)) == REG); \ ! 564: else goto LABEL; }} ! 565: ! 566: /* Double's are not legitimate as immediate operands */ ! 567: ! 568: #define LEGITIMATE_CONSTANT_P(X) \ ! 569: (GET_CODE (X) != CONST_DOUBLE) ! 570: ! 571: ! 572: /* ! 573: * Miscellaneous Parameters ! 574: */ ! 575: ! 576: /* the elements in the case jump table are all words */ ! 577: ! 578: #define CASE_VECTOR_MODE HImode ! 579: ! 580: /* each of the table elements in a case are relative to the jump addess */ ! 581: ! 582: #define CASE_VECTOR_PC_RELATIVE ! 583: ! 584: /* tahoe case instructions just fall through to the next instruction */ ! 585: /* if not satisfied. It doesn't support a default action */ ! 586: ! 587: #define CASE_DROPS_THROUGH ! 588: ! 589: /* the standard answer is given here and work ok */ ! 590: ! 591: #define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR ! 592: ! 593: /* in a general div case, it's easiest to use TRUNC_DIV_EXPR */ ! 594: ! 595: #define EASY_DIV_EXPR TRUNC_DIV_EXPR ! 596: ! 597: /* the standard seems to be leaving char's as signed so we left it */ ! 598: /* this way even though we think they should be unsigned! */ ! 599: ! 600: #define DEFAULT_SIGNED_CHAR 1 ! 601: ! 602: /* the most we can move without cutting down speed is 4 bytes */ ! 603: ! 604: #define MOVE_MAX 4 ! 605: ! 606: /* our int is 32 bits */ ! 607: ! 608: #define INT_TYPE_SIZE 32 ! 609: ! 610: /* byte access isn't really slower than anything else */ ! 611: ! 612: #define SLOW_BYTE_ACCESS 0 ! 613: ! 614: /* zero extension is more than one instruction so try to avoid it */ ! 615: ! 616: #define SLOW_ZERO_EXTEND ! 617: ! 618: /* any bits higher than the low 4 are ignored in the shift count */ ! 619: /* so don't bother zero extending or sign extending them */ ! 620: ! 621: #define SHIFT_COUNT_TRUNCATED ! 622: ! 623: /* we don't need to officially convert from one fixed type to another */ ! 624: /* in order to use it as that type. We can just assume it's the same */ ! 625: ! 626: #define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 ! 627: ! 628: /* pass chars as ints */ ! 629: ! 630: #define PROMOTE_PROTOTYPES ! 631: ! 632: /* pointers can be represented by an si mode expression */ ! 633: ! 634: #define Pmode SImode ! 635: ! 636: /* function addresses are made by specifying a byte address */ ! 637: ! 638: #define FUNCTION_MODE QImode ! 639: ! 640: /* Define this if addresses of constant functions ! 641: shouldn't be put through pseudo regs where they can be cse'd. ! 642: On the tahoe a call with a constant address is much faster than one with a ! 643: register. */ ! 644: ! 645: #define NO_FUNCTION_CSE ! 646: ! 647: /* specify the costs of various sorts of constants, ! 648: and also indicate that multiplication is cheap on this machine. */ ! 649: ! 650: #define CONST_COSTS(RTX,CODE) \ ! 651: case CONST_INT: \ ! 652: /* Constant zero is super cheap due to clr instruction. */ \ ! 653: if (RTX == const0_rtx) return 0; \ ! 654: if ((unsigned) INTVAL (RTX) < 077) return 1; \ ! 655: if (INTVAL (RTX) <= 127 && INTVAL (RTX) >= -128) return 2; \ ! 656: case CONST: \ ! 657: case LABEL_REF: \ ! 658: case SYMBOL_REF: \ ! 659: return 3; \ ! 660: case CONST_DOUBLE: \ ! 661: return 5; \ ! 662: case MULT: \ ! 663: total = 2; ! 664: ! 665: ! 666: /* ! 667: * Condition Code Information ! 668: */ ! 669: ! 670: /* Nonzero if the results of the previous comparison are ! 671: in the floating point condition code register. */ ! 672: ! 673: #define CC_UNCHANGED 04000 ! 674: ! 675: ! 676: #define NOTICE_UPDATE_CC(EXP, INSN) \ ! 677: { if (cc_status.flags & CC_UNCHANGED) \ ! 678: /* Happens for cvtld and a few other insns. */ \ ! 679: cc_status.flags &= ~CC_UNCHANGED; \ ! 680: else if (GET_CODE (EXP) == SET) \ ! 681: { if (GET_CODE (SET_SRC (EXP)) == CALL) \ ! 682: CC_STATUS_INIT; \ ! 683: else if (GET_CODE (SET_DEST (EXP)) != PC) \ ! 684: { cc_status.flags = 0; \ ! 685: cc_status.value1 = SET_DEST (EXP); \ ! 686: cc_status.value2 = SET_SRC (EXP); } } \ ! 687: else if (GET_CODE (EXP) == PARALLEL \ ! 688: && GET_CODE (XVECEXP (EXP, 0, 0)) == SET \ ! 689: && GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) != PC) \ ! 690: { cc_status.flags = 0; \ ! 691: cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \ ! 692: cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); } \ ! 693: /* PARALLELs whose first element sets the PC are aob, sob insns. \ ! 694: They do change the cc's. So drop through and forget the cc's. */ \ ! 695: else CC_STATUS_INIT; \ ! 696: if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \ ! 697: && cc_status.value2 \ ! 698: && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ ! 699: cc_status.value2 = 0; \ ! 700: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM \ ! 701: && cc_status.value2 \ ! 702: && GET_CODE (cc_status.value2) == MEM) \ ! 703: cc_status.value2 = 0; } ! 704: /* Actual condition, one line up, should be that value2's address ! 705: depends on value1, but that is too much of a pain. */ ! 706: ! 707: ! 708: /* ! 709: * Output of Assembler Code ! 710: */ ! 711: ! 712: /* print which tahoe version compiled this code and print a directive */ ! 713: /* to the gnu assembler to say that the following is normal assembly */ ! 714: ! 715: #ifdef HCX_UX ! 716: #define ASM_FILE_START(FILE) \ ! 717: { fprintf (FILE, "#gcc hcx 1.0\n\n"); \ ! 718: output_file_directive ((FILE), main_input_filename);} while (0) ! 719: #else ! 720: #define ASM_FILE_START(FILE) fprintf (FILE, "#gcc tahoe 1.0\n#NO_APP\n"); ! 721: #endif ! 722: ! 723: /* the instruction that turns on the APP for the gnu assembler */ ! 724: ! 725: #define ASM_APP_ON "#APP\n" ! 726: ! 727: /* the instruction that turns off the APP for the gnu assembler */ ! 728: ! 729: #define ASM_APP_OFF "#NO_APP\n" ! 730: ! 731: /* what to output before read-only data. */ ! 732: ! 733: #define TEXT_SECTION_ASM_OP ".text" ! 734: ! 735: /* what to output before writable data. */ ! 736: ! 737: #define DATA_SECTION_ASM_OP ".data" ! 738: ! 739: /* this is what we call each of the regs. notice that the FPP reg is */ ! 740: /* called "ac". This should never get used due to the way we've set */ ! 741: /* up FPP instructions in the md file. But we call it "ac" here to */ ! 742: /* fill the list. */ ! 743: ! 744: #define REGISTER_NAMES \ ! 745: {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ ! 746: "r9", "r10", "r11", "r12", "fp", "sp", "pc", "ac"} ! 747: ! 748: #ifdef HCX_UX ! 749: /* allow generation of sdb info in the assembly */ ! 750: #define SDB_DEBUGGING_INFO ! 751: #else ! 752: /* allow generation of dbx info in the assembly */ ! 753: ! 754: #define DBX_DEBUGGING_INFO ! 755: ! 756: /* our dbx doesn't support this */ ! 757: ! 758: #define DBX_NO_XREFS ! 759: ! 760: /* we don't want symbols broken up */ ! 761: ! 762: #define DBX_CONTIN_LENGTH 0 ! 763: ! 764: /* this'll really never be used, but we'll leave it at this */ ! 765: ! 766: #define DBX_CONTIN_CHAR '?' ! 767: ! 768: #endif /* HCX_UX */ ! 769: ! 770: /* registers are called the same thing in dbx anything else */ ! 771: /* This is necessary even if we generate SDB output */ ! 772: ! 773: #define DBX_REGISTER_NUMBER(REGNO) (REGNO) ! 774: ! 775: /* labels are the label followed by a colon and a newline */ ! 776: /* must be a statement, so surround it in a null loop */ ! 777: ! 778: #define ASM_OUTPUT_LABEL(FILE,NAME) \ ! 779: do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) ! 780: ! 781: /* use the .globl directive to make labels global for the linker */ ! 782: ! 783: #define ASM_GLOBALIZE_LABEL(FILE,NAME) \ ! 784: do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) ! 785: ! 786: /* output a label by appending an underscore to it */ ! 787: ! 788: #define ASM_OUTPUT_LABELREF(FILE,NAME) \ ! 789: fprintf (FILE, "_%s", NAME) ! 790: ! 791: /* use the standard format for printing internal labels */ ! 792: ! 793: #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ ! 794: fprintf (FILE, "%s%d:\n", PREFIX, NUM) ! 795: ! 796: /* a * is used for label indirection in unix assembly */ ! 797: ! 798: #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ ! 799: sprintf (LABEL, "*%s%d", PREFIX, NUM) ! 800: ! 801: /* outputing a double is easy cause we only have one kind */ ! 802: ! 803: #ifdef HCX_UX ! 804: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ ! 805: fprintf (FILE, "\t.double 0d%.20e\n", (VALUE)) ! 806: #else ! 807: #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ ! 808: { \ ! 809: union { int i[2]; double d;} temp; \ ! 810: temp.d = (VALUE); \ ! 811: if (TARGET_HEX_FLOAT) \ ! 812: fprintf ((FILE), "\t.long 0x%x,0x%x # %.20e\n", \ ! 813: temp.i[0], temp.i[1], temp.d); \ ! 814: else \ ! 815: fprintf (FILE, "\t.dfloat 0d%.20e\n", temp.d); \ ! 816: } ! 817: #endif ! 818: ! 819: /* This is how to output an assembler line defining a `float' constant. */ ! 820: ! 821: #ifdef HCX_UX ! 822: #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ ! 823: fprintf (FILE, "\t.float 0f%.20e\n", (VALUE)) ! 824: #else ! 825: #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ ! 826: { \ ! 827: union { int i; float f;} temp; \ ! 828: temp.f = (float) (VALUE); \ ! 829: if (TARGET_HEX_FLOAT) \ ! 830: fprintf ((FILE), "\t.long 0x%x # %.20e\n", \ ! 831: temp.i, temp.f); \ ! 832: else \ ! 833: fprintf (FILE, "\t.float 0f%.20e\n", temp.f); \ ! 834: } ! 835: #endif ! 836: ! 837: /* This is how to output an assembler line defining an `int' constant. */ ! 838: ! 839: #define ASM_OUTPUT_INT(FILE,VALUE) \ ! 840: ( fprintf (FILE, "\t.long "), \ ! 841: output_addr_const (FILE, (VALUE)), \ ! 842: fprintf (FILE, "\n")) ! 843: ! 844: /* Likewise for `char' and `short' constants. */ ! 845: ! 846: #define ASM_OUTPUT_SHORT(FILE,VALUE) \ ! 847: ( fprintf (FILE, "\t.word "), \ ! 848: output_addr_const (FILE, (VALUE)), \ ! 849: fprintf (FILE, "\n")) ! 850: ! 851: #define ASM_OUTPUT_CHAR(FILE,VALUE) \ ! 852: ( fprintf (FILE, "\t.byte "), \ ! 853: output_addr_const (FILE, (VALUE)), \ ! 854: fprintf (FILE, "\n")) ! 855: ! 856: #ifdef HCX_UX ! 857: /* This is how to output an assembler line for an ASCII string. */ ! 858: ! 859: #define ASM_OUTPUT_ASCII(FILE, p, size) \ ! 860: { register int i; \ ! 861: fprintf ((FILE), "\t.ascii \""); \ ! 862: for (i = 0; i < (size); i++) \ ! 863: { \ ! 864: register int c = (p)[i]; \ ! 865: if (c == '\'' || c == '\\') \ ! 866: putc ('\\', (FILE)); \ ! 867: if (c >= ' ' && c < 0177 && c != '\"') \ ! 868: putc (c, (FILE)); \ ! 869: else \ ! 870: { \ ! 871: fprintf ((FILE), "\\%03o", c); \ ! 872: } \ ! 873: } \ ! 874: fprintf ((FILE), "\"\n"); } ! 875: #endif ! 876: ! 877: /* This is how to output an assembler line for a numeric constant byte. */ ! 878: ! 879: #define ASM_OUTPUT_BYTE(FILE,VALUE) \ ! 880: fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) ! 881: ! 882: /* this is the insn to push a register onto the stack */ ! 883: ! 884: #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ ! 885: fprintf (FILE, "\tpushl %s\n", reg_names[REGNO]) ! 886: ! 887: /* this is the insn to pop a register from the stack */ ! 888: ! 889: #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ ! 890: fprintf (FILE, "\tmovl (sp)+,%s\n", reg_names[REGNO]) ! 891: ! 892: /* this is required even thought tahoe doesn't support it */ ! 893: /* cause the C code expects it to be defined */ ! 894: ! 895: #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ ! 896: fprintf (FILE, "\t.long L%d\n", VALUE) ! 897: ! 898: /* This is how to output an element of a case-vector that is relative. */ ! 899: ! 900: #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ ! 901: fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL) ! 902: ! 903: /* This is how to output an assembler line ! 904: that says to advance the location counter ! 905: to a multiple of 2**LOG bytes. */ ! 906: ! 907: #ifdef HCX_UX ! 908: #define CASE_ALIGNMENT 2 ! 909: #define ASM_OUTPUT_ALIGN(FILE,LOG) \ ! 910: if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) ! 911: #else ! 912: #define CASE_ALIGNMENT 1 ! 913: #define ASM_OUTPUT_ALIGN(FILE,LOG) \ ! 914: LOG ? fprintf (FILE, "\t.align %d\n", (LOG)) : 0 ! 915: #endif ! 916: ! 917: /* This is how to skip over some space */ ! 918: ! 919: #define ASM_OUTPUT_SKIP(FILE,SIZE) \ ! 920: fprintf (FILE, "\t.space %u\n", (SIZE)) ! 921: ! 922: /* This defines common variables across files */ ! 923: ! 924: #ifdef HCX_UX ! 925: #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! 926: ( fputs (".comm ", (FILE)), \ ! 927: assemble_name ((FILE), (NAME)), \ ! 928: fprintf ((FILE), ",%u\n", (SIZE))) ! 929: #else ! 930: #define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ ! 931: ( fputs (".comm ", (FILE)), \ ! 932: assemble_name ((FILE), (NAME)), \ ! 933: fprintf ((FILE), ",%u\n", (ROUNDED))) ! 934: #endif ! 935: ! 936: /* This says how to output an assembler line ! 937: to define a local common symbol. */ ! 938: ! 939: #ifdef HCX_UX ! 940: #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! 941: ( fputs ("\t.bss ", (FILE)), \ ! 942: assemble_name ((FILE), (NAME)), \ ! 943: fprintf ((FILE), ",%u,4\n", (SIZE),(ROUNDED))) ! 944: #else ! 945: #define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ ! 946: ( fputs (".lcomm ", (FILE)), \ ! 947: assemble_name ((FILE), (NAME)), \ ! 948: fprintf ((FILE), ",%u\n", (ROUNDED))) ! 949: #endif ! 950: ! 951: /* code to generate a label */ ! 952: ! 953: #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ ! 954: ( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ ! 955: sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) ! 956: ! 957: /* Define the parentheses used to group arithmetic operations ! 958: in assembler code. */ ! 959: ! 960: #define ASM_OPEN_PAREN "(" ! 961: #define ASM_CLOSE_PAREN ")" ! 962: ! 963: /* Define results of standard character escape sequences. */ ! 964: ! 965: #define TARGET_BELL 007 ! 966: #define TARGET_BS 010 ! 967: #define TARGET_TAB 011 ! 968: #define TARGET_NEWLINE 012 ! 969: #define TARGET_VT 013 ! 970: #define TARGET_FF 014 ! 971: #define TARGET_CR 015 ! 972: ! 973: /* Print an instruction operand X on file FILE. ! 974: CODE is the code from the %-spec that requested printing this operand; ! 975: if `%z3' was used to print operand 3, then CODE is 'z'. ! 976: On the Vax, the only code used is `#', indicating that either ! 977: `d' or `g' should be printed, depending on whether we're using dfloat ! 978: or gfloat. */ ! 979: /* Print an operand. Some difference from the vax code, ! 980: since the tahoe can't support immediate floats and doubles. ! 981: ! 982: %@ means print the proper alignment operand for aligning after a casesi. ! 983: This depends on the assembler syntax. ! 984: This is 1 for our assembler, since .align is logarithmic. ! 985: ! 986: %s means the number given is supposed to be a shift value, but on ! 987: the tahoe it should be converted to a number that can be used as a ! 988: multiplicative constant (cause multiplication is a whole lot faster ! 989: than shifting). So make the number 2^n instead. */ ! 990: ! 991: #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ! 992: ((CODE) == '@') ! 993: ! 994: #define PRINT_OPERAND(FILE, X, CODE) \ ! 995: { if (CODE == '@') \ ! 996: putc ('0' + CASE_ALIGNMENT, FILE); \ ! 997: else if (CODE == 's') \ ! 998: fprintf (FILE, "$%d", 1 << INTVAL(X)); \ ! 999: else if (GET_CODE (X) == REG) \ ! 1000: fprintf (FILE, "%s", reg_names[REGNO (X)]); \ ! 1001: else if (GET_CODE (X) == MEM) \ ! 1002: output_address (XEXP (X, 0)); \ ! 1003: else { putc ('$', FILE); output_addr_const (FILE, X); }} ! 1004: ! 1005: /* When the operand is an address, call print_operand_address to */ ! 1006: /* do the work from output-tahoe.c. */ ! 1007: ! 1008: #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ ! 1009: print_operand_address (FILE, ADDR) ! 1010: ! 1011: /* This is for G++ */ ! 1012: ! 1013: #define CRT0_DUMMIES ! 1014: #define DOT_GLOBAL_START ! 1015: #ifdef HCX_UX ! 1016: #define NO_GNU_LD /* because of COFF format */ ! 1017: #define LINK_SPEC "-L/usr/staff/lib" ! 1018: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.