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