|
|
1.1 root 1: /*
2: * The routines in this file print addresses, generate function
3: * prologue and epilogue sequences,
4: * compile switches and perform other non-tree-like functions.
5: * Both SMALL and LARGE model iAPX-86.
6: */
7: #ifdef vax
8: #include "INC$LIB:cc1.h"
9: #else
10: #include "cc1.h"
11: #endif
12:
13: /*
14: * These machine dependent variables hold values
15: * that are used by the machine dependent parts
16: * of register and/or temporary storage allocation.
17: * They are set up by routines in this file.
18: */
19: int maxauto; /* Max autos in this function */
20: int maxtemp; /* Max temps in this function */
21: int curtemp; /* Current temp */
22: PREGSET regbusy; /* Busy flags */
23:
24: /*
25: * This table, indexed by register code,
26: * yields the correct addressing mode for the
27: * register. This is either stashed in an AFIELD or
28: * written out to the intermediate file.
29: */
30: static short ramode[] = {
31: A_RAX, A_RDX, A_RBX, A_RCX,
32: A_RSI, A_RDI, A_RSP, A_RBP,
33: 0,
34: A_RES, A_RCS, A_RSS, A_RDS,
35: 0, 0,
36: 0, 0,
37: 0, 0, 0, 0,
38: 0, 0, 0, 0,
39: A_RAL, A_RBL, A_RCL, A_RDL,
40: A_RAH, A_RBH, A_RCH, A_RDH
41: };
42:
43: /*
44: * Machine-dependent coder initialization.
45: * The i8086 version zeros patcache[] entries which are
46: * inconsistent with specified machine-dependent variants.
47: * This lets the coder decide when the compiler is executed
48: * whether to use certain code tables entries.
49: * Code tables using 80186 instructions include P80186 pattern flag.
50: * Code tables using 80287 instructions include P80287 pattern flag.
51: * Code tables using 8087 instructions should include P8087 pattern flag,
52: * but this flag is currently unimplemented in the tables;
53: * the tables are instead conditionalized for NDP or no NDP when tabgen'ed.
54: */
55: coderinit()
56: {
57: extern int patcsize;
58: register int i;
59: register PATFLAG *pfp;
60: register PATFLAG pflag;
61:
62: for (pfp=patcache, i=0; i < patcsize; pfp++, i++) {
63: if (((pflag = *pfp) & MDPFLAGS) != 0)
64: *pfp = ((notvariant(V80287) && ((pflag&P80287)!=0))
65: || (notvariant(V80186) && ((pflag&P80186)!=0)))
66: ? 0 : (pflag & ~MDPFLAGS);
67: }
68: }
69:
70: /*
71: * Function prolog.
72: * Clear out max. values of autos
73: * and temps.
74: */
75: doprolog()
76: {
77: blkflab = 0;
78: maxauto = 0;
79: maxtemp = 0;
80: }
81:
82: /*
83: * This routine gets called just before
84: * the EPILOG item is put out. It puts out a
85: * single AUTOS item; this item tells CC2 how much
86: * auto space should be reserved.
87: * The second ival_t of the AUTOS record (the register
88: * mask) is not used by CC2.
89: */
90: doepilog()
91: {
92: bput(AUTOS);
93: iput(maxtemp);
94: iput(0);
95: }
96:
97: /*
98: * Read in and treasure up a new
99: * automatic (and register) variable allocation
100: * item. The CC1 phase will toss out a single AUTOS
101: * item, just before the EPILOG, to tell CC2 how many
102: * bytes of automatic storage should be reserved.
103: * CC0 tosses one of these for each auto or register bound so that
104: * allocated space is not clobbered by temps during auto initialization.
105: */
106: doautos()
107: {
108: maxauto = iget();
109: regbusy = iget();
110: }
111:
112: /*
113: * Unconditional jump.
114: */
115: genubr(n)
116: {
117: genl(ZJMP, n);
118: }
119:
120: /*
121: * Conditional jump.
122: */
123: gencbr(c, n)
124: {
125: genl(optab[c-MIOBASE][0], n);
126: }
127:
128: /*
129: * Generate code for switches.
130: * Look for special cases, etc. and
131: * generate the best type of switch
132: * logic.
133: * The switch value is in AX.
134: */
135: genswitch(def, n)
136: {
137: register ival_t l, r, u;
138: register int i, lab0, lab1;
139: register int adjust;
140: register char *opp;
141:
142: /*
143: * If "n" is small pretend the
144: * user said:
145: * if (ax == case0)
146: * goto caselabel0;
147: * if (ax == case1)
148: * goto caselabel1;
149: * ...
150: */
151: if (n < 3) {
152: for (i=0; i<n; ++i) {
153: if ((l = cases[i].c_val) == 0)
154: genrr(ZOR, A_RAX, A_RAX);
155: else
156: genri(ZCMP, A_RAX, l);
157: gencbr(EQ, cases[i].c_lab);
158: }
159: genubr(def);
160: return;
161: }
162: /*
163: * Try for a direct jump table
164: * if it seems reasonable to do so.
165: */
166: l = cases[0].c_val;
167: u = cases[n-1].c_val;
168: r = u-l;
169: if (r>0 && r<=3*n) {
170: if ((adjust=l) != 0) {
171: opp = &optab[SUB-MIOBASE][0];
172: if (adjust < 0) {
173: opp = &optab[ADD-MIOBASE][0];
174: adjust = -adjust;
175: }
176: if (adjust == 1)
177: genr(opp[1], A_RAX);
178: else
179: genri(opp[0], A_RAX, adjust);
180: }
181: genri(ZCMP, A_RAX, r);
182: gencbr(UGT, def);
183: genri(ZSAL, A_RAX, 1);
184: genrr(ZMOV, A_RBX, A_RAX);
185: lab0 = newlab();
186: genone(ZIJMP, A_LID|A_CS|A_XBX, lab0);
187: genlab(lab0);
188: for (i=0; l<=u; ++l) {
189: lab0 = def;
190: if (l == cases[i].c_val)
191: lab0 = cases[i++].c_lab;
192: genl(ZLPTR, lab0);
193: }
194: return;
195: }
196: /*
197: * Table search.
198: */
199: lab0 = newlab();
200: gentwo(ZMOV, A_RBX, A_OFFS|A_LID|A_IMM, -2, lab0);
201: genri(ZMOV, A_RCX, n);
202: lab1 = newlab();
203: genlab(lab1);
204: genr(ZINC, A_RBX);
205: genr(ZINC, A_RBX);
206: gentwo(ZCMP, A_RAX, A_CS|A_XBX);
207: genl(ZLOOPNE, lab1);
208: gencbr(NE, def);
209: genone(ZIJMP, A_OFFS|A_CS|A_XBX, 2*n);
210: genlab(lab0);
211: for (i=0; i<n; ++i)
212: genone(ZWORD, A_OFFS|A_DIR, cases[i].c_val);
213: for (i=0; i<n; ++i)
214: genl(ZLPTR, cases[i].c_lab);
215: }
216:
217: /*
218: * Output an address.
219: * "tp" is a pointer to a TREE.
220: * The "nsef" flag is true if no side effects are desired;
221: * it can be set from the code tables
222: * and is used to supress escape bytes on "LEA" instructions.
223: * The "pfx" array holds "npfx" address prefix bytes.
224: * There is some strangeness here.
225: * In memory a is LO and a+2 is HI;
226: * this is not the same for constants.
227: */
228: genadr(tp, nsef, npfx, pfx)
229: register TREE *tp;
230: unsigned char pfx[];
231: {
232: register int op;
233: register int bias;
234: register int memf;
235: register int byte;
236: register int reg;
237: register ival_t ival;
238: int mode;
239: int offs;
240: lval_t loffs;
241: int lidn;
242: SYM *gidp;
243:
244: static char basebias[] = {
245: 0, 0, /* S8, U8, */
246: 1, 1, /* S16, U16, */
247: 2, 2, /* S32, U32, */
248: 2, 4, /* F32, F64, */
249: 0, /* BLK, */
250: 0, 1, /* FLD8, FLD16, */
251: 2, 2, /* LPTR, LPTRB, */
252: 1, 1 /* SPTR, SPTRB */
253: };
254:
255: while ((op=tp->t_op) == LEAF)
256: tp = tp->t_lp;
257: /*
258: * The "HI" and "LO" options,
259: * when applied to a register node, must
260: * arrange to call the "hihalf" and
261: * "lohalf" macros.
262: */
263: if (op==REG && (reg=tp->t_reg)!=FPAC) {
264: while (npfx--) {
265: if (pfx[npfx] == M_LO)
266: reg = lohalf(reg);
267: else
268: reg = hihalf(reg);
269: }
270: iput(ramode[reg]);
271: return;
272: }
273: /*
274: * For constants and memory locations,
275: * the "HI" and "LO" macros dial the
276: * selected byte or word out of the operand.
277: * Watch out for the "_fpac_" register,
278: * which is actually 64 bits of memory.
279: */
280: offs = 0;
281: if (npfx) {
282: memf = 0;
283: if (op!=ICON && op!=LCON && op!=DCON)
284: ++memf;
285: if (op == REG)
286: bias = 4;
287: else
288: bias = basebias[tp->t_type];
289: while (npfx--) {
290: byte = pfx[npfx];
291: if (memf && bias == 2) {
292: if (byte == M_HI)
293: offs += 2;
294: } else if (byte == M_LO)
295: offs += bias;
296: bias >>= 1;
297: }
298: }
299: /*
300: * This "REG" is the floating point
301: * pseudo register, which is actually a memory
302: * array, 4 words long, called "_fpac_".
303: */
304: if (op == REG) {
305: iput(A_OFFS|A_GID|A_DIR);
306: iput(offs);
307: nput("_fpac");
308: return;
309: }
310: /*
311: * Constant nodes are used as immediate
312: * operands of instructions. Pull the appropriate
313: * 16 bit chunk, and write it out as an immediate
314: * operand.
315: */
316: if (op == DCON) {
317: ival = tp->t_dval[7-offs] & 0377;
318: ival |= tp->t_dval[6-offs] << 8;
319: iput(A_OFFS|A_IMM);
320: iput(ival);
321: return;
322: }
323: if (op == LCON) {
324: ival = lower(tp->t_lval);
325: if (offs == 0)
326: ival = upper(tp->t_lval);
327: iput(A_OFFS|A_IMM);
328: iput(ival);
329: return;
330: }
331: if (op == ICON) {
332: ival = tp->t_ival;
333: iput(A_OFFS|A_IMM);
334: iput(ival);
335: return;
336: }
337: /*
338: * Collect address.
339: * Turn the "f" argument on in the call
340: * to "gencoll" if this is a "lea", so that it
341: * won't generate immediate mode addressing
342: * when it shouldn't.
343: */
344: mode = A_DIR;
345: loffs = offs;
346: if (gencoll(tp, &mode, &loffs, &lidn, &gidp, 0, nsef) == 0)
347: cbotch("collect");
348: /*
349: * No prefix byte on an immediate or on
350: * a "lea" (which is indicated by the "nsef" flag
351: * being set by the macro in the table.
352: */
353: if ((mode&A_AMOD)==A_IMM || nsef!=0)
354: mode &= ~A_PREFX;
355: offs = loffs;
356: if (offs == 0)
357: iput(mode);
358: else {
359: iput(mode|A_OFFS);
360: iput(offs);
361: }
362: if ((mode&A_LID) != 0)
363: iput(lidn);
364: else if ((mode&A_GID) != 0)
365: sput(gidp->s_id);
366: }
367:
368: /*
369: * Walk down an address tree, building up
370: * the addressing mode, the offset and the symbol base
371: * for a general addressing item. Store the data back through
372: * the argument pointers. The caller must set the initial mode
373: * to "A_DIR" and the offset to 0.
374: */
375: gencoll(tp, modep, offsp, lidnp, gidpp, s, f)
376: TREE *tp;
377: int *modep;
378: lval_t *offsp;
379: int *lidnp;
380: SYM **gidpp;
381: {
382: register int op;
383: register lval_t offs;
384: register int seg;
385:
386: while ((op=tp->t_op) == LEAF)
387: tp = tp->t_lp;
388: switch (op) {
389:
390: case ADDR:
391: if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, f) == 0)
392: return (0);
393: if (f == 0) {
394: *modep &= ~A_AMOD;
395: *modep |= A_IMM;
396: }
397: break;
398:
399: case STAR:
400: if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, 1) == 0)
401: return (0);
402: break;
403:
404: case ADD:
405: case SUB:
406: if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, f) == 0)
407: return (0);
408: if (op == SUB)
409: s = !s;
410: if (gencoll(tp->t_rp, modep, offsp, lidnp, gidpp, s, f) == 0)
411: return (0);
412: break;
413:
414: case ICON:
415: case LCON:
416: offs = grabnval(tp);
417: if (s != 0)
418: offs = -offs;
419: *offsp += offs;
420: break;
421:
422: case LID:
423: if ((*modep&(A_GID|A_LID))!=0 || s!=0)
424: return (0);
425: *modep |= A_LID;
426: *lidnp = tp->t_label;
427: goto lidgid;
428:
429: case GID:
430: if ((*modep&(A_GID|A_LID))!=0 || s!=0)
431: return (0);
432: *modep |= A_GID;
433: *gidpp = tp->t_sp;
434: lidgid:
435: *offsp += tp->t_offs;
436: /*
437: * The parser may have told the code generator
438: * where this symbol is located.
439: * Apply a CS: escape if the output writer
440: * will put it in the CODE or module_CODE segment.
441: * This only affects links and MUL/DIM immediate words.
442: */
443: seg = tp->t_seg;
444: if (seg==SCODE || seg==SLINK
445: || (isvariant(VLARGE)
446: && ((seg==SPURE && notvariant(VRAM))
447: || (seg==SSTRN && isvariant(VROM))))) {
448: *modep &= ~A_PREFX;
449: *modep |= A_CS;
450: }
451: break;
452:
453: case REG:
454: if ((*modep&A_AMOD)!=A_DIR || s!=0)
455: return (0);
456: switch (tp->t_reg) {
457: case DSBX:
458: case BX:
459: *modep = A_XBX;
460: break;
461: case ESBX:
462: *modep = A_ES|A_XBX;
463: break;
464: case SSBP:
465: case BP:
466: *modep = A_XBP;
467: break;
468: case DSSI:
469: case SI:
470: *modep = A_XSI;
471: break;
472: case ESSI:
473: *modep = A_ES|A_XSI;
474: break;
475: case DSDI:
476: case DI:
477: *modep = A_XDI;
478: break;
479: case ESDI:
480: *modep = A_ES|A_XDI;
481: break;
482: default:
483: return (0);
484: }
485: break;
486:
487: default:
488: return (0);
489: }
490: return (1);
491: }
492:
493: /*
494: * Output an instruction that takes
495: * a single register as an operand.
496: */
497: genr(op, r)
498: {
499: bput(CODE);
500: bput(op);
501: iput(r);
502: }
503:
504: /*
505: * Output an instruction that takes
506: * two registers as operands.
507: */
508: genrr(op, r1, r2)
509: {
510: bput(CODE);
511: bput(op);
512: iput(r1);
513: iput(r2);
514: }
515:
516: /*
517: * Output an instruction that takes
518: * a register and an immediate constant value.
519: */
520: genri(op, r, i)
521: {
522: bput(CODE);
523: bput(op);
524: iput(r);
525: iput(A_OFFS|A_IMM);
526: iput(i);
527: }
528:
529: /*
530: * Output an instruction with a single
531: * local label parameter.
532: */
533: genl(op, l)
534: {
535: bput(CODE);
536: bput(op);
537: iput(A_LID|A_DIR);
538: iput(l);
539: }
540:
541: /*
542: * Output an instruction that takes
543: * a single global identifier as an operand.
544: */
545: geng(op, g)
546: char *g;
547: {
548: bput(CODE);
549: bput(op);
550: iput(A_GID|A_DIR);
551: sput(g);
552: }
553:
554: /*
555: * Output an instruction that takes an immediate constant value.
556: */
557: geni(op, i)
558: {
559: bput(CODE);
560: bput(op);
561: iput(A_OFFS|A_IMM);
562: iput(i);
563: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.