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