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