1*769Speter /* Copyright (c) 1979 Regents of the University of California */ 2*769Speter 3*769Speter static char sccsid[] = "@(#)put.c 1.1 08/27/80"; 4*769Speter 5*769Speter #include "whoami.h" 6*769Speter #include "opcode.h" 7*769Speter #include "0.h" 8*769Speter #include "objfmt.h" 9*769Speter #ifdef PC 10*769Speter # include "pc.h" 11*769Speter #endif PC 12*769Speter 13*769Speter short *obufp = obuf; 14*769Speter 15*769Speter /* 16*769Speter * If DEBUG is defined, include the table 17*769Speter * of the printing opcode names. 18*769Speter */ 19*769Speter #ifdef DEBUG 20*769Speter #include "OPnames.h" 21*769Speter #endif 22*769Speter 23*769Speter #ifdef OBJ 24*769Speter /* 25*769Speter * Put is responsible for the interpreter equivalent of code 26*769Speter * generation. Since the interpreter is specifically designed 27*769Speter * for Pascal, little work is required here. 28*769Speter */ 29*769Speter put(a) 30*769Speter { 31*769Speter register int *p, i; 32*769Speter register char *cp; 33*769Speter int n, subop, suboppr, op, oldlc, w; 34*769Speter char *string; 35*769Speter static int casewrd; 36*769Speter 37*769Speter /* 38*769Speter * It would be nice to do some more 39*769Speter * optimizations here. The work 40*769Speter * done to collapse offsets in lval 41*769Speter * should be done here, the IFEQ etc 42*769Speter * relational operators could be used 43*769Speter * etc. 44*769Speter */ 45*769Speter oldlc = lc; 46*769Speter if (cgenflg < 0) 47*769Speter /* 48*769Speter * code disabled - do nothing 49*769Speter */ 50*769Speter return (oldlc); 51*769Speter p = &a; 52*769Speter n = *p++; 53*769Speter suboppr = subop = (*p>>8) & 0377; 54*769Speter op = *p & 0377; 55*769Speter string = 0; 56*769Speter #ifdef DEBUG 57*769Speter if ((cp = otext[op]) == NIL) { 58*769Speter printf("op= %o\n", op); 59*769Speter panic("put"); 60*769Speter } 61*769Speter #endif 62*769Speter switch (op) { 63*769Speter case O_ABORT: 64*769Speter cp = "*"; 65*769Speter break; 66*769Speter case O_LINO: 67*769Speter /***** 68*769Speter if (line == codeline) 69*769Speter return (oldlc); 70*769Speter codeline = line; 71*769Speter *****/ 72*769Speter case O_NEW: 73*769Speter case O_DISPOSE: 74*769Speter case O_AS: 75*769Speter case O_IND: 76*769Speter case O_LVCON: 77*769Speter case O_CON: 78*769Speter case O_OFF: 79*769Speter case O_INX2: 80*769Speter case O_INX4: 81*769Speter case O_CARD: 82*769Speter case O_ADDT: 83*769Speter case O_SUBT: 84*769Speter case O_MULT: 85*769Speter case O_IN: 86*769Speter case O_CASE1OP: 87*769Speter case O_CASE2OP: 88*769Speter case O_CASE4OP: 89*769Speter case O_WRITES: 90*769Speter case O_WRITEF: 91*769Speter case O_MAX: 92*769Speter case O_MIN: 93*769Speter case O_PACK: 94*769Speter case O_UNPACK: 95*769Speter case O_ARGV: 96*769Speter case O_CTTOT: 97*769Speter case O_INCT: 98*769Speter case O_RANG2: 99*769Speter case O_RSNG2: 100*769Speter case O_RANG42: 101*769Speter case O_RSNG42: 102*769Speter if (p[1] == 0) 103*769Speter break; 104*769Speter case O_CON2: 105*769Speter case O_CON24: 106*769Speter if (p[1] < 128 && p[1] >= -128) { 107*769Speter suboppr = subop = p[1]; 108*769Speter p++; 109*769Speter n--; 110*769Speter if (op == O_CON2) { 111*769Speter op = O_CON1; 112*769Speter cp = otext[O_CON1]; 113*769Speter } 114*769Speter if (op == O_CON24) { 115*769Speter op = O_CON14; 116*769Speter cp = otext[O_CON14]; 117*769Speter } 118*769Speter } 119*769Speter break; 120*769Speter case O_CON8: 121*769Speter { 122*769Speter short *sp = &p[1]; 123*769Speter 124*769Speter #ifdef DEBUG 125*769Speter if ( opt( 'k' ) ) 126*769Speter printf ( ")#%5d\tCON8\t%10.3f\n" , 127*769Speter lc - HEADER_BYTES , 128*769Speter * ( ( double * ) &p[1] ) ); 129*769Speter #endif 130*769Speter word ( op ); 131*769Speter for ( i = 1 ; i <= 4 ; i ++ ) 132*769Speter word ( *sp ++ ); 133*769Speter return ( oldlc ); 134*769Speter } 135*769Speter default: 136*769Speter if (op >= O_REL2 && op <= O_REL84) { 137*769Speter if ((i = (subop >> 1) * 5 ) >= 30) 138*769Speter i -= 30; 139*769Speter else 140*769Speter i += 2; 141*769Speter #ifdef DEBUG 142*769Speter string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i]; 143*769Speter #endif 144*769Speter suboppr = 0; 145*769Speter } 146*769Speter break; 147*769Speter case O_IF: 148*769Speter case O_TRA: 149*769Speter /***** 150*769Speter codeline = 0; 151*769Speter *****/ 152*769Speter case O_FOR1U: 153*769Speter case O_FOR2U: 154*769Speter case O_FOR4U: 155*769Speter case O_FOR1D: 156*769Speter case O_FOR2D: 157*769Speter case O_FOR4D: 158*769Speter /* relative addressing */ 159*769Speter p[1] -= ( unsigned ) lc + 2; 160*769Speter break; 161*769Speter case O_CONG: 162*769Speter i = p[1]; 163*769Speter cp = * ( ( char ** ) &p[2] ) ; 164*769Speter #ifdef DEBUG 165*769Speter if (opt('k')) 166*769Speter printf(")#%5d\tCONG:%d\t%s\n", 167*769Speter lc - HEADER_BYTES, i, cp); 168*769Speter #endif 169*769Speter if (i <= 127) 170*769Speter word(O_CON | i << 8); 171*769Speter else { 172*769Speter word(O_CON); 173*769Speter word(i); 174*769Speter } 175*769Speter while (i > 0) { 176*769Speter w = *cp ? *cp++ : ' '; 177*769Speter w |= (*cp ? *cp++ : ' ') << 8; 178*769Speter word(w); 179*769Speter i -= 2; 180*769Speter } 181*769Speter return (oldlc); 182*769Speter case O_CONC: 183*769Speter #ifdef DEBUG 184*769Speter (string = "'x'")[1] = p[1]; 185*769Speter #endif 186*769Speter suboppr = 0; 187*769Speter op = O_CON1; 188*769Speter cp = otext[O_CON1]; 189*769Speter subop = p[1]; 190*769Speter goto around; 191*769Speter case O_CONC4: 192*769Speter #ifdef DEBUG 193*769Speter (string = "'x'")[1] = p[1]; 194*769Speter #endif 195*769Speter suboppr = 0; 196*769Speter op = O_CON14; 197*769Speter subop = p[1]; 198*769Speter goto around; 199*769Speter case O_CON1: 200*769Speter case O_CON14: 201*769Speter suboppr = subop = p[1]; 202*769Speter around: 203*769Speter n--; 204*769Speter break; 205*769Speter case O_CASEBEG: 206*769Speter casewrd = 0; 207*769Speter return (oldlc); 208*769Speter case O_CASEEND: 209*769Speter if ((unsigned) lc & 1) { 210*769Speter lc--; 211*769Speter word(casewrd); 212*769Speter } 213*769Speter return (oldlc); 214*769Speter case O_CASE1: 215*769Speter #ifdef DEBUG 216*769Speter if (opt('k')) 217*769Speter printf(")#%5d\tCASE1\t%d\n" 218*769Speter , lc - HEADER_BYTES 219*769Speter , ( int ) *( ( long * ) &p[1] ) ); 220*769Speter #endif 221*769Speter /* 222*769Speter * this to build a byte size case table 223*769Speter * saving bytes across calls in casewrd 224*769Speter * so they can be put out by word() 225*769Speter */ 226*769Speter lc++; 227*769Speter if ((unsigned) lc & 1) 228*769Speter casewrd = *( ( long * ) &p[1] ); 229*769Speter else { 230*769Speter lc -= 2; 231*769Speter word ( casewrd 232*769Speter | ( ( int ) *( ( long * ) &p[1] ) << 8 ) ); 233*769Speter } 234*769Speter return (oldlc); 235*769Speter case O_CASE2: 236*769Speter #ifdef DEBUG 237*769Speter if (opt('k')) 238*769Speter printf(")#%5d\tCASE2\t%d\n" 239*769Speter , lc - HEADER_BYTES 240*769Speter , ( int ) *( ( long * ) &p[1] ) ); 241*769Speter #endif 242*769Speter word( ( short ) *( ( long * ) &p[1] ) ); 243*769Speter return (oldlc); 244*769Speter case O_POP: 245*769Speter case O_PUSH: 246*769Speter if (p[1] == 0) 247*769Speter return (oldlc); 248*769Speter if (p[1] < 128 && p[1] >= -128) { 249*769Speter suboppr = subop = p[1]; 250*769Speter p++; 251*769Speter n--; 252*769Speter break; 253*769Speter } 254*769Speter goto longgen; 255*769Speter case O_TRA4: 256*769Speter case O_CALL: 257*769Speter case O_GOTO: 258*769Speter case O_TRACNT: 259*769Speter case O_NAM: 260*769Speter case O_READE: 261*769Speter /* absolute long addressing */ 262*769Speter p[1] -= HEADER_BYTES; 263*769Speter goto longgen; 264*769Speter case O_RV1: 265*769Speter case O_RV14: 266*769Speter case O_RV2: 267*769Speter case O_RV24: 268*769Speter case O_RV4: 269*769Speter case O_RV8: 270*769Speter case O_RV: 271*769Speter case O_LV: 272*769Speter if (p[1] < SHORTADDR && p[1] >= -SHORTADDR) 273*769Speter break; 274*769Speter else { 275*769Speter op += O_LRV - O_RV; 276*769Speter cp = otext[op]; 277*769Speter } 278*769Speter case O_BEG: 279*769Speter case O_NODUMP: 280*769Speter case O_CON4: 281*769Speter case O_CASE4: 282*769Speter case O_RANG4: 283*769Speter case O_RANG24: 284*769Speter case O_RSNG4: 285*769Speter case O_RSNG24: 286*769Speter longgen: 287*769Speter { 288*769Speter short *sp = &p[1]; 289*769Speter long *lp = &p[1]; 290*769Speter 291*769Speter n = (n << 1) - 1; 292*769Speter if ( op == O_LRV ) 293*769Speter n--; 294*769Speter #ifdef DEBUG 295*769Speter if (opt('k')) 296*769Speter { 297*769Speter printf( ")#%5d\t%s" , lc - HEADER_BYTES , cp+1 ); 298*769Speter if (suboppr) 299*769Speter printf(":%1d", suboppr); 300*769Speter for ( i = 1 ; i < n 301*769Speter ; i += sizeof ( long )/sizeof ( short ) ) 302*769Speter printf( "\t%D " , *lp ++ ); 303*769Speter pchr ( '\n' ); 304*769Speter } 305*769Speter #endif 306*769Speter if ( op != O_CASE4 ) 307*769Speter word ( op | subop<<8 ); 308*769Speter for ( i = 1 ; i < n ; i ++ ) 309*769Speter word ( *sp ++ ); 310*769Speter return ( oldlc ); 311*769Speter } 312*769Speter } 313*769Speter #ifdef DEBUG 314*769Speter if (opt('k')) { 315*769Speter printf(")#%5d\t%s", lc - HEADER_BYTES, cp+1); 316*769Speter if (suboppr) 317*769Speter printf(":%d", suboppr); 318*769Speter if (string) 319*769Speter printf("\t%s",string); 320*769Speter if (n > 1) 321*769Speter pchr('\t'); 322*769Speter for (i=1; i<n; i++) 323*769Speter printf("%d ", ( short ) p[i]); 324*769Speter pchr('\n'); 325*769Speter } 326*769Speter #endif 327*769Speter if (op != NIL) 328*769Speter word(op | subop << 8); 329*769Speter for (i=1; i<n; i++) 330*769Speter word(p[i]); 331*769Speter return (oldlc); 332*769Speter } 333*769Speter #endif OBJ 334*769Speter 335*769Speter /* 336*769Speter * listnames outputs a list of enumerated type names which 337*769Speter * can then be selected from to output a TSCAL 338*769Speter * a pointer to the address in the code of the namelist 339*769Speter * is kept in value[ NL_ELABEL ]. 340*769Speter */ 341*769Speter listnames(ap) 342*769Speter 343*769Speter register struct nl *ap; 344*769Speter { 345*769Speter struct nl *next; 346*769Speter register int oldlc, len; 347*769Speter register unsigned w; 348*769Speter register char *strptr; 349*769Speter 350*769Speter if (cgenflg < 0) 351*769Speter /* code is off - do nothing */ 352*769Speter return(NIL); 353*769Speter if (ap->class != TYPE) 354*769Speter ap = ap->type; 355*769Speter if (ap->value[ NL_ELABEL ] != 0) { 356*769Speter /* the list already exists */ 357*769Speter return( ap -> value[ NL_ELABEL ] ); 358*769Speter } 359*769Speter # ifdef OBJ 360*769Speter oldlc = lc; 361*769Speter put(2, O_TRA, lc); 362*769Speter ap->value[ NL_ELABEL ] = lc; 363*769Speter # endif OBJ 364*769Speter # ifdef PC 365*769Speter putprintf( " .data" , 0 ); 366*769Speter putprintf( " .align 1" , 0 ); 367*769Speter ap -> value[ NL_ELABEL ] = getlab(); 368*769Speter putlab( ap -> value[ NL_ELABEL ] ); 369*769Speter # endif PC 370*769Speter /* number of scalars */ 371*769Speter next = ap->type; 372*769Speter len = next->range[1]-next->range[0]+1; 373*769Speter # ifdef OBJ 374*769Speter put(2, O_CASE2, len); 375*769Speter # endif OBJ 376*769Speter # ifdef PC 377*769Speter putprintf( " .word %d" , 0 , len ); 378*769Speter # endif PC 379*769Speter /* offsets of each scalar name */ 380*769Speter len = (len+1)*sizeof(short); 381*769Speter # ifdef OBJ 382*769Speter put(2, O_CASE2, len); 383*769Speter # endif OBJ 384*769Speter # ifdef PC 385*769Speter putprintf( " .word %d" , 0 , len ); 386*769Speter # endif PC 387*769Speter next = ap->chain; 388*769Speter do { 389*769Speter for(strptr = next->symbol; *strptr++; len++) 390*769Speter continue; 391*769Speter len++; 392*769Speter # ifdef OBJ 393*769Speter put(2, O_CASE2, len); 394*769Speter # endif OBJ 395*769Speter # ifdef PC 396*769Speter putprintf( " .word %d" , 0 , len ); 397*769Speter # endif PC 398*769Speter } while (next = next->chain); 399*769Speter /* list of scalar names */ 400*769Speter strptr = getnext(ap, &next); 401*769Speter # ifdef OBJ 402*769Speter do { 403*769Speter w = (unsigned) *strptr; 404*769Speter if (!*strptr++) 405*769Speter strptr = getnext(next, &next); 406*769Speter w |= *strptr << 8; 407*769Speter if (!*strptr++) 408*769Speter strptr = getnext(next, &next); 409*769Speter word(w); 410*769Speter } while (next); 411*769Speter /* jump over the mess */ 412*769Speter patch(oldlc); 413*769Speter # endif OBJ 414*769Speter # ifdef PC 415*769Speter while ( next ) { 416*769Speter while ( *strptr ) { 417*769Speter putprintf( " .byte 0%o" , 1 , *strptr++ ); 418*769Speter for ( w = 2 ; ( w <= 8 ) && *strptr ; w ++ ) { 419*769Speter putprintf( ",0%o" , 1 , *strptr++ ); 420*769Speter } 421*769Speter putprintf( "" , 0 ); 422*769Speter } 423*769Speter putprintf( " .byte 0" , 0 ); 424*769Speter strptr = getnext( next , &next ); 425*769Speter } 426*769Speter putprintf( " .text" , 0 ); 427*769Speter # endif PC 428*769Speter return( ap -> value[ NL_ELABEL ] ); 429*769Speter } 430*769Speter 431*769Speter getnext(next, new) 432*769Speter 433*769Speter struct nl *next, **new; 434*769Speter { 435*769Speter if (next != NIL) { 436*769Speter next = next->chain; 437*769Speter *new = next; 438*769Speter } 439*769Speter if (next == NIL) 440*769Speter return(""); 441*769Speter #ifdef OBJ 442*769Speter if (opt('k') && cgenflg >= 0) 443*769Speter printf(")#%5d\t\t\"%s\"\n", lc-HEADER_BYTES, next->symbol); 444*769Speter #endif 445*769Speter return(next->symbol); 446*769Speter } 447*769Speter 448*769Speter #ifdef OBJ 449*769Speter /* 450*769Speter * Putspace puts out a table 451*769Speter * of nothing to leave space 452*769Speter * for the case branch table e.g. 453*769Speter */ 454*769Speter putspace(n) 455*769Speter int n; 456*769Speter { 457*769Speter register i; 458*769Speter 459*769Speter if (cgenflg < 0) 460*769Speter /* 461*769Speter * code disabled - do nothing 462*769Speter */ 463*769Speter return(lc); 464*769Speter #ifdef DEBUG 465*769Speter if (opt('k')) 466*769Speter printf(")#%5d\t.=.+%d\n", lc - HEADER_BYTES, n); 467*769Speter #endif 468*769Speter for (i = even(n); i > 0; i -= 2) 469*769Speter word(0); 470*769Speter } 471*769Speter 472*769Speter putstr(sptr, padding) 473*769Speter 474*769Speter char *sptr; 475*769Speter int padding; 476*769Speter { 477*769Speter register unsigned short w; 478*769Speter register char *strptr = sptr; 479*769Speter register int pad = padding; 480*769Speter 481*769Speter if (cgenflg < 0) 482*769Speter /* 483*769Speter * code disabled - do nothing 484*769Speter */ 485*769Speter return(lc); 486*769Speter #ifdef DEBUG 487*769Speter if (opt('k')) 488*769Speter printf(")#%5D\t\t\"%s\"\n", lc-HEADER_BYTES, strptr); 489*769Speter #endif 490*769Speter if (pad == 0) { 491*769Speter do { 492*769Speter w = (unsigned short) * strptr; 493*769Speter if (w) 494*769Speter w |= *++strptr << 8; 495*769Speter word(w); 496*769Speter } while (*strptr++); 497*769Speter } else { 498*769Speter do { 499*769Speter w = (unsigned short) * strptr; 500*769Speter if (w) { 501*769Speter if (*++strptr) 502*769Speter w |= *strptr << 8; 503*769Speter else { 504*769Speter w |= ' ' << 8; 505*769Speter pad--; 506*769Speter } 507*769Speter word(w); 508*769Speter } 509*769Speter } while (*strptr++); 510*769Speter while (pad > 1) { 511*769Speter word(' '); 512*769Speter pad -= 2; 513*769Speter } 514*769Speter if (pad == 1) 515*769Speter word(' '); 516*769Speter else 517*769Speter word(0); 518*769Speter } 519*769Speter } 520*769Speter #endif OBJ 521*769Speter 522*769Speter lenstr(sptr, padding) 523*769Speter 524*769Speter char *sptr; 525*769Speter int padding; 526*769Speter 527*769Speter { 528*769Speter register int cnt; 529*769Speter register char *strptr = sptr; 530*769Speter 531*769Speter cnt = padding; 532*769Speter do { 533*769Speter cnt++; 534*769Speter } while (*strptr++); 535*769Speter return((++cnt) & ~1); 536*769Speter } 537*769Speter 538*769Speter /* 539*769Speter * Patch repairs the branch 540*769Speter * at location loc to come 541*769Speter * to the current location. 542*769Speter * for PC, this puts down the label 543*769Speter * and the branch just references that label. 544*769Speter * lets here it for two pass assemblers. 545*769Speter */ 546*769Speter patch(loc) 547*769Speter { 548*769Speter 549*769Speter # ifdef OBJ 550*769Speter patchfil(loc, lc-loc-2, 1); 551*769Speter # endif OBJ 552*769Speter # ifdef PC 553*769Speter putlab( loc ); 554*769Speter # endif PC 555*769Speter } 556*769Speter 557*769Speter #ifdef OBJ 558*769Speter patch4(loc) 559*769Speter { 560*769Speter 561*769Speter patchfil(loc, lc - HEADER_BYTES, 2); 562*769Speter } 563*769Speter 564*769Speter /* 565*769Speter * Patchfil makes loc+2 have value 566*769Speter * as its contents. 567*769Speter */ 568*769Speter patchfil(loc, value, words) 569*769Speter PTR_DCL loc; 570*769Speter int value, words; 571*769Speter { 572*769Speter register i; 573*769Speter 574*769Speter if (cgenflg < 0) 575*769Speter return; 576*769Speter if (loc > (unsigned) lc) 577*769Speter panic("patchfil"); 578*769Speter #ifdef DEBUG 579*769Speter if (opt('k')) 580*769Speter printf(")#\tpatch %u %d\n", loc - HEADER_BYTES, value); 581*769Speter #endif 582*769Speter do { 583*769Speter i = ((unsigned) loc + 2 - ((unsigned) lc & ~01777))/2; 584*769Speter if (i >= 0 && i < 1024) 585*769Speter obuf[i] = value; 586*769Speter else { 587*769Speter lseek(ofil, (long) loc+2, 0); 588*769Speter write(ofil, &value, 2); 589*769Speter lseek(ofil, (long) 0, 2); 590*769Speter } 591*769Speter loc += 2; 592*769Speter value = value >> 16; 593*769Speter } while (--words); 594*769Speter } 595*769Speter 596*769Speter /* 597*769Speter * Put the word o into the code 598*769Speter */ 599*769Speter word(o) 600*769Speter int o; 601*769Speter { 602*769Speter 603*769Speter *obufp = o; 604*769Speter obufp++; 605*769Speter lc += 2; 606*769Speter if (obufp >= obuf+512) 607*769Speter pflush(); 608*769Speter } 609*769Speter 610*769Speter extern char *obj; 611*769Speter /* 612*769Speter * Flush the code buffer 613*769Speter */ 614*769Speter pflush() 615*769Speter { 616*769Speter register i; 617*769Speter 618*769Speter i = (obufp - ( ( short * ) obuf ) ) * 2; 619*769Speter if (i != 0 && write(ofil, obuf, i) != i) 620*769Speter perror(obj), pexit(DIED); 621*769Speter obufp = obuf; 622*769Speter } 623*769Speter #endif OBJ 624*769Speter 625*769Speter /* 626*769Speter * Getlab - returns the location counter. 627*769Speter * included here for the eventual code generator. 628*769Speter * for PC, thank you! 629*769Speter */ 630*769Speter getlab() 631*769Speter { 632*769Speter # ifdef OBJ 633*769Speter 634*769Speter return (lc); 635*769Speter # endif OBJ 636*769Speter # ifdef PC 637*769Speter static long lastlabel; 638*769Speter 639*769Speter return ( ++lastlabel ); 640*769Speter # endif PC 641*769Speter } 642*769Speter 643*769Speter /* 644*769Speter * Putlab - lay down a label. 645*769Speter * for PC, just print the label name with a colon after it. 646*769Speter */ 647*769Speter putlab(l) 648*769Speter int l; 649*769Speter { 650*769Speter 651*769Speter # ifdef PC 652*769Speter putprintf( PREFIXFORMAT , 1 , LABELPREFIX , l ); 653*769Speter putprintf( ":" , 0 ); 654*769Speter # endif PC 655*769Speter return (l); 656*769Speter } 657*769Speter 658