xref: /original-bsd/usr.bin/pascal/src/put.c (revision 2301fdfb)
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.2 (Berkeley) 11/12/86";
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 = 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 }
792