Commit | Line | Data |
---|---|---|
74e161b0 PK |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | ||
31cef89c | 3 | static char sccsid[] = "@(#)put.c 1.3 10/2/80"; |
74e161b0 PK |
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: | |
c4e911b6 | 89 | case O_FRTN: |
74e161b0 PK |
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) | |
40fc1934 | 229 | casewrd = *( ( long * ) &p[1] ) & 0377; |
74e161b0 PK |
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); | |
c4e911b6 PK |
245 | case O_FCALL: |
246 | if (p[1] == 0) | |
247 | goto longgen; | |
248 | /* and fall through */ | |
74e161b0 PK |
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: | |
c4e911b6 | 261 | case O_FSAV: |
74e161b0 | 262 | case O_GOTO: |
74e161b0 PK |
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 | \f | |
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 | \f | |
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 | \f | |
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 | \f | |
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 |