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