|
|
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:
1.1.1.2 root 131: #define STRICT_ALIGNMENT 1
1.1 root 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:
1.1.1.2 root 170: /* lots of regs aren't guaranteed to return from a call. The FPP reg */
1.1 root 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:
1.1.1.2 root 267: /* 'a' as a constraint in the md file means the FFP_REG class */
1.1 root 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 */
1.1.1.2 root 457: /* tahoe and vax addressing modes are nearly identical. */
1.1 root 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:
1.1.1.2 root 580: /* each of the table elements in a case are relative to the jump address */
1.1 root 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:
1.1.1.3 ! root 650: #define CONST_COSTS(RTX,CODE,OUTER_CODE) \
1.1 root 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:
1.1.1.2 root 801: /* outputting a double is easy cause we only have one kind */
1.1 root 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.