1769Speter /* Copyright (c) 1979 Regents of the University of California */ 2769Speter 3*2221Smckusic static char sccsid[] = "@(#)put.c 1.9 01/24/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; 66*2221Smckusic case O_AS: 67*2221Smckusic switch(p[1]) { 68*2221Smckusic case 2: 69*2221Smckusic op = O_AS2; 70*2221Smckusic break; 71*2221Smckusic case 4: 72*2221Smckusic op = O_AS4; 73*2221Smckusic break; 74*2221Smckusic case 8: 75*2221Smckusic op = O_AS8; 76*2221Smckusic break; 77*2221Smckusic default: 78*2221Smckusic goto pack; 79*2221Smckusic } 80*2221Smckusic n = 1; 81*2221Smckusic cp = otext[op]; 82*2221Smckusic break; 83769Speter case O_LINO: 84769Speter case O_NEW: 85769Speter case O_DISPOSE: 86769Speter case O_IND: 87769Speter case O_LVCON: 88769Speter case O_CON: 89769Speter case O_OFF: 90769Speter case O_INX2: 91769Speter case O_INX4: 92769Speter case O_CARD: 93769Speter case O_ADDT: 94769Speter case O_SUBT: 95769Speter case O_MULT: 96769Speter case O_IN: 97769Speter case O_CASE1OP: 98769Speter case O_CASE2OP: 99769Speter case O_CASE4OP: 1001199Speter case O_FRTN: 101769Speter case O_WRITES: 102769Speter case O_WRITEF: 103769Speter case O_MAX: 104769Speter case O_MIN: 105769Speter case O_ARGV: 106769Speter case O_CTTOT: 107769Speter case O_INCT: 108769Speter case O_RANG2: 109769Speter case O_RSNG2: 110769Speter case O_RANG42: 111769Speter case O_RSNG42: 1122105Smckusic case O_SUCC2: 1132105Smckusic case O_SUCC24: 1142105Smckusic case O_PRED2: 1152105Smckusic case O_PRED24: 116769Speter if (p[1] == 0) 117769Speter break; 118769Speter case O_CON2: 119769Speter case O_CON24: 120*2221Smckusic pack: 121769Speter if (p[1] < 128 && p[1] >= -128) { 122769Speter suboppr = subop = p[1]; 123769Speter p++; 124769Speter n--; 125769Speter if (op == O_CON2) { 126769Speter op = O_CON1; 127769Speter cp = otext[O_CON1]; 128769Speter } 129769Speter if (op == O_CON24) { 130769Speter op = O_CON14; 131769Speter cp = otext[O_CON14]; 132769Speter } 133769Speter } 134769Speter break; 135769Speter case O_CON8: 136769Speter { 137769Speter short *sp = &p[1]; 138769Speter 139769Speter #ifdef DEBUG 140769Speter if ( opt( 'k' ) ) 141769Speter printf ( ")#%5d\tCON8\t%10.3f\n" , 142769Speter lc - HEADER_BYTES , 143769Speter * ( ( double * ) &p[1] ) ); 144769Speter #endif 145769Speter word ( op ); 146769Speter for ( i = 1 ; i <= 4 ; i ++ ) 147769Speter word ( *sp ++ ); 148769Speter return ( oldlc ); 149769Speter } 150769Speter default: 151769Speter if (op >= O_REL2 && op <= O_REL84) { 1521883Smckusic if ((i = (subop >> INDX) * 5 ) >= 30) 153769Speter i -= 30; 154769Speter else 155769Speter i += 2; 156769Speter #ifdef DEBUG 157769Speter string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i]; 158769Speter #endif 159769Speter suboppr = 0; 160769Speter } 161769Speter break; 162769Speter case O_IF: 163769Speter case O_TRA: 164769Speter /***** 165769Speter codeline = 0; 166769Speter *****/ 1672184Smckusic /* relative addressing */ 1682184Smckusic p[1] -= ( unsigned ) lc + sizeof(short); 1692184Smckusic break; 170769Speter case O_FOR1U: 171769Speter case O_FOR2U: 172769Speter case O_FOR1D: 173769Speter case O_FOR2D: 174769Speter /* relative addressing */ 1752184Smckusic p[3] -= ( unsigned ) lc + 3 * sizeof(short); 176769Speter break; 177769Speter case O_CONG: 178769Speter i = p[1]; 179769Speter cp = * ( ( char ** ) &p[2] ) ; 180769Speter #ifdef DEBUG 181769Speter if (opt('k')) 182769Speter printf(")#%5d\tCONG:%d\t%s\n", 183769Speter lc - HEADER_BYTES, i, cp); 184769Speter #endif 185769Speter if (i <= 127) 186769Speter word(O_CON | i << 8); 187769Speter else { 188769Speter word(O_CON); 189769Speter word(i); 190769Speter } 191769Speter while (i > 0) { 192769Speter w = *cp ? *cp++ : ' '; 193769Speter w |= (*cp ? *cp++ : ' ') << 8; 194769Speter word(w); 195769Speter i -= 2; 196769Speter } 197769Speter return (oldlc); 198769Speter case O_CONC: 199769Speter #ifdef DEBUG 200769Speter (string = "'x'")[1] = p[1]; 201769Speter #endif 202769Speter suboppr = 0; 203769Speter op = O_CON1; 204769Speter cp = otext[O_CON1]; 205769Speter subop = p[1]; 206769Speter goto around; 207769Speter case O_CONC4: 208769Speter #ifdef DEBUG 209769Speter (string = "'x'")[1] = p[1]; 210769Speter #endif 211769Speter suboppr = 0; 212769Speter op = O_CON14; 213769Speter subop = p[1]; 214769Speter goto around; 215769Speter case O_CON1: 216769Speter case O_CON14: 217769Speter suboppr = subop = p[1]; 218769Speter around: 219769Speter n--; 220769Speter break; 221769Speter case O_CASEBEG: 222769Speter casewrd = 0; 223769Speter return (oldlc); 224769Speter case O_CASEEND: 225769Speter if ((unsigned) lc & 1) { 226769Speter lc--; 227769Speter word(casewrd); 228769Speter } 229769Speter return (oldlc); 230769Speter case O_CASE1: 231769Speter #ifdef DEBUG 232769Speter if (opt('k')) 233769Speter printf(")#%5d\tCASE1\t%d\n" 234769Speter , lc - HEADER_BYTES 235769Speter , ( int ) *( ( long * ) &p[1] ) ); 236769Speter #endif 237769Speter /* 238769Speter * this to build a byte size case table 239769Speter * saving bytes across calls in casewrd 240769Speter * so they can be put out by word() 241769Speter */ 242769Speter lc++; 243769Speter if ((unsigned) lc & 1) 244892Speter casewrd = *( ( long * ) &p[1] ) & 0377; 245769Speter else { 246769Speter lc -= 2; 247769Speter word ( casewrd 248769Speter | ( ( int ) *( ( long * ) &p[1] ) << 8 ) ); 249769Speter } 250769Speter return (oldlc); 251769Speter case O_CASE2: 252769Speter #ifdef DEBUG 253769Speter if (opt('k')) 254769Speter printf(")#%5d\tCASE2\t%d\n" 255769Speter , lc - HEADER_BYTES 256769Speter , ( int ) *( ( long * ) &p[1] ) ); 257769Speter #endif 258769Speter word( ( short ) *( ( long * ) &p[1] ) ); 259769Speter return (oldlc); 2601199Speter case O_FCALL: 2611199Speter if (p[1] == 0) 2621199Speter goto longgen; 2631199Speter /* and fall through */ 264769Speter case O_PUSH: 265769Speter if (p[1] == 0) 266769Speter return (oldlc); 267769Speter if (p[1] < 128 && p[1] >= -128) { 268769Speter suboppr = subop = p[1]; 269769Speter p++; 270769Speter n--; 271769Speter break; 272769Speter } 273769Speter goto longgen; 2742184Smckusic case O_FOR4U: 2752184Smckusic case O_FOR4D: 2762184Smckusic /* relative addressing */ 2772184Smckusic p[3] -= ( unsigned ) lc + 2782184Smckusic (sizeof(short) + 2 * sizeof(long)); 2792184Smckusic goto longgen; 280769Speter case O_TRA4: 281769Speter case O_CALL: 2821199Speter case O_FSAV: 283769Speter case O_GOTO: 284769Speter case O_NAM: 285769Speter case O_READE: 286769Speter /* absolute long addressing */ 287769Speter p[1] -= HEADER_BYTES; 288769Speter goto longgen; 289769Speter case O_RV1: 290769Speter case O_RV14: 291769Speter case O_RV2: 292769Speter case O_RV24: 293769Speter case O_RV4: 294769Speter case O_RV8: 295769Speter case O_RV: 296769Speter case O_LV: 2972105Smckusic /* 2982105Smckusic * positive offsets represent arguments 2992105Smckusic * and must use "ap" display entry rather 3002105Smckusic * than the "fp" entry 3012105Smckusic */ 3022105Smckusic if (p[1] >= 0) { 3032105Smckusic subop++; 3042105Smckusic suboppr++; 3052105Smckusic } 3062105Smckusic /* 3072105Smckusic * offsets out of range of word addressing 3082105Smckusic * must use long offset opcodes 3092105Smckusic */ 310769Speter if (p[1] < SHORTADDR && p[1] >= -SHORTADDR) 311769Speter break; 312769Speter else { 313769Speter op += O_LRV - O_RV; 314769Speter cp = otext[op]; 315769Speter } 3162105Smckusic /* and fall through */ 317769Speter case O_BEG: 318769Speter case O_NODUMP: 319769Speter case O_CON4: 320769Speter case O_CASE4: 321769Speter case O_RANG4: 322769Speter case O_RANG24: 323769Speter case O_RSNG4: 324769Speter case O_RSNG24: 3252105Smckusic case O_SUCC4: 3262105Smckusic case O_PRED4: 327769Speter longgen: 328769Speter { 329769Speter short *sp = &p[1]; 330769Speter long *lp = &p[1]; 331769Speter 332769Speter n = (n << 1) - 1; 3332184Smckusic if ( op == O_LRV || op == O_FOR4U || op == O_FOR4D) 334769Speter n--; 335769Speter #ifdef DEBUG 336769Speter if (opt('k')) 337769Speter { 338769Speter printf( ")#%5d\t%s" , lc - HEADER_BYTES , cp+1 ); 339769Speter if (suboppr) 340769Speter printf(":%1d", suboppr); 341769Speter for ( i = 1 ; i < n 342769Speter ; i += sizeof ( long )/sizeof ( short ) ) 343769Speter printf( "\t%D " , *lp ++ ); 344769Speter pchr ( '\n' ); 345769Speter } 346769Speter #endif 347769Speter if ( op != O_CASE4 ) 348769Speter word ( op | subop<<8 ); 349769Speter for ( i = 1 ; i < n ; i ++ ) 350769Speter word ( *sp ++ ); 351769Speter return ( oldlc ); 352769Speter } 353769Speter } 354769Speter #ifdef DEBUG 355769Speter if (opt('k')) { 356769Speter printf(")#%5d\t%s", lc - HEADER_BYTES, cp+1); 357769Speter if (suboppr) 358769Speter printf(":%d", suboppr); 359769Speter if (string) 360769Speter printf("\t%s",string); 361769Speter if (n > 1) 362769Speter pchr('\t'); 363769Speter for (i=1; i<n; i++) 364769Speter printf("%d ", ( short ) p[i]); 365769Speter pchr('\n'); 366769Speter } 367769Speter #endif 368769Speter if (op != NIL) 369769Speter word(op | subop << 8); 370769Speter for (i=1; i<n; i++) 371769Speter word(p[i]); 372769Speter return (oldlc); 373769Speter } 374769Speter #endif OBJ 375769Speter 376769Speter /* 377769Speter * listnames outputs a list of enumerated type names which 378769Speter * can then be selected from to output a TSCAL 379769Speter * a pointer to the address in the code of the namelist 380769Speter * is kept in value[ NL_ELABEL ]. 381769Speter */ 382769Speter listnames(ap) 383769Speter 384769Speter register struct nl *ap; 385769Speter { 386769Speter struct nl *next; 387769Speter register int oldlc, len; 388769Speter register unsigned w; 389769Speter register char *strptr; 390769Speter 391769Speter if (cgenflg < 0) 392769Speter /* code is off - do nothing */ 393769Speter return(NIL); 394769Speter if (ap->class != TYPE) 395769Speter ap = ap->type; 396769Speter if (ap->value[ NL_ELABEL ] != 0) { 397769Speter /* the list already exists */ 398769Speter return( ap -> value[ NL_ELABEL ] ); 399769Speter } 400769Speter # ifdef OBJ 401769Speter oldlc = lc; 402769Speter put(2, O_TRA, lc); 403769Speter ap->value[ NL_ELABEL ] = lc; 404769Speter # endif OBJ 405769Speter # ifdef PC 406769Speter putprintf( " .data" , 0 ); 407769Speter putprintf( " .align 1" , 0 ); 408769Speter ap -> value[ NL_ELABEL ] = getlab(); 409769Speter putlab( ap -> value[ NL_ELABEL ] ); 410769Speter # endif PC 411769Speter /* number of scalars */ 412769Speter next = ap->type; 413769Speter len = next->range[1]-next->range[0]+1; 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 /* offsets of each scalar name */ 421769Speter len = (len+1)*sizeof(short); 422769Speter # ifdef OBJ 423769Speter put(2, O_CASE2, len); 424769Speter # endif OBJ 425769Speter # ifdef PC 426769Speter putprintf( " .word %d" , 0 , len ); 427769Speter # endif PC 428769Speter next = ap->chain; 429769Speter do { 430769Speter for(strptr = next->symbol; *strptr++; len++) 431769Speter continue; 432769Speter len++; 433769Speter # ifdef OBJ 434769Speter put(2, O_CASE2, len); 435769Speter # endif OBJ 436769Speter # ifdef PC 437769Speter putprintf( " .word %d" , 0 , len ); 438769Speter # endif PC 439769Speter } while (next = next->chain); 440769Speter /* list of scalar names */ 441769Speter strptr = getnext(ap, &next); 442769Speter # ifdef OBJ 443769Speter do { 444769Speter w = (unsigned) *strptr; 445769Speter if (!*strptr++) 446769Speter strptr = getnext(next, &next); 447769Speter w |= *strptr << 8; 448769Speter if (!*strptr++) 449769Speter strptr = getnext(next, &next); 450769Speter word(w); 451769Speter } while (next); 452769Speter /* jump over the mess */ 453769Speter patch(oldlc); 454769Speter # endif OBJ 455769Speter # ifdef PC 456769Speter while ( next ) { 457769Speter while ( *strptr ) { 458769Speter putprintf( " .byte 0%o" , 1 , *strptr++ ); 459769Speter for ( w = 2 ; ( w <= 8 ) && *strptr ; w ++ ) { 460769Speter putprintf( ",0%o" , 1 , *strptr++ ); 461769Speter } 462769Speter putprintf( "" , 0 ); 463769Speter } 464769Speter putprintf( " .byte 0" , 0 ); 465769Speter strptr = getnext( next , &next ); 466769Speter } 467769Speter putprintf( " .text" , 0 ); 468769Speter # endif PC 469769Speter return( ap -> value[ NL_ELABEL ] ); 470769Speter } 471769Speter 472769Speter getnext(next, new) 473769Speter 474769Speter struct nl *next, **new; 475769Speter { 476769Speter if (next != NIL) { 477769Speter next = next->chain; 478769Speter *new = next; 479769Speter } 480769Speter if (next == NIL) 481769Speter return(""); 482769Speter #ifdef OBJ 483769Speter if (opt('k') && cgenflg >= 0) 484769Speter printf(")#%5d\t\t\"%s\"\n", lc-HEADER_BYTES, next->symbol); 4852213Speter #endif OBJ 486769Speter return(next->symbol); 487769Speter } 488769Speter 489769Speter #ifdef OBJ 490769Speter /* 491769Speter * Putspace puts out a table 492769Speter * of nothing to leave space 493769Speter * for the case branch table e.g. 494769Speter */ 495769Speter putspace(n) 496769Speter int n; 497769Speter { 498769Speter register i; 499769Speter 500769Speter if (cgenflg < 0) 501769Speter /* 502769Speter * code disabled - do nothing 503769Speter */ 504769Speter return(lc); 505769Speter #ifdef DEBUG 506769Speter if (opt('k')) 507769Speter printf(")#%5d\t.=.+%d\n", lc - HEADER_BYTES, n); 508769Speter #endif 509769Speter for (i = even(n); i > 0; i -= 2) 510769Speter word(0); 511769Speter } 512769Speter 513769Speter putstr(sptr, padding) 514769Speter 515769Speter char *sptr; 516769Speter int padding; 517769Speter { 518769Speter register unsigned short w; 519769Speter register char *strptr = sptr; 520769Speter register int pad = padding; 521769Speter 522769Speter if (cgenflg < 0) 523769Speter /* 524769Speter * code disabled - do nothing 525769Speter */ 526769Speter return(lc); 527769Speter #ifdef DEBUG 528769Speter if (opt('k')) 529769Speter printf(")#%5D\t\t\"%s\"\n", lc-HEADER_BYTES, strptr); 530769Speter #endif 531769Speter if (pad == 0) { 532769Speter do { 533769Speter w = (unsigned short) * strptr; 534769Speter if (w) 535769Speter w |= *++strptr << 8; 536769Speter word(w); 537769Speter } while (*strptr++); 538769Speter } else { 539769Speter do { 540769Speter w = (unsigned short) * strptr; 541769Speter if (w) { 542769Speter if (*++strptr) 543769Speter w |= *strptr << 8; 544769Speter else { 545769Speter w |= ' ' << 8; 546769Speter pad--; 547769Speter } 548769Speter word(w); 549769Speter } 550769Speter } while (*strptr++); 551769Speter while (pad > 1) { 552769Speter word(' '); 553769Speter pad -= 2; 554769Speter } 555769Speter if (pad == 1) 556769Speter word(' '); 557769Speter else 558769Speter word(0); 559769Speter } 560769Speter } 561769Speter #endif OBJ 562769Speter 563769Speter lenstr(sptr, padding) 564769Speter 565769Speter char *sptr; 566769Speter int padding; 567769Speter 568769Speter { 569769Speter register int cnt; 570769Speter register char *strptr = sptr; 571769Speter 572769Speter cnt = padding; 573769Speter do { 574769Speter cnt++; 575769Speter } while (*strptr++); 576769Speter return((++cnt) & ~1); 577769Speter } 578769Speter 579769Speter /* 580769Speter * Patch repairs the branch 581769Speter * at location loc to come 582769Speter * to the current location. 583769Speter * for PC, this puts down the label 584769Speter * and the branch just references that label. 585769Speter * lets here it for two pass assemblers. 586769Speter */ 587769Speter patch(loc) 588769Speter { 589769Speter 590769Speter # ifdef OBJ 591769Speter patchfil(loc, lc-loc-2, 1); 592769Speter # endif OBJ 593769Speter # ifdef PC 594769Speter putlab( loc ); 595769Speter # endif PC 596769Speter } 597769Speter 598769Speter #ifdef OBJ 599769Speter patch4(loc) 600769Speter { 601769Speter 602769Speter patchfil(loc, lc - HEADER_BYTES, 2); 603769Speter } 604769Speter 605769Speter /* 606769Speter * Patchfil makes loc+2 have value 607769Speter * as its contents. 608769Speter */ 609769Speter patchfil(loc, value, words) 610769Speter PTR_DCL loc; 611769Speter int value, words; 612769Speter { 613769Speter register i; 614769Speter 615769Speter if (cgenflg < 0) 616769Speter return; 617769Speter if (loc > (unsigned) lc) 618769Speter panic("patchfil"); 619769Speter #ifdef DEBUG 620769Speter if (opt('k')) 621769Speter printf(")#\tpatch %u %d\n", loc - HEADER_BYTES, value); 622769Speter #endif 623769Speter do { 624769Speter i = ((unsigned) loc + 2 - ((unsigned) lc & ~01777))/2; 625769Speter if (i >= 0 && i < 1024) 626769Speter obuf[i] = value; 627769Speter else { 628769Speter lseek(ofil, (long) loc+2, 0); 629769Speter write(ofil, &value, 2); 630769Speter lseek(ofil, (long) 0, 2); 631769Speter } 632769Speter loc += 2; 633769Speter value = value >> 16; 634769Speter } while (--words); 635769Speter } 636769Speter 637769Speter /* 638769Speter * Put the word o into the code 639769Speter */ 640769Speter word(o) 641769Speter int o; 642769Speter { 643769Speter 644769Speter *obufp = o; 645769Speter obufp++; 646769Speter lc += 2; 647769Speter if (obufp >= obuf+512) 648769Speter pflush(); 649769Speter } 650769Speter 651769Speter extern char *obj; 652769Speter /* 653769Speter * Flush the code buffer 654769Speter */ 655769Speter pflush() 656769Speter { 657769Speter register i; 658769Speter 659769Speter i = (obufp - ( ( short * ) obuf ) ) * 2; 660769Speter if (i != 0 && write(ofil, obuf, i) != i) 661769Speter perror(obj), pexit(DIED); 662769Speter obufp = obuf; 663769Speter } 664769Speter #endif OBJ 665769Speter 666769Speter /* 667769Speter * Getlab - returns the location counter. 668769Speter * included here for the eventual code generator. 669769Speter * for PC, thank you! 670769Speter */ 671769Speter getlab() 672769Speter { 673769Speter # ifdef OBJ 674769Speter 675769Speter return (lc); 676769Speter # endif OBJ 677769Speter # ifdef PC 678769Speter static long lastlabel; 679769Speter 680769Speter return ( ++lastlabel ); 681769Speter # endif PC 682769Speter } 683769Speter 684769Speter /* 685769Speter * Putlab - lay down a label. 686769Speter * for PC, just print the label name with a colon after it. 687769Speter */ 688769Speter putlab(l) 689769Speter int l; 690769Speter { 691769Speter 692769Speter # ifdef PC 693769Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , l ); 694769Speter putprintf( ":" , 0 ); 695769Speter # endif PC 696769Speter return (l); 697769Speter } 698769Speter 699