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.1 (Berkeley) 6/18/85"; 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 = even(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: }