|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)put.c 5.1 (Berkeley) 6/18/85";
9: #endif not lint
10:
11: #include "whoami.h"
12: #include "opcode.h"
13: #include "0.h"
14: #include "objfmt.h"
15: #ifdef PC
16: # include "pc.h"
17: # include "align.h"
18: #else
19: short *obufp = obuf;
20: #endif
21:
22: /*
23: * If DEBUG is defined, include the table
24: * of the printing opcode names.
25: */
26: #ifdef DEBUG
27: #include "OPnames.h"
28: #endif
29:
30: #ifdef OBJ
31: /*
32: * Put is responsible for the interpreter equivalent of code
33: * generation. Since the interpreter is specifically designed
34: * for Pascal, little work is required here.
35: */
36: /*VARARGS*/
37: put(a)
38: {
39: register int *p, i;
40: register char *cp;
41: register short *sp;
42: register long *lp;
43: int n, subop, suboppr, op, oldlc;
44: char *string;
45: static int casewrd;
46:
47: /*
48: * It would be nice to do some more
49: * optimizations here. The work
50: * done to collapse offsets in lval
51: * should be done here, the IFEQ etc
52: * relational operators could be used
53: * etc.
54: */
55: oldlc = (int) lc; /* its either this or change put to return a char * */
56: if ( !CGENNING )
57: /*
58: * code disabled - do nothing
59: */
60: return (oldlc);
61: p = &a;
62: n = *p++;
63: suboppr = subop = (*p >> 8) & 0377;
64: op = *p & 0377;
65: string = 0;
66: #ifdef DEBUG
67: if ((cp = otext[op]) == NIL) {
68: printf("op= %o\n", op);
69: panic("put");
70: }
71: #endif
72: switch (op) {
73: case O_ABORT:
74: cp = "*";
75: break;
76: case O_AS:
77: switch(p[1]) {
78: case 0:
79: break;
80: case 2:
81: op = O_AS2;
82: n = 1;
83: break;
84: case 4:
85: op = O_AS4;
86: n = 1;
87: break;
88: case 8:
89: op = O_AS8;
90: n = 1;
91: break;
92: default:
93: goto pack;
94: }
95: # ifdef DEBUG
96: cp = otext[op];
97: # endif DEBUG
98: break;
99: case O_FOR1U:
100: case O_FOR2U:
101: case O_FOR4U:
102: case O_FOR1D:
103: case O_FOR2D:
104: case O_FOR4D:
105: /* relative addressing */
106: p[1] -= ( unsigned ) lc + sizeof(short);
107: /* try to pack the jump */
108: if (p[1] <= 127 && p[1] >= -128) {
109: suboppr = subop = p[1];
110: p++;
111: n--;
112: } else {
113: /* have to allow for extra displacement */
114: p[1] -= sizeof(short);
115: }
116: break;
117: case O_CONG:
118: case O_LVCON:
119: case O_CON:
120: case O_LINO:
121: case O_NEW:
122: case O_DISPOSE:
123: case O_DFDISP:
124: case O_IND:
125: case O_OFF:
126: case O_INX2:
127: case O_INX4:
128: case O_CARD:
129: case O_ADDT:
130: case O_SUBT:
131: case O_MULT:
132: case O_IN:
133: case O_CASE1OP:
134: case O_CASE2OP:
135: case O_CASE4OP:
136: case O_FRTN:
137: case O_WRITES:
138: case O_WRITEC:
139: case O_WRITEF:
140: case O_MAX:
141: case O_MIN:
142: case O_ARGV:
143: case O_CTTOT:
144: case O_INCT:
145: case O_RANG2:
146: case O_RSNG2:
147: case O_RANG42:
148: case O_RSNG42:
149: case O_SUCC2:
150: case O_SUCC24:
151: case O_PRED2:
152: case O_PRED24:
153: if (p[1] == 0)
154: break;
155: case O_CON2:
156: case O_CON24:
157: pack:
158: if (p[1] <= 127 && p[1] >= -128) {
159: suboppr = subop = p[1];
160: p++;
161: n--;
162: if (op == O_CON2) {
163: op = O_CON1;
164: # ifdef DEBUG
165: cp = otext[O_CON1];
166: # endif DEBUG
167: }
168: if (op == O_CON24) {
169: op = O_CON14;
170: # ifdef DEBUG
171: cp = otext[O_CON14];
172: # endif DEBUG
173: }
174: }
175: break;
176: case O_CON8:
177: {
178: short *sp = (short *) (&p[1]);
179:
180: #ifdef DEBUG
181: if ( opt( 'k' ) )
182: printf ( "%5d\tCON8\t%22.14e\n" ,
183: lc - HEADER_BYTES ,
184: * ( ( double * ) &p[1] ) );
185: #endif
186: # ifdef DEC11
187: word(op);
188: # else
189: word(op << 8);
190: # endif DEC11
191: for ( i = 1 ; i <= 4 ; i ++ )
192: word ( *sp ++ );
193: return ( oldlc );
194: }
195: default:
196: if (op >= O_REL2 && op <= O_REL84) {
197: if ((i = (subop >> INDX) * 5 ) >= 30)
198: i -= 30;
199: else
200: i += 2;
201: #ifdef DEBUG
202: string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i];
203: #endif
204: suboppr = 0;
205: }
206: break;
207: case O_IF:
208: case O_TRA:
209: /*****
210: codeline = 0;
211: *****/
212: /* relative addressing */
213: p[1] -= ( unsigned ) lc + sizeof(short);
214: break;
215: case O_CONC:
216: #ifdef DEBUG
217: (string = "'x'")[1] = p[1];
218: #endif
219: suboppr = 0;
220: op = O_CON1;
221: # ifdef DEBUG
222: cp = otext[O_CON1];
223: # endif DEBUG
224: subop = p[1];
225: goto around;
226: case O_CONC4:
227: #ifdef DEBUG
228: (string = "'x'")[1] = p[1];
229: #endif
230: suboppr = 0;
231: op = O_CON14;
232: subop = p[1];
233: goto around;
234: case O_CON1:
235: case O_CON14:
236: suboppr = subop = p[1];
237: around:
238: n--;
239: break;
240: case O_CASEBEG:
241: casewrd = 0;
242: return (oldlc);
243: case O_CASEEND:
244: if ((unsigned) lc & 1) {
245: lc--;
246: word(casewrd);
247: }
248: return (oldlc);
249: case O_CASE1:
250: #ifdef DEBUG
251: if (opt('k'))
252: printf("%5d\tCASE1\t%d\n"
253: , lc - HEADER_BYTES, p[1]);
254: #endif
255: /*
256: * this to build a byte size case table
257: * saving bytes across calls in casewrd
258: * so they can be put out by word()
259: */
260: lc++;
261: if ((unsigned) lc & 1)
262: # ifdef DEC11
263: casewrd = p[1] & 0377;
264: # else
265: casewrd = (p[1] & 0377) << 8;
266: # endif DEC11
267: else {
268: lc -= 2;
269: # ifdef DEC11
270: word(((p[1] & 0377) << 8) | casewrd);
271: # else
272: word((p[1] & 0377) | casewrd);
273: # endif DEC11
274: }
275: return (oldlc);
276: case O_CASE2:
277: #ifdef DEBUG
278: if (opt('k'))
279: printf("%5d\tCASE2\t%d\n"
280: , lc - HEADER_BYTES , p[1]);
281: #endif
282: word(p[1]);
283: return (oldlc);
284: case O_PUSH:
285: lp = (long *)&p[1];
286: if (*lp == 0)
287: return (oldlc);
288: /* and fall through */
289: case O_RANG4:
290: case O_RANG24:
291: case O_RSNG4:
292: case O_RSNG24:
293: case O_SUCC4:
294: case O_PRED4:
295: /* sub opcode optimization */
296: lp = (long *)&p[1];
297: if (*lp < 128 && *lp >= -128 && *lp != 0) {
298: suboppr = subop = *lp;
299: p += (sizeof(long) / sizeof(int));
300: n--;
301: }
302: goto longgen;
303: case O_TRA4:
304: case O_CALL:
305: case O_FSAV:
306: case O_GOTO:
307: case O_NAM:
308: case O_READE:
309: /* absolute long addressing */
310: lp = (long *)&p[1];
311: *lp -= HEADER_BYTES;
312: goto longgen;
313: case O_RV1:
314: case O_RV14:
315: case O_RV2:
316: case O_RV24:
317: case O_RV4:
318: case O_RV8:
319: case O_RV:
320: case O_LV:
321: /*
322: * positive offsets represent arguments
323: * and must use "ap" display entry rather
324: * than the "fp" entry
325: */
326: if (p[1] >= 0) {
327: subop++;
328: suboppr++;
329: }
330: # ifdef PDP11
331: break;
332: # else
333: /*
334: * offsets out of range of word addressing
335: * must use long offset opcodes
336: */
337: if (p[1] < SHORTADDR && p[1] >= -SHORTADDR)
338: break;
339: else {
340: op += O_LRV - O_RV;
341: # ifdef DEBUG
342: cp = otext[op];
343: # endif DEBUG
344: }
345: /* and fall through */
346: # endif PDP11
347: case O_BEG:
348: case O_NODUMP:
349: case O_CON4:
350: case O_CASE4:
351: longgen:
352: n = (n << 1) - 1;
353: if ( op == O_LRV ) {
354: n--;
355: # if defined(ADDR32) && !defined(DEC11)
356: p[n / 2] <<= 16;
357: # endif
358: }
359: #ifdef DEBUG
360: if (opt('k')) {
361: printf("%5d\t%s", lc - HEADER_BYTES, cp+1);
362: if (suboppr)
363: printf(":%d", suboppr);
364: for ( i = 2, lp = (long *)&p[1]; i < n
365: ; i += sizeof ( long )/sizeof ( short ) )
366: printf( "\t%D " , *lp ++ );
367: if (i == n) {
368: sp = (short *)lp;
369: printf( "\t%d ", *sp );
370: }
371: pchr ( '\n' );
372: }
373: #endif
374: if ( op != O_CASE4 )
375: # ifdef DEC11
376: word((op & 0377) | subop << 8);
377: # else
378: word(op << 8 | (subop & 0377));
379: # endif DEC11
380: for ( i = 1, sp = (short *)&p[1]; i < n; i++)
381: word ( *sp ++ );
382: return ( oldlc );
383: }
384: #ifdef DEBUG
385: if (opt('k')) {
386: printf("%5d\t%s", lc - HEADER_BYTES, cp+1);
387: if (suboppr)
388: printf(":%d", suboppr);
389: if (string)
390: printf("\t%s",string);
391: if (n > 1)
392: pchr('\t');
393: for (i=1; i<n; i++)
394: printf("%d ", p[i]);
395: pchr('\n');
396: }
397: #endif
398: if (op != NIL)
399: # ifdef DEC11
400: word((op & 0377) | subop << 8);
401: # else
402: word(op << 8 | (subop & 0377));
403: # endif DEC11
404: for (i=1; i<n; i++)
405: word(p[i]);
406: return (oldlc);
407: }
408: #endif OBJ
409:
410: /*
411: * listnames outputs a list of enumerated type names which
412: * can then be selected from to output a TSCAL
413: * a pointer to the address in the code of the namelist
414: * is kept in value[ NL_ELABEL ].
415: */
416: listnames(ap)
417:
418: register struct nl *ap;
419: {
420: struct nl *next;
421: #ifdef OBJ
422: register int oldlc;
423: #endif
424: register int len;
425: register unsigned w;
426: register char *strptr;
427:
428: if ( !CGENNING )
429: /* code is off - do nothing */
430: return(NIL);
431: if (ap->class != TYPE)
432: ap = ap->type;
433: if (ap->value[ NL_ELABEL ] != 0) {
434: /* the list already exists */
435: return( ap -> value[ NL_ELABEL ] );
436: }
437: # ifdef OBJ
438: oldlc = (int) lc; /* same problem as put */
439: (void) put(2, O_TRA, lc);
440: ap->value[ NL_ELABEL ] = (int) lc;
441: # endif OBJ
442: # ifdef PC
443: putprintf(" .data", 0);
444: aligndot(A_STRUCT);
445: ap -> value[ NL_ELABEL ] = (int) getlab();
446: (void) putlab((char *) ap -> value[ NL_ELABEL ] );
447: # endif PC
448: /* number of scalars */
449: next = ap->type;
450: len = next->range[1]-next->range[0]+1;
451: # ifdef OBJ
452: (void) put(2, O_CASE2, len);
453: # endif OBJ
454: # ifdef PC
455: putprintf( " .word %d" , 0 , len );
456: # endif PC
457: /* offsets of each scalar name */
458: len = (len+1)*sizeof(short);
459: # ifdef OBJ
460: (void) put(2, O_CASE2, len);
461: # endif OBJ
462: # ifdef PC
463: putprintf( " .word %d" , 0 , len );
464: # endif PC
465: next = ap->chain;
466: do {
467: for(strptr = next->symbol; *strptr++; len++)
468: continue;
469: len++;
470: # ifdef OBJ
471: (void) put(2, O_CASE2, len);
472: # endif OBJ
473: # ifdef PC
474: putprintf( " .word %d" , 0 , len );
475: # endif PC
476: } while (next = next->chain);
477: /* list of scalar names */
478: strptr = getnext(ap, &next);
479: # ifdef OBJ
480: do {
481: # ifdef DEC11
482: w = (unsigned) *strptr;
483: # else
484: w = *strptr << 8;
485: # endif DEC11
486: if (!*strptr++)
487: strptr = getnext(next, &next);
488: # ifdef DEC11
489: w |= *strptr << 8;
490: # else
491: w |= (unsigned) *strptr;
492: # endif DEC11
493: if (!*strptr++)
494: strptr = getnext(next, &next);
495: word((int) w);
496: } while (next);
497: /* jump over the mess */
498: patch((PTR_DCL) oldlc);
499: # endif OBJ
500: # ifdef PC
501: while ( next ) {
502: while ( *strptr ) {
503: putprintf( " .byte 0%o" , 1 , *strptr++ );
504: for ( w = 2 ; ( w <= 8 ) && *strptr ; w ++ ) {
505: putprintf( ",0%o" , 1 , *strptr++ );
506: }
507: putprintf( "" , 0 );
508: }
509: putprintf( " .byte 0" , 0 );
510: strptr = getnext( next , &next );
511: }
512: putprintf( " .text" , 0 );
513: # endif PC
514: return( ap -> value[ NL_ELABEL ] );
515: }
516:
517: char *
518: getnext(next, new)
519:
520: struct nl *next, **new;
521: {
522: if (next != NIL) {
523: next = next->chain;
524: *new = next;
525: }
526: if (next == NLNIL)
527: return("");
528: #ifdef OBJ
529: if (opt('k') && CGENNING )
530: printf("%5d\t\t\"%s\"\n", lc-HEADER_BYTES, next->symbol);
531: #endif OBJ
532: return(next->symbol);
533: }
534:
535: #ifdef OBJ
536: /*
537: * Putspace puts out a table
538: * of nothing to leave space
539: * for the case branch table e.g.
540: */
541: putspace(n)
542: int n;
543: {
544: register i;
545:
546: if ( !CGENNING )
547: /*
548: * code disabled - do nothing
549: */
550: return;
551: #ifdef DEBUG
552: if (opt('k'))
553: printf("%5d\t.=.+%d\n", lc - HEADER_BYTES, n);
554: #endif
555: for (i = even(n); i > 0; i -= 2)
556: word(0);
557: }
558:
559: putstr(sptr, padding)
560:
561: char *sptr;
562: int padding;
563: {
564: register unsigned short w;
565: register char *strptr = sptr;
566: register int pad = padding;
567:
568: if ( !CGENNING )
569: /*
570: * code disabled - do nothing
571: */
572: return;
573: #ifdef DEBUG
574: if (opt('k'))
575: printf("%5d\t\t\"%s\"\n", lc-HEADER_BYTES, strptr);
576: #endif
577: if (pad == 0) {
578: do {
579: # ifdef DEC11
580: w = (unsigned short) * strptr;
581: # else
582: w = (unsigned short)*strptr<<8;
583: # endif DEC11
584: if (w)
585: # ifdef DEC11
586: w |= *++strptr << 8;
587: # else
588: w |= *++strptr;
589: # endif DEC11
590: word((int) w);
591: } while (*strptr++);
592: } else {
593: # ifdef DEC11
594: do {
595: w = (unsigned short) * strptr;
596: if (w) {
597: if (*++strptr)
598: w |= *strptr << 8;
599: else {
600: w |= ' ' << 8;
601: pad--;
602: }
603: word((int) w);
604: }
605: } while (*strptr++);
606: # else
607: do {
608: w = (unsigned short)*strptr<<8;
609: if (w) {
610: if (*++strptr)
611: w |= *strptr;
612: else {
613: w |= ' ';
614: pad--;
615: }
616: word(w);
617: }
618: } while (*strptr++);
619: # endif DEC11
620: while (pad > 1) {
621: # ifdef DEC11
622: word(' ' | (' ' << 8));
623: # else
624: word((' ' << 8) | ' ');
625: # endif DEC11
626: pad -= 2;
627: }
628: if (pad == 1)
629: # ifdef DEC11
630: word(' ');
631: # else
632: word(' ' << 8);
633: # endif DEC11
634: else
635: word(0);
636: }
637: }
638: #endif OBJ
639:
640: #ifndef PC
641: lenstr(sptr, padding)
642:
643: char *sptr;
644: int padding;
645:
646: {
647: register int cnt;
648: register char *strptr = sptr;
649:
650: cnt = padding;
651: do {
652: cnt++;
653: } while (*strptr++);
654: return((++cnt) & ~1);
655: }
656: #endif
657:
658: /*
659: * Patch repairs the branch
660: * at location loc to come
661: * to the current location.
662: * for PC, this puts down the label
663: * and the branch just references that label.
664: * lets here it for two pass assemblers.
665: */
666: patch(loc)
667: PTR_DCL loc;
668: {
669:
670: # ifdef OBJ
671: patchfil(loc, (long)(lc-loc-2), 1);
672: # endif OBJ
673: # ifdef PC
674: (void) putlab((char *) loc );
675: # endif PC
676: }
677:
678: #ifdef OBJ
679: patch4(loc)
680: PTR_DCL loc;
681: {
682: patchfil(loc, (long)(lc - HEADER_BYTES), 2);
683: }
684:
685: /*
686: * Patchfil makes loc+2 have jmploc
687: * as its contents.
688: */
689: patchfil(loc, jmploc, words)
690: PTR_DCL loc;
691: long jmploc;
692: int words;
693: {
694: register i;
695: extern long lseek();
696: short val;
697:
698: if ( !CGENNING )
699: return;
700: if (loc > (unsigned) lc)
701: panic("patchfil");
702: #ifdef DEBUG
703: if (opt('k'))
704: printf("\tpatch %u %D\n", loc - HEADER_BYTES, jmploc);
705: #endif
706: val = jmploc;
707: do {
708: # ifndef DEC11
709: if (words > 1)
710: val = jmploc >> 16;
711: else
712: val = jmploc;
713: # endif DEC11
714: i = ((unsigned) loc + 2 - ((unsigned) lc & ~01777))/2;
715: if (i >= 0 && i < 1024) {
716: obuf[i] = val;
717: } else {
718: (void) lseek(ofil, (long) loc+2, 0);
719: write(ofil, (char *) (&val), 2);
720: (void) lseek(ofil, (long) 0, 2);
721: }
722: loc += 2;
723: # ifdef DEC11
724: val = jmploc >> 16;
725: # endif DEC11
726: } while (--words);
727: }
728:
729: /*
730: * Put the word o into the code
731: */
732: word(o)
733: int o;
734: {
735:
736: *obufp = o;
737: obufp++;
738: lc += 2;
739: if (obufp >= obuf+512)
740: pflush();
741: }
742:
743: extern char *obj;
744: /*
745: * Flush the code buffer
746: */
747: pflush()
748: {
749: register i;
750:
751: i = (obufp - ( ( short * ) obuf ) ) * 2;
752: if (i != 0 && write(ofil, (char *) obuf, i) != i)
753: perror(obj), pexit(DIED);
754: obufp = obuf;
755: }
756: #endif OBJ
757:
758: /*
759: * Getlab - returns the location counter.
760: * included here for the eventual code generator.
761: * for PC, thank you!
762: */
763: char *
764: getlab()
765: {
766: # ifdef OBJ
767:
768: return (lc);
769: # endif OBJ
770: # ifdef PC
771: static long lastlabel;
772:
773: return ( (char *) ++lastlabel );
774: # endif PC
775: }
776:
777: /*
778: * Putlab - lay down a label.
779: * for PC, just print the label name with a colon after it.
780: */
781: char *
782: putlab(l)
783: char *l;
784: {
785:
786: # ifdef PC
787: putprintf( PREFIXFORMAT , 1 , (int) LABELPREFIX , (int) l );
788: putprintf( ":" , 0 );
789: # endif PC
790: return (l);
791: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.