|
|
1.1 root 1: /*
2: * n3/i386/igen.c
3: * C compiler intermediate file printer.
4: * Machine and assembly format dependent output routines.
5: * i386.
6: */
7:
8: #ifdef vax
9: #include "INC$LIB:cc3.h"
10: #else
11: #include "cc3.h"
12: #endif
13:
14: extern char *tempnam();
15:
16: /* Output strings which depend on assembler format. */
17: #if AS_FORMAT
18: #define SHRI ".text"
19: #define PRVI ".text"
20: #define SHRD ".text" /* unused, we think */
21: #define STRN ".text"
22: #define PRVD ".data"
23: #define BSSD ".data"
24: #define COMMFMT "\t.comm"
25: #define ALFMT ".align"
26: #define GLOBL ".globl"
27: #define BLKBFMT "\t.blkb\t0x%lx\n"
28: #define MODNAM "/\tmodule name"
29: #else
30: #define SHRI "code"
31: #define PRVI "linkage"
32: #define SHRD "pure"
33: #define STRN "strings"
34: #define PRVD "impure"
35: #define BSSD "bss"
36: #define COMMFMT ";\tcommon"
37: #define ALFMT "align"
38: #define GLOBL "public"
39: #define BLKBFMT "\tdb\t0%lxh dup(0)\n"
40: #define MODNAM "\tname"
41: #endif
42:
43: #define NSEGS 6 /* number of output segments */
44: char sfname[NSEGS][L_tmpnam]; /* per-segment tempfile names */
45: FILE *sfp[NSEGS]; /* per-segment output FILEs */
46:
47: /*
48: * How to enter or leave a segment.
49: */
50: char *seg_enter[] = {
51: SHRI, PRVI, SHRD, STRN, PRVD, BSSD
52: };
53:
54: #if 0
55: char *seg_leave[] = {
56: NULL, NULL, NULL, NULL, NULL, NULL
57: };
58: #endif
59:
60: /*
61: * Initialize the disassembler phase.
62: */
63: cc3init()
64: {
65: if (notvariant(VPSTR))
66: seg_enter[SSTRN] = PRVD;
67: sfp[SCODE] = ofp; /* write CODE directly to ofp */
68: }
69:
70: /*
71: * Terminate the disassembler.
72: * Output for each segment goes to a separate file;
73: * this copies the segments to the actual output file
74: * and cleans up.
75: */
76: cc3close()
77: {
78: register int i, c;
79: register FILE *fp;
80: int prev;
81:
82: ofp = sfp[SCODE];
83: prev = SCODE; /* previous segment written */
84: for (i = 1; i < NSEGS; i++) {
85: if ((fp = sfp[i]) == NULL)
86: continue; /* unused */
87: fprintf(ofp, "\t.align\t4\n");
88: if (strcmp(seg_enter[prev], seg_enter[i]) != 0)
89: fprintf(ofp, "\n\t%s\n", seg_enter[i]);
90: prev = i;
91: rewind(fp);
92: while ((c = getc(fp)) != EOF)
93: putc(c, ofp); /* copy to ofp */
94: fclose(fp);
95: unlink(sfname[i]);
96: }
97: }
98:
99: /*
100: * Process AUTOS items.
101: * The opcode byte has been read.
102: * Read in operands used by the target machine
103: * and print them out in a nice way.
104: */
105: genautos()
106: {
107: register ival_t numauto;
108: register int regmask;
109: register int reg;
110: register int sepchar;
111:
112: numauto = iget();
113: regmask = iget();
114: fprintf(ofp, "\tautos\t%ld", (long)numauto);
115: sepchar = '\t';
116: for (reg = FRREG; reg <= NFBREG; ++reg) {
117: if ((regmask&01) != 0) {
118: fprintf(ofp, "%c%s", sepchar, regnames[reg]);
119: sepchar = ' ';
120: }
121: regmask >>= 1;
122: }
123: fprintf(ofp, "\n");
124: }
125:
126: /*
127: * Output a double value.
128: */
129: gendval(dp)
130: register dval_t dp;
131: {
132: register int i;
133:
134: for (i = 0; i < sizeof(dval_t); i += 1)
135: fprintf(ofp, "%02x", dp[i] & 0377);
136: }
137:
138: /*
139: * Generate a machine dependent leaf node.
140: */
141: genmdl(op)
142: {
143: cbotch("bad mdl: %d", op);
144: }
145:
146: /*
147: * Generate a machine dependent operator node.
148: */
149: genmdo(op)
150: {
151: cbotch("bad mdo: %d", op);
152: }
153:
154: /*
155: * Generat a .comm record.
156: * The operands must be read.
157: */
158: gencomm()
159: {
160: sget(id, NCSYMB);
161: if (isvariant(VASM))
162: fprintf(ofp, COMMFMT);
163: else
164: fprintf(ofp, "common");
165: fprintf(ofp, "\t%s,\t%ld\n", id, (long)zget());
166: }
167:
168: /*
169: * Generate an assembly operator involving a name.
170: */
171: genname(op, id)
172: char *id;
173: {
174: switch (op) {
175: case FNAME:
176: fprintf(ofp, "%s\tfile name %s\n", CMTSTR, id);
177: break;
178: case MNAME:
179: fprintf(ofp, "%s %s\n", MODNAM, id);
180: #if AS_FORMAT
181: fprintf(ofp, "\t.alignoff\n");
182: fprintf(ofp, "\t.intelorder\n");
183: #endif
184: break;
185: case GLABEL:
186: fprintf(ofp, "\t%s %s\n%s:\n", GLOBL, id, id);
187: break;
188: case SLABEL:
189: fprintf(ofp, "%s:\n", id);
190: break;
191: #ifdef UREFER
192: case UREFER:
193: fprintf(ofp, "%s\tundefined reference %s\n", CMTSTR, id);
194: break;
195: #endif
196: default:
197: cbotch("genname: bad op: %d", op);
198: }
199: }
200:
201: /*
202: * Generate an assembly operator involving an integer value.
203: */
204: genival(op, i) int op; register long i;
205: {
206: register char *s;
207:
208: switch (op) {
209: case LINE:
210: fprintf(ofp, "%s\tline number %ld\n", CMTSTR, i);
211: break;
212: case BLOCK:
213: fprintf(ofp, BLKBFMT, i);
214: break;
215: case ALIGN:
216: fprintf(ofp, "\t%s\t%d\n", ALFMT, i);
217: break;
218: case ENTER:
219: #if 1
220: /*
221: * Write each segment to a different FILE.
222: * This allows the assember to assemble the .s to the
223: * same bits as those produced by the compiler.
224: */
225: if (dotseg == -1) /* first ENTER */
226: fprintf(ofp, "\n\t%s\n", seg_enter[SCODE]);
227: if (i != dotseg) { /* new segment */
228: dotseg = i;
229: if (sfp[i] == NULL) { /* previously unused segment */
230: s = tempnam(NULL, "cc3");
231: strcpy(sfname[i], s);
232: if ((sfp[i] = fopen(s, "w+")) == NULL)
233: cfatal("cannot open temp file %s", s);
234: free(s);
235: }
236: ofp = sfp[i];
237: }
238: break;
239: #else
240: /* Old code, just print appropriate entering text. */
241: #if 0
242: /* Nothing special required when leaving segments. */
243: if (dotseg >= 0 && (s=seg_leave[dotseg]) != NULL)
244: fprintf(ofp, "\n\t%s\n\n", s);
245: #endif
246: dotseg = i;
247: if (dotseg >= 0 && (s=seg_enter[dotseg]) != NULL)
248: fprintf(ofp, "\n\t%s\n\n", s);
249: break;
250: #endif
251: case LLABEL:
252: fprintf(ofp, ".L%ld:\n", i);
253: break;
254: default:
255: cbotch("genival: bad op: %d", op);
256: }
257: }
258:
259: /* end of n3/i386/igen.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.