1769Speter /* Copyright (c) 1979 Regents of the University of California */ 2769Speter 3*2213Speter static char sccsid[] = "@(#)put.c 1.8 01/22/81"; 4769Speter 5769Speter #include "whoami.h" 6769Speter #include "opcode.h" 7769Speter #include "0.h" 8769Speter #include "objfmt.h" 9769Speter #ifdef PC 10769Speter # include "pc.h" 11769Speter #endif PC 12769Speter 13769Speter short *obufp = obuf; 14769Speter 15769Speter /* 16769Speter * If DEBUG is defined, include the table 17769Speter * of the printing opcode names. 18769Speter */ 19769Speter #ifdef DEBUG 20769Speter #include "OPnames.h" 21769Speter #endif 22769Speter 23769Speter #ifdef OBJ 24769Speter /* 25769Speter * Put is responsible for the interpreter equivalent of code 26769Speter * generation. Since the interpreter is specifically designed 27769Speter * for Pascal, little work is required here. 28769Speter */ 29769Speter put(a) 30769Speter { 31769Speter register int *p, i; 32769Speter register char *cp; 33769Speter int n, subop, suboppr, op, oldlc, w; 34769Speter char *string; 35769Speter static int casewrd; 36769Speter 37769Speter /* 38769Speter * It would be nice to do some more 39769Speter * optimizations here. The work 40769Speter * done to collapse offsets in lval 41769Speter * should be done here, the IFEQ etc 42769Speter * relational operators could be used 43769Speter * etc. 44769Speter */ 45769Speter oldlc = lc; 46769Speter if (cgenflg < 0) 47769Speter /* 48769Speter * code disabled - do nothing 49769Speter */ 50769Speter return (oldlc); 51769Speter p = &a; 52769Speter n = *p++; 53769Speter suboppr = subop = (*p>>8) & 0377; 54769Speter op = *p & 0377; 55769Speter string = 0; 56769Speter #ifdef DEBUG 57769Speter if ((cp = otext[op]) == NIL) { 58769Speter printf("op= %o\n", op); 59769Speter panic("put"); 60769Speter } 61769Speter #endif 62769Speter switch (op) { 63769Speter case O_ABORT: 64769Speter cp = "*"; 65769Speter break; 66769Speter case O_LINO: 67769Speter /***** 68769Speter if (line == codeline) 69769Speter return (oldlc); 70769Speter codeline = line; 71769Speter *****/ 72769Speter case O_NEW: 73769Speter case O_DISPOSE: 74769Speter case O_AS: 75769Speter case O_IND: 76769Speter case O_LVCON: 77769Speter case O_CON: 78769Speter case O_OFF: 79769Speter case O_INX2: 80769Speter case O_INX4: 81769Speter case O_CARD: 82769Speter case O_ADDT: 83769Speter case O_SUBT: 84769Speter case O_MULT: 85769Speter case O_IN: 86769Speter case O_CASE1OP: 87769Speter case O_CASE2OP: 88769Speter case O_CASE4OP: 891199Speter case O_FRTN: 90769Speter case O_WRITES: 91769Speter case O_WRITEF: 92769Speter case O_MAX: 93769Speter case O_MIN: 94769Speter case O_ARGV: 95769Speter case O_CTTOT: 96769Speter case O_INCT: 97769Speter case O_RANG2: 98769Speter case O_RSNG2: 99769Speter case O_RANG42: 100769Speter case O_RSNG42: 1012105Smckusic case O_SUCC2: 1022105Smckusic case O_SUCC24: 1032105Smckusic case O_PRED2: 1042105Smckusic case O_PRED24: 105769Speter if (p[1] == 0) 106769Speter break; 107769Speter case O_CON2: 108769Speter case O_CON24: 109769Speter if (p[1] < 128 && p[1] >= -128) { 110769Speter suboppr = subop = p[1]; 111769Speter p++; 112769Speter n--; 113769Speter if (op == O_CON2) { 114769Speter op = O_CON1; 115769Speter cp = otext[O_CON1]; 116769Speter } 117769Speter if (op == O_CON24) { 118769Speter op = O_CON14; 119769Speter cp = otext[O_CON14]; 120769Speter } 121769Speter } 122769Speter break; 123769Speter case O_CON8: 124769Speter { 125769Speter short *sp = &p[1]; 126769Speter 127769Speter #ifdef DEBUG 128769Speter if ( opt( 'k' ) ) 129769Speter printf ( ")#%5d\tCON8\t%10.3f\n" , 130769Speter lc - HEADER_BYTES , 131769Speter * ( ( double * ) &p[1] ) ); 132769Speter #endif 133769Speter word ( op ); 134769Speter for ( i = 1 ; i <= 4 ; i ++ ) 135769Speter word ( *sp ++ ); 136769Speter return ( oldlc ); 137769Speter } 138769Speter default: 139769Speter if (op >= O_REL2 && op <= O_REL84) { 1401883Smckusic if ((i = (subop >> INDX) * 5 ) >= 30) 141769Speter i -= 30; 142769Speter else 143769Speter i += 2; 144769Speter #ifdef DEBUG 145769Speter string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i]; 146769Speter #endif 147769Speter suboppr = 0; 148769Speter } 149769Speter break; 150769Speter case O_IF: 151769Speter case O_TRA: 152769Speter /***** 153769Speter codeline = 0; 154769Speter *****/ 1552184Smckusic /* relative addressing */ 1562184Smckusic p[1] -= ( unsigned ) lc + sizeof(short); 1572184Smckusic break; 158769Speter case O_FOR1U: 159769Speter case O_FOR2U: 160769Speter case O_FOR1D: 161769Speter case O_FOR2D: 162769Speter /* relative addressing */ 1632184Smckusic p[3] -= ( unsigned ) lc + 3 * sizeof(short); 164769Speter break; 165769Speter case O_CONG: 166769Speter i = p[1]; 167769Speter cp = * ( ( char ** ) &p[2] ) ; 168769Speter #ifdef DEBUG 169769Speter if (opt('k')) 170769Speter printf(")#%5d\tCONG:%d\t%s\n", 171769Speter lc - HEADER_BYTES, i, cp); 172769Speter #endif 173769Speter if (i <= 127) 174769Speter word(O_CON | i << 8); 175769Speter else { 176769Speter word(O_CON); 177769Speter word(i); 178769Speter } 179769Speter while (i > 0) { 180769Speter w = *cp ? *cp++ : ' '; 181769Speter w |= (*cp ? *cp++ : ' ') << 8; 182769Speter word(w); 183769Speter i -= 2; 184769Speter } 185769Speter return (oldlc); 186769Speter case O_CONC: 187769Speter #ifdef DEBUG 188769Speter (string = "'x'")[1] = p[1]; 189769Speter #endif 190769Speter suboppr = 0; 191769Speter op = O_CON1; 192769Speter cp = otext[O_CON1]; 193769Speter subop = p[1]; 194769Speter goto around; 195769Speter case O_CONC4: 196769Speter #ifdef DEBUG 197769Speter (string = "'x'")[1] = p[1]; 198769Speter #endif 199769Speter suboppr = 0; 200769Speter op = O_CON14; 201769Speter subop = p[1]; 202769Speter goto around; 203769Speter case O_CON1: 204769Speter case O_CON14: 205769Speter suboppr = subop = p[1]; 206769Speter around: 207769Speter n--; 208769Speter break; 209769Speter case O_CASEBEG: 210769Speter casewrd = 0; 211769Speter return (oldlc); 212769Speter case O_CASEEND: 213769Speter if ((unsigned) lc & 1) { 214769Speter lc--; 215769Speter word(casewrd); 216769Speter } 217769Speter return (oldlc); 218769Speter case O_CASE1: 219769Speter #ifdef DEBUG 220769Speter if (opt('k')) 221769Speter printf(")#%5d\tCASE1\t%d\n" 222769Speter , lc - HEADER_BYTES 223769Speter , ( int ) *( ( long * ) &p[1] ) ); 224769Speter #endif 225769Speter /* 226769Speter * this to build a byte size case table 227769Speter * saving bytes across calls in casewrd 228769Speter * so they can be put out by word() 229769Speter */ 230769Speter lc++; 231769Speter if ((unsigned) lc & 1) 232892Speter casewrd = *( ( long * ) &p[1] ) & 0377; 233769Speter else { 234769Speter lc -= 2; 235769Speter word ( casewrd 236769Speter | ( ( int ) *( ( long * ) &p[1] ) << 8 ) ); 237769Speter } 238769Speter return (oldlc); 239769Speter case O_CASE2: 240769Speter #ifdef DEBUG 241769Speter if (opt('k')) 242769Speter printf(")#%5d\tCASE2\t%d\n" 243769Speter , lc - HEADER_BYTES 244769Speter , ( int ) *( ( long * ) &p[1] ) ); 245769Speter #endif 246769Speter word( ( short ) *( ( long * ) &p[1] ) ); 247769Speter return (oldlc); 2481199Speter case O_FCALL: 2491199Speter if (p[1] == 0) 2501199Speter goto longgen; 2511199Speter /* and fall through */ 252769Speter case O_PUSH: 253769Speter if (p[1] == 0) 254769Speter return (oldlc); 255769Speter if (p[1] < 128 && p[1] >= -128) { 256769Speter suboppr = subop = p[1]; 257769Speter p++; 258769Speter n--; 259769Speter break; 260769Speter } 261769Speter goto longgen; 2622184Smckusic case O_FOR4U: 2632184Smckusic case O_FOR4D: 2642184Smckusic /* relative addressing */ 2652184Smckusic p[3] -= ( unsigned ) lc + 2662184Smckusic (sizeof(short) + 2 * sizeof(long)); 2672184Smckusic goto longgen; 268769Speter case O_TRA4: 269769Speter case O_CALL: 2701199Speter case O_FSAV: 271769Speter case O_GOTO: 272769Speter case O_NAM: 273769Speter case O_READE: 274769Speter /* absolute long addressing */ 275769Speter p[1] -= HEADER_BYTES; 276769Speter goto longgen; 277769Speter case O_RV1: 278769Speter case O_RV14: 279769Speter case O_RV2: 280769Speter case O_RV24: 281769Speter case O_RV4: 282769Speter case O_RV8: 283769Speter case O_RV: 284769Speter case O_LV: 2852105Smckusic /* 2862105Smckusic * positive offsets represent arguments 2872105Smckusic * and must use "ap" display entry rather 2882105Smckusic * than the "fp" entry 2892105Smckusic */ 2902105Smckusic if (p[1] >= 0) { 2912105Smckusic subop++; 2922105Smckusic suboppr++; 2932105Smckusic } 2942105Smckusic /* 2952105Smckusic * offsets out of range of word addressing 2962105Smckusic * must use long offset opcodes 2972105Smckusic */ 298769Speter if (p[1] < SHORTADDR && p[1] >= -SHORTADDR) 299769Speter break; 300769Speter else { 301769Speter op += O_LRV - O_RV; 302769Speter cp = otext[op]; 303769Speter } 3042105Smckusic /* and fall through */ 305769Speter case O_BEG: 306769Speter case O_NODUMP: 307769Speter case O_CON4: 308769Speter case O_CASE4: 309769Speter case O_RANG4: 310769Speter case O_RANG24: 311769Speter case O_RSNG4: 312769Speter case O_RSNG24: 3132105Smckusic case O_SUCC4: 3142105Smckusic case O_PRED4: 315769Speter longgen: 316769Speter { 317769Speter short *sp = &p[1]; 318769Speter long *lp = &p[1]; 319769Speter 320769Speter n = (n << 1) - 1; 3212184Smckusic if ( op == O_LRV || op == O_FOR4U || op == O_FOR4D) 322769Speter n--; 323769Speter #ifdef DEBUG 324769Speter if (opt('k')) 325769Speter { 326769Speter printf( ")#%5d\t%s" , lc - HEADER_BYTES , cp+1 ); 327769Speter if (suboppr) 328769Speter printf(":%1d", suboppr); 329769Speter for ( i = 1 ; i < n 330769Speter ; i += sizeof ( long )/sizeof ( short ) ) 331769Speter printf( "\t%D " , *lp ++ ); 332769Speter pchr ( '\n' ); 333769Speter } 334769Speter #endif 335769Speter if ( op != O_CASE4 ) 336769Speter word ( op | subop<<8 ); 337769Speter for ( i = 1 ; i < n ; i ++ ) 338769Speter word ( *sp ++ ); 339769Speter return ( oldlc ); 340769Speter } 341769Speter } 342769Speter #ifdef DEBUG 343769Speter if (opt('k')) { 344769Speter printf(")#%5d\t%s", lc - HEADER_BYTES, cp+1); 345769Speter if (suboppr) 346769Speter printf(":%d", suboppr); 347769Speter if (string) 348769Speter printf("\t%s",string); 349769Speter if (n > 1) 350769Speter pchr('\t'); 351769Speter for (i=1; i<n; i++) 352769Speter printf("%d ", ( short ) p[i]); 353769Speter pchr('\n'); 354769Speter } 355769Speter #endif 356769Speter if (op != NIL) 357769Speter word(op | subop << 8); 358769Speter for (i=1; i<n; i++) 359769Speter word(p[i]); 360769Speter return (oldlc); 361769Speter } 362769Speter #endif OBJ 363769Speter 364769Speter /* 365769Speter * listnames outputs a list of enumerated type names which 366769Speter * can then be selected from to output a TSCAL 367769Speter * a pointer to the address in the code of the namelist 368769Speter * is kept in value[ NL_ELABEL ]. 369769Speter */ 370769Speter listnames(ap) 371769Speter 372769Speter register struct nl *ap; 373769Speter { 374769Speter struct nl *next; 375769Speter register int oldlc, len; 376769Speter register unsigned w; 377769Speter register char *strptr; 378769Speter 379769Speter if (cgenflg < 0) 380769Speter /* code is off - do nothing */ 381769Speter return(NIL); 382769Speter if (ap->class != TYPE) 383769Speter ap = ap->type; 384769Speter if (ap->value[ NL_ELABEL ] != 0) { 385769Speter /* the list already exists */ 386769Speter return( ap -> value[ NL_ELABEL ] ); 387769Speter } 388769Speter # ifdef OBJ 389769Speter oldlc = lc; 390769Speter put(2, O_TRA, lc); 391769Speter ap->value[ NL_ELABEL ] = lc; 392769Speter # endif OBJ 393769Speter # ifdef PC 394769Speter putprintf( " .data" , 0 ); 395769Speter putprintf( " .align 1" , 0 ); 396769Speter ap -> value[ NL_ELABEL ] = getlab(); 397769Speter putlab( ap -> value[ NL_ELABEL ] ); 398769Speter # endif PC 399769Speter /* number of scalars */ 400769Speter next = ap->type; 401769Speter len = next->range[1]-next->range[0]+1; 402769Speter # ifdef OBJ 403769Speter put(2, O_CASE2, len); 404769Speter # endif OBJ 405769Speter # ifdef PC 406769Speter putprintf( " .word %d" , 0 , len ); 407769Speter # endif PC 408769Speter /* offsets of each scalar name */ 409769Speter len = (len+1)*sizeof(short); 410769Speter # ifdef OBJ 411769Speter put(2, O_CASE2, len); 412769Speter # endif OBJ 413769Speter # ifdef PC 414769Speter putprintf( " .word %d" , 0 , len ); 415769Speter # endif PC 416769Speter next = ap->chain; 417769Speter do { 418769Speter for(strptr = next->symbol; *strptr++; len++) 419769Speter continue; 420769Speter len++; 421769Speter # ifdef OBJ 422769Speter put(2, O_CASE2, len); 423769Speter # endif OBJ 424769Speter # ifdef PC 425769Speter putprintf( " .word %d" , 0 , len ); 426769Speter # endif PC 427769Speter } while (next = next->chain); 428769Speter /* list of scalar names */ 429769Speter strptr = getnext(ap, &next); 430769Speter # ifdef OBJ 431769Speter do { 432769Speter w = (unsigned) *strptr; 433769Speter if (!*strptr++) 434769Speter strptr = getnext(next, &next); 435769Speter w |= *strptr << 8; 436769Speter if (!*strptr++) 437769Speter strptr = getnext(next, &next); 438769Speter word(w); 439769Speter } while (next); 440769Speter /* jump over the mess */ 441769Speter patch(oldlc); 442769Speter # endif OBJ 443769Speter # ifdef PC 444769Speter while ( next ) { 445769Speter while ( *strptr ) { 446769Speter putprintf( " .byte 0%o" , 1 , *strptr++ ); 447769Speter for ( w = 2 ; ( w <= 8 ) && *strptr ; w ++ ) { 448769Speter putprintf( ",0%o" , 1 , *strptr++ ); 449769Speter } 450769Speter putprintf( "" , 0 ); 451769Speter } 452769Speter putprintf( " .byte 0" , 0 ); 453769Speter strptr = getnext( next , &next ); 454769Speter } 455769Speter putprintf( " .text" , 0 ); 456769Speter # endif PC 457769Speter return( ap -> value[ NL_ELABEL ] ); 458769Speter } 459769Speter 460769Speter getnext(next, new) 461769Speter 462769Speter struct nl *next, **new; 463769Speter { 464769Speter if (next != NIL) { 465769Speter next = next->chain; 466769Speter *new = next; 467769Speter } 468769Speter if (next == NIL) 469769Speter return(""); 470769Speter #ifdef OBJ 471769Speter if (opt('k') && cgenflg >= 0) 472769Speter printf(")#%5d\t\t\"%s\"\n", lc-HEADER_BYTES, next->symbol); 473*2213Speter #endif OBJ 474769Speter return(next->symbol); 475769Speter } 476769Speter 477769Speter #ifdef OBJ 478769Speter /* 479769Speter * Putspace puts out a table 480769Speter * of nothing to leave space 481769Speter * for the case branch table e.g. 482769Speter */ 483769Speter putspace(n) 484769Speter int n; 485769Speter { 486769Speter register i; 487769Speter 488769Speter if (cgenflg < 0) 489769Speter /* 490769Speter * code disabled - do nothing 491769Speter */ 492769Speter return(lc); 493769Speter #ifdef DEBUG 494769Speter if (opt('k')) 495769Speter printf(")#%5d\t.=.+%d\n", lc - HEADER_BYTES, n); 496769Speter #endif 497769Speter for (i = even(n); i > 0; i -= 2) 498769Speter word(0); 499769Speter } 500769Speter 501769Speter putstr(sptr, padding) 502769Speter 503769Speter char *sptr; 504769Speter int padding; 505769Speter { 506769Speter register unsigned short w; 507769Speter register char *strptr = sptr; 508769Speter register int pad = padding; 509769Speter 510769Speter if (cgenflg < 0) 511769Speter /* 512769Speter * code disabled - do nothing 513769Speter */ 514769Speter return(lc); 515769Speter #ifdef DEBUG 516769Speter if (opt('k')) 517769Speter printf(")#%5D\t\t\"%s\"\n", lc-HEADER_BYTES, strptr); 518769Speter #endif 519769Speter if (pad == 0) { 520769Speter do { 521769Speter w = (unsigned short) * strptr; 522769Speter if (w) 523769Speter w |= *++strptr << 8; 524769Speter word(w); 525769Speter } while (*strptr++); 526769Speter } else { 527769Speter do { 528769Speter w = (unsigned short) * strptr; 529769Speter if (w) { 530769Speter if (*++strptr) 531769Speter w |= *strptr << 8; 532769Speter else { 533769Speter w |= ' ' << 8; 534769Speter pad--; 535769Speter } 536769Speter word(w); 537769Speter } 538769Speter } while (*strptr++); 539769Speter while (pad > 1) { 540769Speter word(' '); 541769Speter pad -= 2; 542769Speter } 543769Speter if (pad == 1) 544769Speter word(' '); 545769Speter else 546769Speter word(0); 547769Speter } 548769Speter } 549769Speter #endif OBJ 550769Speter 551769Speter lenstr(sptr, padding) 552769Speter 553769Speter char *sptr; 554769Speter int padding; 555769Speter 556769Speter { 557769Speter register int cnt; 558769Speter register char *strptr = sptr; 559769Speter 560769Speter cnt = padding; 561769Speter do { 562769Speter cnt++; 563769Speter } while (*strptr++); 564769Speter return((++cnt) & ~1); 565769Speter } 566769Speter 567769Speter /* 568769Speter * Patch repairs the branch 569769Speter * at location loc to come 570769Speter * to the current location. 571769Speter * for PC, this puts down the label 572769Speter * and the branch just references that label. 573769Speter * lets here it for two pass assemblers. 574769Speter */ 575769Speter patch(loc) 576769Speter { 577769Speter 578769Speter # ifdef OBJ 579769Speter patchfil(loc, lc-loc-2, 1); 580769Speter # endif OBJ 581769Speter # ifdef PC 582769Speter putlab( loc ); 583769Speter # endif PC 584769Speter } 585769Speter 586769Speter #ifdef OBJ 587769Speter patch4(loc) 588769Speter { 589769Speter 590769Speter patchfil(loc, lc - HEADER_BYTES, 2); 591769Speter } 592769Speter 593769Speter /* 594769Speter * Patchfil makes loc+2 have value 595769Speter * as its contents. 596769Speter */ 597769Speter patchfil(loc, value, words) 598769Speter PTR_DCL loc; 599769Speter int value, words; 600769Speter { 601769Speter register i; 602769Speter 603769Speter if (cgenflg < 0) 604769Speter return; 605769Speter if (loc > (unsigned) lc) 606769Speter panic("patchfil"); 607769Speter #ifdef DEBUG 608769Speter if (opt('k')) 609769Speter printf(")#\tpatch %u %d\n", loc - HEADER_BYTES, value); 610769Speter #endif 611769Speter do { 612769Speter i = ((unsigned) loc + 2 - ((unsigned) lc & ~01777))/2; 613769Speter if (i >= 0 && i < 1024) 614769Speter obuf[i] = value; 615769Speter else { 616769Speter lseek(ofil, (long) loc+2, 0); 617769Speter write(ofil, &value, 2); 618769Speter lseek(ofil, (long) 0, 2); 619769Speter } 620769Speter loc += 2; 621769Speter value = value >> 16; 622769Speter } while (--words); 623769Speter } 624769Speter 625769Speter /* 626769Speter * Put the word o into the code 627769Speter */ 628769Speter word(o) 629769Speter int o; 630769Speter { 631769Speter 632769Speter *obufp = o; 633769Speter obufp++; 634769Speter lc += 2; 635769Speter if (obufp >= obuf+512) 636769Speter pflush(); 637769Speter } 638769Speter 639769Speter extern char *obj; 640769Speter /* 641769Speter * Flush the code buffer 642769Speter */ 643769Speter pflush() 644769Speter { 645769Speter register i; 646769Speter 647769Speter i = (obufp - ( ( short * ) obuf ) ) * 2; 648769Speter if (i != 0 && write(ofil, obuf, i) != i) 649769Speter perror(obj), pexit(DIED); 650769Speter obufp = obuf; 651769Speter } 652769Speter #endif OBJ 653769Speter 654769Speter /* 655769Speter * Getlab - returns the location counter. 656769Speter * included here for the eventual code generator. 657769Speter * for PC, thank you! 658769Speter */ 659769Speter getlab() 660769Speter { 661769Speter # ifdef OBJ 662769Speter 663769Speter return (lc); 664769Speter # endif OBJ 665769Speter # ifdef PC 666769Speter static long lastlabel; 667769Speter 668769Speter return ( ++lastlabel ); 669769Speter # endif PC 670769Speter } 671769Speter 672769Speter /* 673769Speter * Putlab - lay down a label. 674769Speter * for PC, just print the label name with a colon after it. 675769Speter */ 676769Speter putlab(l) 677769Speter int l; 678769Speter { 679769Speter 680769Speter # ifdef PC 681769Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , l ); 682769Speter putprintf( ":" , 0 ); 683769Speter # endif PC 684769Speter return (l); 685769Speter } 686769Speter 687