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