1769Speter /* Copyright (c) 1979 Regents of the University of California */ 2769Speter 3*1883Smckusic static char sccsid[] = "@(#)put.c 1.4 12/12/80"; 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_PACK: 95769Speter case O_UNPACK: 96769Speter case O_ARGV: 97769Speter case O_CTTOT: 98769Speter case O_INCT: 99769Speter case O_RANG2: 100769Speter case O_RSNG2: 101769Speter case O_RANG42: 102769Speter case O_RSNG42: 103769Speter if (p[1] == 0) 104769Speter break; 105769Speter case O_CON2: 106769Speter case O_CON24: 107769Speter if (p[1] < 128 && p[1] >= -128) { 108769Speter suboppr = subop = p[1]; 109769Speter p++; 110769Speter n--; 111769Speter if (op == O_CON2) { 112769Speter op = O_CON1; 113769Speter cp = otext[O_CON1]; 114769Speter } 115769Speter if (op == O_CON24) { 116769Speter op = O_CON14; 117769Speter cp = otext[O_CON14]; 118769Speter } 119769Speter } 120769Speter break; 121769Speter case O_CON8: 122769Speter { 123769Speter short *sp = &p[1]; 124769Speter 125769Speter #ifdef DEBUG 126769Speter if ( opt( 'k' ) ) 127769Speter printf ( ")#%5d\tCON8\t%10.3f\n" , 128769Speter lc - HEADER_BYTES , 129769Speter * ( ( double * ) &p[1] ) ); 130769Speter #endif 131769Speter word ( op ); 132769Speter for ( i = 1 ; i <= 4 ; i ++ ) 133769Speter word ( *sp ++ ); 134769Speter return ( oldlc ); 135769Speter } 136769Speter default: 137769Speter if (op >= O_REL2 && op <= O_REL84) { 138*1883Smckusic if ((i = (subop >> INDX) * 5 ) >= 30) 139769Speter i -= 30; 140769Speter else 141769Speter i += 2; 142769Speter #ifdef DEBUG 143769Speter string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i]; 144769Speter #endif 145769Speter suboppr = 0; 146769Speter } 147769Speter break; 148769Speter case O_IF: 149769Speter case O_TRA: 150769Speter /***** 151769Speter codeline = 0; 152769Speter *****/ 153769Speter case O_FOR1U: 154769Speter case O_FOR2U: 155769Speter case O_FOR4U: 156769Speter case O_FOR1D: 157769Speter case O_FOR2D: 158769Speter case O_FOR4D: 159769Speter /* relative addressing */ 160769Speter p[1] -= ( unsigned ) lc + 2; 161769Speter break; 162769Speter case O_CONG: 163769Speter i = p[1]; 164769Speter cp = * ( ( char ** ) &p[2] ) ; 165769Speter #ifdef DEBUG 166769Speter if (opt('k')) 167769Speter printf(")#%5d\tCONG:%d\t%s\n", 168769Speter lc - HEADER_BYTES, i, cp); 169769Speter #endif 170769Speter if (i <= 127) 171769Speter word(O_CON | i << 8); 172769Speter else { 173769Speter word(O_CON); 174769Speter word(i); 175769Speter } 176769Speter while (i > 0) { 177769Speter w = *cp ? *cp++ : ' '; 178769Speter w |= (*cp ? *cp++ : ' ') << 8; 179769Speter word(w); 180769Speter i -= 2; 181769Speter } 182769Speter return (oldlc); 183769Speter case O_CONC: 184769Speter #ifdef DEBUG 185769Speter (string = "'x'")[1] = p[1]; 186769Speter #endif 187769Speter suboppr = 0; 188769Speter op = O_CON1; 189769Speter cp = otext[O_CON1]; 190769Speter subop = p[1]; 191769Speter goto around; 192769Speter case O_CONC4: 193769Speter #ifdef DEBUG 194769Speter (string = "'x'")[1] = p[1]; 195769Speter #endif 196769Speter suboppr = 0; 197769Speter op = O_CON14; 198769Speter subop = p[1]; 199769Speter goto around; 200769Speter case O_CON1: 201769Speter case O_CON14: 202769Speter suboppr = subop = p[1]; 203769Speter around: 204769Speter n--; 205769Speter break; 206769Speter case O_CASEBEG: 207769Speter casewrd = 0; 208769Speter return (oldlc); 209769Speter case O_CASEEND: 210769Speter if ((unsigned) lc & 1) { 211769Speter lc--; 212769Speter word(casewrd); 213769Speter } 214769Speter return (oldlc); 215769Speter case O_CASE1: 216769Speter #ifdef DEBUG 217769Speter if (opt('k')) 218769Speter printf(")#%5d\tCASE1\t%d\n" 219769Speter , lc - HEADER_BYTES 220769Speter , ( int ) *( ( long * ) &p[1] ) ); 221769Speter #endif 222769Speter /* 223769Speter * this to build a byte size case table 224769Speter * saving bytes across calls in casewrd 225769Speter * so they can be put out by word() 226769Speter */ 227769Speter lc++; 228769Speter if ((unsigned) lc & 1) 229892Speter casewrd = *( ( long * ) &p[1] ) & 0377; 230769Speter else { 231769Speter lc -= 2; 232769Speter word ( casewrd 233769Speter | ( ( int ) *( ( long * ) &p[1] ) << 8 ) ); 234769Speter } 235769Speter return (oldlc); 236769Speter case O_CASE2: 237769Speter #ifdef DEBUG 238769Speter if (opt('k')) 239769Speter printf(")#%5d\tCASE2\t%d\n" 240769Speter , lc - HEADER_BYTES 241769Speter , ( int ) *( ( long * ) &p[1] ) ); 242769Speter #endif 243769Speter word( ( short ) *( ( long * ) &p[1] ) ); 244769Speter return (oldlc); 2451199Speter case O_FCALL: 2461199Speter if (p[1] == 0) 2471199Speter goto longgen; 2481199Speter /* and fall through */ 249769Speter case O_PUSH: 250769Speter if (p[1] == 0) 251769Speter return (oldlc); 252769Speter if (p[1] < 128 && p[1] >= -128) { 253769Speter suboppr = subop = p[1]; 254769Speter p++; 255769Speter n--; 256769Speter break; 257769Speter } 258769Speter goto longgen; 259769Speter case O_TRA4: 260769Speter case O_CALL: 2611199Speter case O_FSAV: 262769Speter case O_GOTO: 263769Speter case O_NAM: 264769Speter case O_READE: 265769Speter /* absolute long addressing */ 266769Speter p[1] -= HEADER_BYTES; 267769Speter goto longgen; 268769Speter case O_RV1: 269769Speter case O_RV14: 270769Speter case O_RV2: 271769Speter case O_RV24: 272769Speter case O_RV4: 273769Speter case O_RV8: 274769Speter case O_RV: 275769Speter case O_LV: 276769Speter if (p[1] < SHORTADDR && p[1] >= -SHORTADDR) 277769Speter break; 278769Speter else { 279769Speter op += O_LRV - O_RV; 280769Speter cp = otext[op]; 281769Speter } 282769Speter case O_BEG: 283769Speter case O_NODUMP: 284769Speter case O_CON4: 285769Speter case O_CASE4: 286769Speter case O_RANG4: 287769Speter case O_RANG24: 288769Speter case O_RSNG4: 289769Speter case O_RSNG24: 290769Speter longgen: 291769Speter { 292769Speter short *sp = &p[1]; 293769Speter long *lp = &p[1]; 294769Speter 295769Speter n = (n << 1) - 1; 296769Speter if ( op == O_LRV ) 297769Speter n--; 298769Speter #ifdef DEBUG 299769Speter if (opt('k')) 300769Speter { 301769Speter printf( ")#%5d\t%s" , lc - HEADER_BYTES , cp+1 ); 302769Speter if (suboppr) 303769Speter printf(":%1d", suboppr); 304769Speter for ( i = 1 ; i < n 305769Speter ; i += sizeof ( long )/sizeof ( short ) ) 306769Speter printf( "\t%D " , *lp ++ ); 307769Speter pchr ( '\n' ); 308769Speter } 309769Speter #endif 310769Speter if ( op != O_CASE4 ) 311769Speter word ( op | subop<<8 ); 312769Speter for ( i = 1 ; i < n ; i ++ ) 313769Speter word ( *sp ++ ); 314769Speter return ( oldlc ); 315769Speter } 316769Speter } 317769Speter #ifdef DEBUG 318769Speter if (opt('k')) { 319769Speter printf(")#%5d\t%s", lc - HEADER_BYTES, cp+1); 320769Speter if (suboppr) 321769Speter printf(":%d", suboppr); 322769Speter if (string) 323769Speter printf("\t%s",string); 324769Speter if (n > 1) 325769Speter pchr('\t'); 326769Speter for (i=1; i<n; i++) 327769Speter printf("%d ", ( short ) p[i]); 328769Speter pchr('\n'); 329769Speter } 330769Speter #endif 331769Speter if (op != NIL) 332769Speter word(op | subop << 8); 333769Speter for (i=1; i<n; i++) 334769Speter word(p[i]); 335769Speter return (oldlc); 336769Speter } 337769Speter #endif OBJ 338769Speter 339769Speter /* 340769Speter * listnames outputs a list of enumerated type names which 341769Speter * can then be selected from to output a TSCAL 342769Speter * a pointer to the address in the code of the namelist 343769Speter * is kept in value[ NL_ELABEL ]. 344769Speter */ 345769Speter listnames(ap) 346769Speter 347769Speter register struct nl *ap; 348769Speter { 349769Speter struct nl *next; 350769Speter register int oldlc, len; 351769Speter register unsigned w; 352769Speter register char *strptr; 353769Speter 354769Speter if (cgenflg < 0) 355769Speter /* code is off - do nothing */ 356769Speter return(NIL); 357769Speter if (ap->class != TYPE) 358769Speter ap = ap->type; 359769Speter if (ap->value[ NL_ELABEL ] != 0) { 360769Speter /* the list already exists */ 361769Speter return( ap -> value[ NL_ELABEL ] ); 362769Speter } 363769Speter # ifdef OBJ 364769Speter oldlc = lc; 365769Speter put(2, O_TRA, lc); 366769Speter ap->value[ NL_ELABEL ] = lc; 367769Speter # endif OBJ 368769Speter # ifdef PC 369769Speter putprintf( " .data" , 0 ); 370769Speter putprintf( " .align 1" , 0 ); 371769Speter ap -> value[ NL_ELABEL ] = getlab(); 372769Speter putlab( ap -> value[ NL_ELABEL ] ); 373769Speter # endif PC 374769Speter /* number of scalars */ 375769Speter next = ap->type; 376769Speter len = next->range[1]-next->range[0]+1; 377769Speter # ifdef OBJ 378769Speter put(2, O_CASE2, len); 379769Speter # endif OBJ 380769Speter # ifdef PC 381769Speter putprintf( " .word %d" , 0 , len ); 382769Speter # endif PC 383769Speter /* offsets of each scalar name */ 384769Speter len = (len+1)*sizeof(short); 385769Speter # ifdef OBJ 386769Speter put(2, O_CASE2, len); 387769Speter # endif OBJ 388769Speter # ifdef PC 389769Speter putprintf( " .word %d" , 0 , len ); 390769Speter # endif PC 391769Speter next = ap->chain; 392769Speter do { 393769Speter for(strptr = next->symbol; *strptr++; len++) 394769Speter continue; 395769Speter len++; 396769Speter # ifdef OBJ 397769Speter put(2, O_CASE2, len); 398769Speter # endif OBJ 399769Speter # ifdef PC 400769Speter putprintf( " .word %d" , 0 , len ); 401769Speter # endif PC 402769Speter } while (next = next->chain); 403769Speter /* list of scalar names */ 404769Speter strptr = getnext(ap, &next); 405769Speter # ifdef OBJ 406769Speter do { 407769Speter w = (unsigned) *strptr; 408769Speter if (!*strptr++) 409769Speter strptr = getnext(next, &next); 410769Speter w |= *strptr << 8; 411769Speter if (!*strptr++) 412769Speter strptr = getnext(next, &next); 413769Speter word(w); 414769Speter } while (next); 415769Speter /* jump over the mess */ 416769Speter patch(oldlc); 417769Speter # endif OBJ 418769Speter # ifdef PC 419769Speter while ( next ) { 420769Speter while ( *strptr ) { 421769Speter putprintf( " .byte 0%o" , 1 , *strptr++ ); 422769Speter for ( w = 2 ; ( w <= 8 ) && *strptr ; w ++ ) { 423769Speter putprintf( ",0%o" , 1 , *strptr++ ); 424769Speter } 425769Speter putprintf( "" , 0 ); 426769Speter } 427769Speter putprintf( " .byte 0" , 0 ); 428769Speter strptr = getnext( next , &next ); 429769Speter } 430769Speter putprintf( " .text" , 0 ); 431769Speter # endif PC 432769Speter return( ap -> value[ NL_ELABEL ] ); 433769Speter } 434769Speter 435769Speter getnext(next, new) 436769Speter 437769Speter struct nl *next, **new; 438769Speter { 439769Speter if (next != NIL) { 440769Speter next = next->chain; 441769Speter *new = next; 442769Speter } 443769Speter if (next == NIL) 444769Speter return(""); 445769Speter #ifdef OBJ 446769Speter if (opt('k') && cgenflg >= 0) 447769Speter printf(")#%5d\t\t\"%s\"\n", lc-HEADER_BYTES, next->symbol); 448769Speter #endif 449769Speter return(next->symbol); 450769Speter } 451769Speter 452769Speter #ifdef OBJ 453769Speter /* 454769Speter * Putspace puts out a table 455769Speter * of nothing to leave space 456769Speter * for the case branch table e.g. 457769Speter */ 458769Speter putspace(n) 459769Speter int n; 460769Speter { 461769Speter register i; 462769Speter 463769Speter if (cgenflg < 0) 464769Speter /* 465769Speter * code disabled - do nothing 466769Speter */ 467769Speter return(lc); 468769Speter #ifdef DEBUG 469769Speter if (opt('k')) 470769Speter printf(")#%5d\t.=.+%d\n", lc - HEADER_BYTES, n); 471769Speter #endif 472769Speter for (i = even(n); i > 0; i -= 2) 473769Speter word(0); 474769Speter } 475769Speter 476769Speter putstr(sptr, padding) 477769Speter 478769Speter char *sptr; 479769Speter int padding; 480769Speter { 481769Speter register unsigned short w; 482769Speter register char *strptr = sptr; 483769Speter register int pad = padding; 484769Speter 485769Speter if (cgenflg < 0) 486769Speter /* 487769Speter * code disabled - do nothing 488769Speter */ 489769Speter return(lc); 490769Speter #ifdef DEBUG 491769Speter if (opt('k')) 492769Speter printf(")#%5D\t\t\"%s\"\n", lc-HEADER_BYTES, strptr); 493769Speter #endif 494769Speter if (pad == 0) { 495769Speter do { 496769Speter w = (unsigned short) * strptr; 497769Speter if (w) 498769Speter w |= *++strptr << 8; 499769Speter word(w); 500769Speter } while (*strptr++); 501769Speter } else { 502769Speter do { 503769Speter w = (unsigned short) * strptr; 504769Speter if (w) { 505769Speter if (*++strptr) 506769Speter w |= *strptr << 8; 507769Speter else { 508769Speter w |= ' ' << 8; 509769Speter pad--; 510769Speter } 511769Speter word(w); 512769Speter } 513769Speter } while (*strptr++); 514769Speter while (pad > 1) { 515769Speter word(' '); 516769Speter pad -= 2; 517769Speter } 518769Speter if (pad == 1) 519769Speter word(' '); 520769Speter else 521769Speter word(0); 522769Speter } 523769Speter } 524769Speter #endif OBJ 525769Speter 526769Speter lenstr(sptr, padding) 527769Speter 528769Speter char *sptr; 529769Speter int padding; 530769Speter 531769Speter { 532769Speter register int cnt; 533769Speter register char *strptr = sptr; 534769Speter 535769Speter cnt = padding; 536769Speter do { 537769Speter cnt++; 538769Speter } while (*strptr++); 539769Speter return((++cnt) & ~1); 540769Speter } 541769Speter 542769Speter /* 543769Speter * Patch repairs the branch 544769Speter * at location loc to come 545769Speter * to the current location. 546769Speter * for PC, this puts down the label 547769Speter * and the branch just references that label. 548769Speter * lets here it for two pass assemblers. 549769Speter */ 550769Speter patch(loc) 551769Speter { 552769Speter 553769Speter # ifdef OBJ 554769Speter patchfil(loc, lc-loc-2, 1); 555769Speter # endif OBJ 556769Speter # ifdef PC 557769Speter putlab( loc ); 558769Speter # endif PC 559769Speter } 560769Speter 561769Speter #ifdef OBJ 562769Speter patch4(loc) 563769Speter { 564769Speter 565769Speter patchfil(loc, lc - HEADER_BYTES, 2); 566769Speter } 567769Speter 568769Speter /* 569769Speter * Patchfil makes loc+2 have value 570769Speter * as its contents. 571769Speter */ 572769Speter patchfil(loc, value, words) 573769Speter PTR_DCL loc; 574769Speter int value, words; 575769Speter { 576769Speter register i; 577769Speter 578769Speter if (cgenflg < 0) 579769Speter return; 580769Speter if (loc > (unsigned) lc) 581769Speter panic("patchfil"); 582769Speter #ifdef DEBUG 583769Speter if (opt('k')) 584769Speter printf(")#\tpatch %u %d\n", loc - HEADER_BYTES, value); 585769Speter #endif 586769Speter do { 587769Speter i = ((unsigned) loc + 2 - ((unsigned) lc & ~01777))/2; 588769Speter if (i >= 0 && i < 1024) 589769Speter obuf[i] = value; 590769Speter else { 591769Speter lseek(ofil, (long) loc+2, 0); 592769Speter write(ofil, &value, 2); 593769Speter lseek(ofil, (long) 0, 2); 594769Speter } 595769Speter loc += 2; 596769Speter value = value >> 16; 597769Speter } while (--words); 598769Speter } 599769Speter 600769Speter /* 601769Speter * Put the word o into the code 602769Speter */ 603769Speter word(o) 604769Speter int o; 605769Speter { 606769Speter 607769Speter *obufp = o; 608769Speter obufp++; 609769Speter lc += 2; 610769Speter if (obufp >= obuf+512) 611769Speter pflush(); 612769Speter } 613769Speter 614769Speter extern char *obj; 615769Speter /* 616769Speter * Flush the code buffer 617769Speter */ 618769Speter pflush() 619769Speter { 620769Speter register i; 621769Speter 622769Speter i = (obufp - ( ( short * ) obuf ) ) * 2; 623769Speter if (i != 0 && write(ofil, obuf, i) != i) 624769Speter perror(obj), pexit(DIED); 625769Speter obufp = obuf; 626769Speter } 627769Speter #endif OBJ 628769Speter 629769Speter /* 630769Speter * Getlab - returns the location counter. 631769Speter * included here for the eventual code generator. 632769Speter * for PC, thank you! 633769Speter */ 634769Speter getlab() 635769Speter { 636769Speter # ifdef OBJ 637769Speter 638769Speter return (lc); 639769Speter # endif OBJ 640769Speter # ifdef PC 641769Speter static long lastlabel; 642769Speter 643769Speter return ( ++lastlabel ); 644769Speter # endif PC 645769Speter } 646769Speter 647769Speter /* 648769Speter * Putlab - lay down a label. 649769Speter * for PC, just print the label name with a colon after it. 650769Speter */ 651769Speter putlab(l) 652769Speter int l; 653769Speter { 654769Speter 655769Speter # ifdef PC 656769Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , l ); 657769Speter putprintf( ":" , 0 ); 658769Speter # endif PC 659769Speter return (l); 660769Speter } 661769Speter 662