|
|
1.1 root 1: /*
2: * n2/i386/outcoh.c
3: * The routines in this file make up
4: * a writer for the Coherent style l.out object
5: * file. During code assembly all the bits get
6: * written to a temporary file. At the very end the
7: * bits get copied back to the final object file.
8: * This uses the newest compiler base (the one
9: * that does "readonly" and has the segment names rearranged).
10: * i386.
11: */
12:
13: #ifdef vax
14: #include "INC$LIB:cc2.h"
15: #include "INC$LIB:canon.h"
16: #include "INC$LIB:lout.h"
17: #else
18: #include "cc2.h"
19: #include "canon.h"
20: #include "l.out.h"
21: #endif
22:
23: #define NTXT 256 /* Text buffer size */
24: #define NREL 256 /* Relocation buffer size */
25:
26: /*
27: * Scratch file.
28: */
29: #define TTYPE 07 /* Type */
30: #define TTYPE 07 /* Type */
31: #define TPCR 010 /* PC rel flag, ored in */
32: #define TSYM 020 /* Symbol based flag, ored in */
33: #define T8087 0340 /* 8087 flags */
34:
35: #define TEND 00 /* End marker */
36: #define TENTER 01 /* Enter new area */
37: #define TBYTE 02 /* Byte data */
38: #define TWORD 03 /* Word data */
39: #define TCODE 04 /* Code segment base */
40: #define TDATA 05 /* Data segment base */
41: #define TBASE 06 /* External segment base */
42:
43: #define TWT 0040 /* M:_WT */
44: #define TWST 0100 /* M:_WST */
45: #define TWES 0140 /* M:_WES */
46: #define TWCS 0200 /* M:_WCS */
47: #define TWSS 0240 /* M:_WSS */
48: #define TWDS 0300 /* M:_WDS */
49:
50: struct ldheader ldh; /* Header buffer */
51: long crseek; /* Current relocation seek address */
52: ADDRESS txtla; /* Load address */
53: char txt[NTXT]; /* Text buffer */
54: char rel[NREL]; /* Relocation buffer */
55: char *txtp; /* Text pointer */
56: char *relp; /* Relocation pointer */
57:
58: /*
59: * Convert a C compiler segment into
60: * an "l.out" segment. This is no longer a
61: * one to one mapping.
62: */
63: char segindex[] = {
64: L_SHRI, /* SCODE */
65: L_SHRI, /* SLINK */
66: L_SHRD, /* SPURE */
67: 0, /* SSTRN (Patched) */
68: L_PRVD, /* SDATA */
69: L_BSSD /* SBSS */
70: };
71:
72: /*
73: * Output a segment switch.
74: */
75: outseg(s)
76: {
77: bput(TENTER);
78: bput(s);
79: }
80:
81: /*
82: * Output an absolute byte.
83: */
84: outab(b)
85: {
86: bput(TBYTE);
87: bput(b);
88: ++dot;
89: }
90:
91: /*
92: * Output an absolute word.
93: */
94: outaw(w)
95: {
96: bput(TWORD);
97: iput((ival_t)w);
98: dot += 2;
99: }
100:
101: /*
102: * Output a full byte.
103: */
104: outxb(sp, b, pcrf)
105: register SYM *sp;
106: {
107: register int opcode;
108:
109: opcode = TBYTE;
110: if (sp != NULL)
111: opcode |= TSYM;
112: if (pcrf)
113: opcode |= TPCR;
114: bput(opcode);
115: bput(b);
116: if (sp != NULL)
117: pput(sp);
118: ++dot;
119: }
120:
121: /*
122: * Output a full word.
123: */
124: outxw(sp, w, pcrf)
125: register SYM *sp;
126: {
127: register int opcode;
128:
129: opcode = TWORD;
130: if (sp != NULL)
131: opcode |= TSYM;
132: if (pcrf)
133: opcode |= TPCR;
134: bput(opcode);
135: iput((ival_t)w);
136: if (sp != NULL)
137: pput(sp);
138: dot += 2;
139: }
140:
141: /*
142: * Output a 1 word object containing
143: * the base address of the current code
144: * segment.
145: */
146: outcb()
147: {
148: bput(TCODE);
149: dot += 2;
150: }
151:
152: /*
153: * Output a 1 word object containing
154: * the base address of the current data
155: * segment.
156: */
157: outdb()
158: {
159: bput(TDATA);
160: dot += 2;
161: }
162:
163: /*
164: * Output a 1 word object containing
165: * the base address of the external symbol
166: * pointed to by 'sp'.
167: */
168: outsb(sp)
169: SYM *sp;
170: {
171: bput(TBASE);
172: pput(sp);
173: dot += 2;
174: }
175:
176: /*
177: * Copy a dlabel record from ifp to nowhere.
178: */
179: outdlab(i, n)
180: int i; /* Indentation */
181: register int n; /* Class initially */
182: {
183: /* Get line number */
184: iget();
185:
186: /* Get value */
187: if (n < DC_AUTO)
188: ;
189: else if (n < DC_MOS)
190: iget();
191: else {
192: bget(); /* Width */
193: bget(); /* Offset */
194: iget(); /* Value */
195: }
196:
197: /* Get name */
198: sget(id, NCSYMB);
199:
200: /* Get type */
201: for (;;) {
202: n = bget();
203: if (n < DC_SEX) {
204: if (n < DX_MEMBS)
205: iget();
206: if (n == DX_MEMBS) {
207: ++i;
208: n = iget();
209: for ( ; n > 0; n-=1) {
210: outdlab(i, bget());
211: }
212: --i;
213: break;
214: } else if (n == DX_NAME) {
215: iget();
216: sget(id, NCSYMB);
217: break;
218: } else if (n < DT_STRUCT)
219: break;
220: } else
221: cbotch("unrecognized type byte: %d", n);
222: }
223:
224: /* Done */
225: }
226:
227: /*
228: * Forget a debug line record.
229: */
230: outdlin(op)
231: {
232: }
233:
234: /*
235: * Forget a debug relocation record.
236: */
237: outdloc(n)
238: {
239: }
240:
241: /*
242: * Initialize the code writer.
243: */
244: outinit()
245: {
246: txtp = &txt[0];
247: relp = &rel[0];
248: }
249:
250: /*
251: * Finish up.
252: */
253: outdone()
254: {
255: if (notvariant(VASM))
256: bput(TEND);
257: }
258:
259: /*
260: * Copy back.
261: * Figure out the sizes and final values
262: * of everything. Copy the code from the scratch
263: * file back to the output file.
264: */
265: copycode()
266: {
267: register SYM *sp;
268: register SEG *segp;
269: register int op;
270: register int data;
271: register ADDRESS mseek;
272: register long dseek;
273: register int nd;
274: register int nr;
275: register int index;
276: register ADDRESS segsize;
277: register ADDRESS auxsize;
278: register ADDRESS reldot;
279: register int refnum;
280: register int i;
281: register int rop;
282: struct ldsym lds;
283:
284: /*
285: * Make sure that the "segindex"
286: * table is set up correctly for the string
287: * mapping, based on the VPSTR flags.
288: */
289: if (isvariant(VPSTR))
290: segindex[SSTRN] = L_SHRD;
291: else
292: segindex[SSTRN] = L_PRVD;
293: /*
294: * Sweep through the segment table and
295: * assign the memory and disc seek addresses to each
296: * entry. Two sections (SLINK and SSTRN) are done in
297: * a magic way, because they live in another segment.
298: */
299: mseek = 0;
300: index = 0;
301: dseek = sizeof(ldh);
302: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp) {
303: if (segp!=&seg[SLINK] && segp!=&seg[SSTRN]) {
304: segp->s_mseek = mseek;
305: segsize = rup(segp->s_dot);
306: mseek += segsize;
307: if (segp != &seg[SBSS]) {
308: segp->s_dseek = dseek;
309: dseek += segsize;
310: }
311: if (segp == &seg[SCODE]) {
312: seg[SLINK].s_mseek = mseek;
313: auxsize = rup(seg[SLINK].s_dot);
314: mseek += auxsize;
315: seg[SLINK].s_dseek = dseek;
316: dseek += auxsize;
317: segsize += auxsize;
318: }
319: if (isvariant(VPSTR) && segp==&seg[SPURE]
320: || notvariant(VPSTR) && segp==&seg[SDATA]) {
321: seg[SSTRN].s_mseek = mseek;
322: auxsize = rup(seg[SSTRN].s_dot);
323: mseek += auxsize;
324: seg[SSTRN].s_dseek = dseek;
325: dseek += auxsize;
326: segsize += auxsize;
327: }
328: ldh.l_ssize[segindex[index]] = segsize;
329: }
330: ++index;
331: }
332: /*
333: * Seek to the start of the symbol table and
334: * write out all of the global symbols. All symbols get
335: * relocated to their final values here. Reference numbers
336: * are assigned to every symbol.
337: */
338: fseek(ofp, dseek, 0);
339: ldh.l_ssize[L_SYM] = 0;
340: refnum = 0;
341: for (i=0; i<NSHASH; ++i) {
342: sp = hash2[i];
343: while (sp != NULL) {
344: if ((sp->s_flag&S_DEF) != 0)
345: sp->s_value += seg[sp->s_seg].s_mseek;
346: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) {
347: sp->s_ref = refnum++;
348: ldscopy(lds.ls_id, sp->s_id);
349: lds.ls_type = L_REF;
350: if ((sp->s_flag&S_DEF) != 0)
351: lds.ls_type = segindex[sp->s_seg];
352: lds.ls_type |= L_GLOBAL;
353: lds.ls_addr = sp->s_value;
354: canint(lds.ls_type);
355: canvaddr(lds.ls_addr);
356: owrite((char *) &lds, sizeof(lds));
357: ldh.l_ssize[L_SYM] += sizeof(lds);
358: }
359: sp = sp->s_fp;
360: }
361: }
362: /*
363: * Copy out code.
364: */
365: crseek = ftell(ofp);
366: ldh.l_ssize[L_REL] = 0;
367: for (segp=&seg[SCODE]; segp<=&seg[SBSS]; ++segp)
368: segp->s_dot = 0;
369: dotseg = SCODE;
370: dot = 0;
371: while ((op = bget()) != TEND) {
372: if (op==TCODE || op==TDATA || op==TBASE)
373: cbotch("large item");
374: if ((op&T8087) != 0)
375: cbotch("8087 item");
376: if (op == TENTER) {
377: notenuf();
378: seg[dotseg].s_dot = dot;
379: dotseg = bget();
380: dot = seg[dotseg].s_dot;
381: continue;
382: }
383: if ((op&TTYPE) == TBYTE) {
384: nd = 1;
385: data = bget();
386: } else {
387: nd = 2;
388: data = iget();
389: }
390: if ((op&TPCR) != 0)
391: data -= dot+nd;
392: /*
393: * Absolute.
394: */
395: if ((op&(TSYM|TPCR)) == 0) {
396: enuf(nd, 0);
397: *txtp++ = data;
398: if (nd != 1)
399: *txtp++ = data>>8;
400: dot += nd;
401: continue;
402: }
403: /*
404: * Not symbol based.
405: * Must be absolute and PC rel.
406: */
407: reldot = dot + seg[dotseg].s_mseek;
408: if ((op&TSYM) == 0) {
409: enuf(nd, 3);
410: rop = LR_BYTE|L_ABS|LR_PCR;
411: *txtp++ = data;
412: if (nd != 1) {
413: rop = LR_WORD|L_ABS|LR_PCR;
414: *txtp++ = data>>8;
415: }
416: *relp++ = rop;
417: *relp++ = reldot;
418: *relp++ = reldot>>8;
419: dot += nd;
420: continue;
421: }
422: /*
423: * Symbol based.
424: * Might be PC rel.
425: */
426: nr = 5;
427: sp = pget();
428: if ((sp->s_flag&S_DEF) != 0) {
429: nr = 3;
430: data += sp->s_value;
431: }
432: enuf(nd, nr);
433: rop = LR_BYTE;
434: *txtp++ = data;
435: if (nd != 1) {
436: rop = LR_WORD;
437: *txtp++ = data>>8;
438: }
439: if ((op&TPCR) != 0)
440: rop |= LR_PCR;
441: if (nr == 3)
442: rop |= segindex[sp->s_seg];
443: else
444: rop |= L_SYM;
445: *relp++ = rop;
446: *relp++ = reldot;
447: *relp++ = reldot>>8;
448: if (nr == 5) {
449: *relp++ = sp->s_ref;
450: *relp++ = sp->s_ref>>8;
451: }
452: dot += nd;
453: }
454: /*
455: * Flush buffers.
456: * Write out the l.out header, since we
457: * now know the size of the relocation section.
458: */
459: notenuf();
460: ldh.l_magic = L_MAGIC;
461: canint(ldh.l_magic);
462: ldh.l_flag = 0;
463: canint(ldh.l_flag);
464: ldh.l_machine = M_8086;
465: canint(ldh.l_machine);
466: ldh.l_entry = 0;
467: canvaddr(ldh.l_entry);
468: for (i=L_SHRI; i<=L_REL; ++i)
469: cansize(ldh.l_ssize[i]);
470: fseek(ofp, (long)0, 0);
471: owrite((char *) &ldh, sizeof(ldh));
472: }
473:
474: /*
475: * Copy a NUL terminated name into
476: * a loader symbol. Pad the symbol out with
477: * 0 bytes.
478: */
479: ldscopy(p1, p2)
480: register char *p1;
481: register char *p2;
482: {
483: register int n;
484:
485: n = NCPLN;
486: while (*p2!=0 && n!=0) {
487: *p1++ = *p2++;
488: --n;
489: }
490: while (n != 0) {
491: *p1++ = 0;
492: --n;
493: }
494: }
495:
496: /*
497: * This routine checks to see if
498: * there is enough room in the text and relocation
499: * buffers to hold 'nt' bytes of text and 'nr' bytes of
500: * relocation.
501: */
502: enuf(nt, nr)
503: {
504: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL])
505: notenuf();
506: if (txtp == txt)
507: txtla = dot;
508: }
509:
510: /*
511: * Flush the text and relocation buffers. Look
512: * at the segment table to figure out the exact location
513: * of the data in the file, and compute the correct seek
514: * address in the image by adding the base address of
515: * the text record "txtla" to that base.
516: */
517: notenuf()
518: {
519: register int n;
520:
521: if ((n=txtp-txt) != 0) {
522: fseek(ofp, txtla+seg[dotseg].s_dseek, 0);
523: owrite(txt, n);
524: if ((n=relp-rel) != 0) {
525: fseek(ofp, crseek, 0);
526: owrite(rel, n);
527: crseek += n;
528: ldh.l_ssize[L_REL] += n;
529: relp = rel;
530: }
531: }
532: txtp = txt;
533: }
534:
535: /*
536: * Write a block of bytes to the output file,
537: * looking at the return status and checking for any
538: * write errors.
539: */
540: owrite(p, n)
541: char *p;
542: {
543: if (fwrite(p, sizeof(char), n, ofp) != n)
544: cfatal("output write error");
545: }
546:
547: /*
548: * Round up a size to the next
549: * even boundry.
550: */
551: rup(a)
552: {
553: return ((a+01)&~01);
554: }
555:
556: /* end of n2/i386/outcoh.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.