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