|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)operand.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: #include "as.h" ! 10: #include <ctype.h> ! 11: ! 12: short cinfo[128] = { ! 13: ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ! 14: ERR, SPC, EOL, SPC, SPC, SPC, ERR, ERR, ! 15: ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ! 16: ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ! 17: SPC, ERR, QUO, IMM, S+T, ERR, ERR, ERR, ! 18: LP, RP, MUL, ADD, COM, SUB, S+T, DIV, ! 19: D+T, D+T, D+T, D+T, D+T, D+T, D+T, D+T, ! 20: D+T, D+T, COL, EOL, ERR, EQL, ERR, ERR, ! 21: IND, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 22: S+T, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 23: S+T, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 24: S+T, S+T, S+T, ERR, ERR, ERR, ERR, S+T, ! 25: ERR, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 26: S+T, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 27: S+T, S+T, S+T, S+T, S+T, S+T, S+T, S+T, ! 28: S+T, S+T, S+T, LB, EOL, RB, NOT, S+T ! 29: }; ! 30: ! 31: /* for local labels: ``[0-9]:'', and references ``[0-9][bh]'' */ ! 32: char *ll_format = "*%c%06d"; ! 33: int ll_val[10]; ! 34: ! 35: static struct suffix { ! 36: int indx_sx; /* index register */ ! 37: int scale_sx; /* index scaling */ ! 38: long disp_sx; /* displacement */ ! 39: struct sym_bkt *sym_sx; /* symbolic displacement */ ! 40: unsigned flags_sx; /* see below */ ! 41: } fix [2]; ! 42: ! 43: static struct suffix zero_suffix = { 0 }; ! 44: ! 45: /* flags_sx values */ ! 46: #define SX_INDXW 1 /* word-size index specified */ ! 47: #define SX_INDXL 2 /* long-size index specified */ ! 48: #define SX_DISPW 4 /* word-size displacement specified */ ! 49: #define SX_DISPL 010 /* long-size displacement specified */ ! 50: #define SX_GOTINDEX 020 /* index register specified */ ! 51: #define SX_GOTDISP 040 /* displacement specified */ ! 52: #define SX_DISPB 0100 /* word-size displacement specified */ ! 53: ! 54: static struct oper zero_oper = { T_NULL }; ! 55: ! 56: char *suffix(), *exp(), *term(), *scan_reg_or_immed(); ! 57: char * scan_float(); ! 58: double atof(); ! 59: char * reglist () ; ! 60: ! 61: /* ! 62: * Fetches operand value and register subfields and loads them into ! 63: * the operand structure. This routine will fetch only one set of value ! 64: * and register subfields. ! 65: * It will move line pointer to first untouched char. ! 66: */ ! 67: char * ! 68: soperand(lptr,opnd) ! 69: register char *lptr; ! 70: struct oper *opnd; ! 71: { ! 72: struct oper spare_oper; ! 73: int v; ! 74: ! 75: *opnd = zero_oper; ! 76: spare_oper = zero_oper; ! 77: ! 78: if ((v=cinfo[*lptr]) == IMM) { ! 79: lptr = exp(++lptr,opnd); ! 80: if (opnd->type_o == T_REG) ! 81: PROG_ERROR(E_REG); ! 82: opnd->immed_o = opnd->type_o ; /* Save type. */ ! 83: opnd->type_o = T_IMMED; ! 84: } else if (v == IND) { ! 85: /* index mode, omitted base */ ! 86: /* expecting LP next */ ! 87: lptr += 1; ! 88: skipb(lptr); ! 89: if (cinfo[*lptr] == LP) ! 90: goto index_mode; ! 91: else ! 92: PROG_ERROR(E_OPERAND); ! 93: } else { ! 94: lptr = exp(lptr,opnd); ! 95: skipb(lptr); ! 96: switch (opnd->type_o){ ! 97: case T_REG: ! 98: switch (cinfo[*lptr]){ ! 99: case COL: ! 100: /* should be a register pair */ ! 101: lptr = exp( ++lptr, &spare_oper); ! 102: if (spare_oper.type_o != T_REG) ! 103: PROG_ERROR(E_OPERAND); ! 104: if (!ext_instruction_set) ! 105: PROG_ERROR( E_OPERAND ); ! 106: opnd->type_o = T_REGPAIR; ! 107: opnd->reg_o = spare_oper.value_o; ! 108: break; ! 109: case IND: ! 110: if (!(areg(opnd->value_o) ! 111: || pcreg(opnd->value_o))) ! 112: PROG_ERROR(E_OPERAND); ! 113: lptr += 1; ! 114: skipb(lptr); ! 115: switch (cinfo[*lptr]){ ! 116: default: ! 117: opnd->type_o = T_DEFER; ! 118: break; ! 119: case ADD: ! 120: opnd->type_o = T_POSTINC; ! 121: lptr++; ! 122: break; ! 123: case SUB: ! 124: opnd->type_o = T_PREDEC; ! 125: lptr++; ! 126: break; ! 127: case LP: ! 128: /* defer or indexing coming up here */ ! 129: index_mode: ! 130: lptr = suffix( lptr, &fix[0] ); ! 131: if (cinfo[*lptr] != IND){ ! 132: simplify1( opnd, &fix[0] ); ! 133: } else { ! 134: lptr = suffix( ++lptr, &fix[1] ); ! 135: simplify2( opnd, &fix[0], &fix[1] ); ! 136: } ! 137: break; ! 138: case IND: ! 139: lptr = suffix( ++lptr, &fix[1] ); ! 140: simplify2( opnd, &zero_suffix, ! 141: &fix[1] ); ! 142: break; ! 143: } ! 144: if (opnd->type_o == T_INDEX ! 145: && !ext_instruction_set) ! 146: if ( (opnd->flags_o & ! 147: (O_BSUPRESS|O_INDIRECT|O_WDISP|O_LDISP)) ! 148: || opnd->scale_o != 1 ! 149: || !(opnd->flags_o&O_PREINDEX)) ! 150: PROG_ERROR( E_OPERAND ); ! 151: /* flow through */ ! 152: default: ! 153: break; ! 154: } ! 155: break; ! 156: case T_NORMAL: ! 157: if (cinfo[*lptr] == COL ){ ! 158: switch (*++lptr) { ! 159: case 'W': ! 160: case 'w': opnd->type_o = T_ABSS; ! 161: lptr++; ! 162: break; ! 163: case 'L': ! 164: case 'l': opnd->type_o = T_ABSL; ! 165: lptr++; ! 166: break; ! 167: } ! 168: } ! 169: if (cinfo[*lptr] == IND) ! 170: goto index_mode; ! 171: break; ! 172: } ! 173: } ! 174: skipb( lptr ); ! 175: if ( cinfo[ *lptr ] == LB ) { ! 176: /* oh, boy, bitfields */ ! 177: opnd->flags_o |= O_BFLD; ! 178: spare_oper = zero_oper; ! 179: lptr = scan_reg_or_immed( lptr+1, &spare_oper); ! 180: v = spare_oper.value_o; ! 181: if (spare_oper.type_o == T_REG){ ! 182: opnd->flags_o |= O_BFOREG; ! 183: } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) ! 184: || v < 0 || v > 31){ ! 185: PROG_ERROR(E_CONSTANT); ! 186: } ! 187: opnd->bfoffset_o = v; ! 188: skipb( lptr ); ! 189: if ( cinfo[ *lptr ] == COL) ! 190: lptr ++; ! 191: else ! 192: PROG_ERROR(E_OPERAND); ! 193: spare_oper = zero_oper; ! 194: lptr = scan_reg_or_immed( lptr, &spare_oper); ! 195: v = spare_oper.value_o; ! 196: if (spare_oper.type_o == T_REG){ ! 197: opnd->flags_o |= O_BFWREG; ! 198: } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) ! 199: || v < 0 || v > 32){ ! 200: PROG_ERROR(E_CONSTANT); ! 201: } ! 202: opnd->bfwidth_o = (v == 32 ? 0 : v); ! 203: skipb( lptr ); ! 204: if ( cinfo[ *lptr ] == RB ) ! 205: lptr++; ! 206: else ! 207: PROG_ERROR(E_OPERAND); ! 208: } ! 209: return(lptr); ! 210: } /* end soperand */ ! 211: ! 212: static char * ! 213: scan_reg_or_immed( lptr, o ) ! 214: register char *lptr; ! 215: register struct oper *o; ! 216: { ! 217: skipb( lptr ); ! 218: if (cinfo[*lptr] == IMM) { ! 219: lptr = exp(++lptr,o); ! 220: if (o->type_o == T_REG) ! 221: PROG_ERROR(E_REG); ! 222: if (o->sym_o && !(o->sym_o->attr_s&S_DEF)) ! 223: PROG_ERROR(E_REG); ! 224: o->type_o = T_IMMED; ! 225: } else { ! 226: lptr = exp( lptr, o ); ! 227: if ( o->type_o != T_REG || o->value_o > D7REG) ! 228: PROG_ERROR(E_OPERAND); ! 229: } ! 230: return lptr; ! 231: } ! 232: ! 233: static char * ! 234: opt_length( lptr, fp, wflag, lflag, bflag ) ! 235: register char * lptr; ! 236: struct suffix * fp; ! 237: { ! 238: char * save = lptr; ! 239: if (cinfo[ *lptr ] == COL){ ! 240: lptr++; ! 241: skipb( lptr ); ! 242: switch ( *lptr ){ ! 243: case 'b': ! 244: case 'B': ! 245: if (bflag == 0) return save ; ! 246: fp->flags_sx |= bflag; ! 247: lptr++; ! 248: break; ! 249: case 'l': ! 250: case 'L': ! 251: fp->flags_sx |= lflag; ! 252: lptr++; ! 253: break; ! 254: case 'w': ! 255: case 'W': ! 256: fp->flags_sx |= wflag; ! 257: lptr++; ! 258: break; ! 259: default: return save; /* : yes, length, no: may be scale */ ! 260: } ! 261: } ! 262: return lptr; ! 263: } ! 264: static char * ! 265: opt_scale( lptr, fp ) ! 266: char * lptr; ! 267: struct suffix * fp; ! 268: { ! 269: fp->scale_sx = 1; ! 270: if (cinfo[ *lptr ] == COL){ ! 271: lptr++; ! 272: skipb( lptr ); ! 273: switch ( *lptr ){ ! 274: case '1': ! 275: case '2': ! 276: case '4': ! 277: case '8': ! 278: fp->scale_sx = *lptr - '0'; ! 279: lptr++; ! 280: break; ! 281: default: PROG_ERROR(E_OPERAND); ! 282: } ! 283: } ! 284: return lptr; ! 285: } ! 286: ! 287: static char * ! 288: suffix( lptr, fixp ) ! 289: register char * lptr; ! 290: register struct suffix * fixp; ! 291: { ! 292: /* ! 293: * scan for open paran. look for displacement, optional length ! 294: * specifier, then index register, optional length specifier, ! 295: * optional scale specifier. ! 296: * fill in suffix structure with what we find. ! 297: */ ! 298: struct oper o; ! 299: o = zero_oper; ! 300: *fixp = zero_suffix; ! 301: skipb( lptr ); ! 302: if (cinfo[ *lptr ] == LP ) ! 303: lptr += 1; ! 304: else ! 305: return lptr; /* guess that null suffix might be ok */ ! 306: lptr = exp( lptr , &o ); ! 307: if ( o.type_o == T_NORMAL ){ ! 308: fixp->disp_sx = o.value_o; ! 309: fixp->sym_sx = o.sym_o; ! 310: fixp->flags_sx |= SX_GOTDISP; ! 311: lptr = opt_length( lptr, fixp, SX_DISPW, SX_DISPL, SX_DISPB ); ! 312: skipb( lptr ); ! 313: if (cinfo[ *lptr ] == COM) ! 314: lptr = exp( ++lptr, &o ); ! 315: else ! 316: goto scan_rp; ! 317: } ! 318: /* now we're talking index */ ! 319: if ( o.type_o != T_REG ){ ! 320: PROG_ERROR( E_OPERAND); ! 321: } ! 322: fixp->flags_sx |= SX_GOTINDEX; ! 323: fixp->indx_sx = o.value_o; ! 324: lptr = opt_length( lptr, fixp, SX_INDXW, SX_INDXL, 0 ); ! 325: lptr = opt_scale( lptr, fixp ); ! 326: scan_rp: ! 327: skipb( lptr ); ! 328: if (cinfo[ *lptr ] == RP) ! 329: lptr ++; ! 330: else ! 331: PROG_ERROR( E_OPERAND); ! 332: return lptr; ! 333: } ! 334: ! 335: static ! 336: simplify1( oper, fp ) ! 337: register struct oper * oper; ! 338: register struct suffix *fp; ! 339: { ! 340: register bval = oper->value_o; ! 341: /* we have some form of deferred or indexed addressing here */ ! 342: /* try to make the best of it. */ ! 343: /* ! 344: * examples are: ! 345: * a0@(disp) ! 346: * a0@(disp,d0:w:2) ! 347: * a0@(d0:w:2) ! 348: * pc@(disp) ! 349: * pc@(disp,d0:w:2) ! 350: * pc@(d0:w:2) ! 351: * @(d0) ! 352: * @(disp,d0) ! 353: */ ! 354: switch (oper->type_o){ ! 355: case T_REG: ! 356: if( !(fp->flags_sx&(SX_GOTINDEX|SX_DISPL)) ){ ! 357: /* displacement mode */ ! 358: oper->type_o = T_DISPL; ! 359: oper->reg_o = bval; ! 360: oper->value_o = fp->disp_sx; ! 361: oper->sym_o = fp->sym_sx; ! 362: if (fp->flags_sx & SX_DISPW) ! 363: oper->flags_o|= O_WDISP; ! 364: else if (fp->flags_sx & SX_DISPB) { ! 365: PROG_ERROR(E_OPERAND); ! 366: oper->flags_o|= O_WDISP; ! 367: } ! 368: } else { ! 369: /* index mode */ ! 370: imode: ! 371: oper->type_o = T_INDEX; ! 372: oper->reg_o = bval; ! 373: oper->disp_o = fp->disp_sx; ! 374: oper->sym_o = fp->sym_sx; ! 375: if (fp->flags_sx&SX_GOTINDEX){ ! 376: oper->value_o = fp->indx_sx; ! 377: oper->scale_o = fp->scale_sx; ! 378: if (fp->flags_sx&SX_INDXW) ! 379: oper->flags_o|= O_WINDEX|O_PREINDEX; ! 380: else ! 381: oper->flags_o|= O_LINDEX|O_PREINDEX; ! 382: } else { ! 383: oper->value_o = 0; ! 384: oper->scale_o = 0; ! 385: } ! 386: if (fp->flags_sx & SX_DISPL) ! 387: oper->flags_o|= O_LDISP; ! 388: /* else short form indexing */ ! 389: else if (fp->flags_sx & SX_DISPW) ! 390: oper->flags_o|= O_WDISP; ! 391: else if (fp->flags_sx & SX_DISPB) ! 392: oper->flags_o|= O_BDISP; ! 393: } ! 394: return; ! 395: case T_NULL: ! 396: /* @(disp,d0) */ ! 397: /* @(d0) */ ! 398: /* index mode, supressed base */ ! 399: oper->type_o= T_INDEX; ! 400: oper->flags_o|= O_BSUPRESS; ! 401: oper->reg_o = A0REG; /* Supress THIS register */ ! 402: oper->disp_o= fp->disp_sx; ! 403: oper->sym_o= fp->sym_sx; ! 404: if(fp->flags_sx & SX_DISPL) ! 405: oper->flags_o |= O_LDISP; ! 406: else if (fp->flags_sx & SX_DISPW) ! 407: oper->flags_o |= O_WDISP; ! 408: else if (fp->flags_sx & SX_DISPB) { ! 409: PROG_ERROR(E_OPERAND); ! 410: oper->flags_o |= O_WDISP; ! 411: } ! 412: do_index: ! 413: if (fp->flags_sx & SX_GOTINDEX){ ! 414: oper->value_o = fp->indx_sx; ! 415: oper->scale_o = fp->scale_sx; ! 416: if (fp->flags_sx & (SX_INDXW) ) ! 417: oper->flags_o |= O_PREINDEX|O_WINDEX; ! 418: else ! 419: oper->flags_o |= O_PREINDEX|O_LINDEX; ! 420: } else { ! 421: oper->value_o = 0; ! 422: oper->scale_o = 0; ! 423: } ! 424: return; ! 425: case T_ABSS: ! 426: oper->flags_o = O_WDISP; ! 427: goto normal; ! 428: case T_ABSL: ! 429: oper->flags_o = O_LDISP; ! 430: goto normal; ! 431: case T_NORMAL: ! 432: /* disp@ */ ! 433: /* disp@(d0) */ ! 434: /* index mode, supressed base */ ! 435: oper->flags_o = 0; ! 436: normal: ! 437: oper->type_o = T_INDEX; ! 438: oper->flags_o|= O_BSUPRESS; ! 439: oper->reg_o = A0REG; /* Supress THIS register */ ! 440: oper->disp_o = oper->value_o; ! 441: if (fp->flags_sx&SX_GOTDISP) ! 442: PROG_ERROR(E_OPERAND); ! 443: goto do_index; ! 444: default: ! 445: PROG_ERROR(E_OPERAND); ! 446: } ! 447: } ! 448: ! 449: static ! 450: simplify2( oper, fp, dfp ) ! 451: register struct oper * oper; ! 452: struct suffix *fp; ! 453: register struct suffix *dfp; ! 454: { ! 455: /* ! 456: * we have a memory indirect operand. ! 457: * examples: ! 458: * a0@(disp:l,d0:l:4)@(disp:w) ! 459: * a0@(disp)@(disp,d0:l:4) ! 460: * a0@@ ! 461: * @(disp,d0)@(disp) ! 462: * @(d0)@ ! 463: * @(disp)@ ! 464: * @(disp,d0)@ ! 465: * @(disp)@(d0) ! 466: */ ! 467: simplify1( oper, fp ); ! 468: if (oper->type_o == T_DISPL){ ! 469: oper->type_o = T_INDEX; ! 470: oper->disp_o = oper->value_o; ! 471: oper->value_o = 0; ! 472: } ! 473: /* now build on that with second suffix */ ! 474: oper->flags_o |= O_INDIRECT; ! 475: oper->disp2_o = dfp->disp_sx; ! 476: oper->sym2_o = dfp->sym_sx; ! 477: if (dfp->flags_sx & SX_DISPL) ! 478: oper->flags_o |= O_LDISP2; ! 479: else if (dfp->flags_sx & SX_DISPW) ! 480: oper->flags_o |= O_WDISP2; ! 481: else if (dfp->flags_sx & SX_DISPB) { ! 482: PROG_ERROR(E_OPERAND); ! 483: oper->flags_o |= O_WDISP2; ! 484: } ! 485: if (dfp->flags_sx & SX_GOTINDEX){ ! 486: if (oper->flags_o&O_PREINDEX) ! 487: PROG_ERROR(E_OPERAND); ! 488: oper->value_o = dfp->indx_sx; ! 489: oper->flags_o |= O_POSTINDEX; ! 490: oper->scale_o = dfp->scale_sx; ! 491: if (dfp->flags_sx&SX_INDXW) ! 492: oper->flags_o |= O_WINDEX; ! 493: else ! 494: oper->flags_o |= O_LINDEX; ! 495: } ! 496: ! 497: } ! 498: ! 499: /* read expression */ ! 500: char * ! 501: exp(lptr, arg1) ! 502: register char *lptr; ! 503: register struct oper *arg1; ! 504: { ! 505: struct oper arg2; /* holds value of right hand term */ ! 506: register int i; ! 507: static struct oper zero_opr; ! 508: register char *lptr0 ; ! 509: ! 510: lptr0 = lptr ; /* Save pointer to beginning for ! 511: use by reglist. */ ! 512: skipb(lptr); /* Find the operator */ ! 513: i = cinfo[*lptr]; ! 514: if (i==EOL || i==COM){ /* nil operand is zero */ ! 515: arg1->sym_o = NULL; ! 516: arg1->value_o = 0; ! 517: return(lptr); ! 518: } ! 519: lptr = term( lptr, arg1 ); ! 520: ! 521: while (1) { ! 522: arg2 = zero_opr; ! 523: skipb(lptr); ! 524: switch (cinfo[*lptr]) { ! 525: case ADD: lptr = term( ++lptr, &arg2 ); ! 526: if (arg1->type_o==T_REG || arg2.type_o==T_REG) ! 527: break; ! 528: if (arg1->sym_o && arg2.sym_o) ! 529: if (pass==2) break; ! 530: if (arg2.sym_o) ! 531: arg1->sym_o = arg2.sym_o; ! 532: arg1->value_o += arg2.value_o; ! 533: arg1->flags_o |= arg2.flags_o&O_COMPLEX; ! 534: continue; ! 535: ! 536: case MUL: lptr = term(++lptr,&arg2); ! 537: if (arg1->type_o==T_REG || arg2.type_o==T_REG) ! 538: break; ! 539: if (arg1->sym_o || arg2.sym_o) ! 540: if (pass==2) break; ! 541: arg1->value_o *= arg2.value_o; ! 542: arg1->flags_o |= arg2.flags_o&O_COMPLEX; ! 543: continue; ! 544: ! 545: case DIV: lptr = term( ++lptr, &arg2 ); ! 546: if (arg1->type_o==T_REG || arg2.type_o==T_REG) ! 547: if (arg1->type_o==T_REG && arg2.type_o==T_REG) ! 548: { /* try move multiple */ ! 549: lptr = lptr0 ; ! 550: return(reglist( lptr, arg1)) ; ! 551: } ! 552: else break; ! 553: if (arg1->sym_o || arg2.sym_o) ! 554: if (pass==2) break; ! 555: else if (arg2.value_o == 0) arg2.value_o = 1; ! 556: arg1->value_o /= arg2.value_o; ! 557: arg1->flags_o |= arg2.flags_o&O_COMPLEX; ! 558: continue; ! 559: ! 560: case SUB: lptr = term( ++lptr, &arg2 ); ! 561: if (arg1->type_o==T_REG || arg2.type_o==T_REG) ! 562: if (arg1->type_o==T_REG && arg2.type_o==T_REG) ! 563: { /* try move multiple */ ! 564: lptr = lptr0 ; ! 565: return(reglist( lptr, arg1)) ; ! 566: } ! 567: else break; ! 568: if (arg2.sym_o){ /* if B is relocatable, */ ! 569: if (arg1->sym_o){ /* and A is relocatable, */ ! 570: if ((arg1->sym_o->csect_s == 0) && ! 571: ( arg2.sym_o->csect_s != 0)) ! 572: { /* special case: external - relocatable */ ! 573: arg1->flags_o |= O_COMPLEX; ! 574: } ! 575: else ! 576: if (arg2.sym_o->csect_s ! 577: != arg1->sym_o->csect_s ! 578: && pass == 2){ ! 579: break; /* break into error */ ! 580: } else { /* result is absolute (no offset) */ ! 581: arg1->sym_o = NULL; ! 582: /* but not a simple address for sdi's */ ! 583: arg1->flags_o |= O_COMPLEX; ! 584: } ! 585: } ! 586: else break; /* if B rel., and A is not, */ ! 587: /* then break into relocation error */ ! 588: } ! 589: arg1->value_o -= arg2.value_o; ! 590: continue; ! 591: ! 592: default: return(lptr); ! 593: } ! 594: PROG_ERROR(E_RELOCATE); ! 595: return(lptr); ! 596: } ! 597: } /* end exp <read expression> */ ! 598: ! 599: /* read term: either symbol, constant, or unary minus */ ! 600: char * ! 601: term( lptr, vp ) ! 602: register char *lptr; ! 603: register struct oper *vp; ! 604: { ! 605: register struct sym_bkt *sbp; ! 606: register int base = 10; ! 607: register long val; ! 608: register char *p; ! 609: register int i; ! 610: char savechar, *t; ! 611: char token[50]; ! 612: ! 613: *vp = zero_oper; ! 614: skipb(lptr); ! 615: i = cinfo[*lptr]; ! 616: ! 617: /* here for number */ ! 618: if (i & D){ ! 619: p = lptr; ! 620: val = 0; ! 621: if (*lptr == '0'){ ! 622: lptr++; ! 623: switch (*lptr ){ ! 624: case 'x': ! 625: case 'X': ! 626: lptr++; ! 627: /* hexidecimal number */ ! 628: while (1){ ! 629: if (cinfo[*lptr] & D) ! 630: val = val*16 + *lptr++ - '0'; ! 631: else if (*lptr>='A' && *lptr<='F') ! 632: val = val*16 + *lptr++ - 'A' + 10; ! 633: else if (*lptr>='a' && *lptr<='f') ! 634: val = val*16 + *lptr++ - 'a' + 10; ! 635: else break; ! 636: } ! 637: break; ! 638: case 'r': ! 639: case 'R': ! 640: lptr = scan_float( lptr, vp ); ! 641: return (lptr); ! 642: default: ! 643: /* octal number */ ! 644: while (cinfo[*lptr] & D){ ! 645: if (*lptr == '8' || *lptr == '9') ! 646: PROG_ERROR(E_CONSTANT); ! 647: val = val*8 + *lptr++ - '0'; ! 648: } ! 649: } ! 650: } else { ! 651: /* decimal number */ ! 652: while (cinfo[*lptr] & D) ! 653: val = val*10 + *lptr++ - '0'; ! 654: } ! 655: got_a_number: ! 656: if (*lptr == '$') ! 657: { lptr = p; goto sym; } ! 658: if (*lptr == 'b' || *lptr == 'f'){ ! 659: /* local label reference, of form [0-9][bh] */ ! 660: /* single digits only */ ! 661: if (lptr > p+1 ){ ! 662: PROG_ERROR(E_SYMLEN); ! 663: } ! 664: val = ll_val[*p-'0'] + (*lptr++=='f'); ! 665: if (val < 0 ) PROG_ERROR(E_SYMDEF); ! 666: sprintf(token, ll_format, *p, val); ! 667: sbp = lookup(token); ! 668: goto sym2; ! 669: ! 670: } ! 671: vp->value_o = val; ! 672: vp->sym_o = NULL; ! 673: vp->type_o = T_NORMAL; ! 674: return(lptr); ! 675: } ! 676: ! 677: /* here for symbol name */ ! 678: if (i & S) { ! 679: sym: t = lptr; ! 680: while (cinfo[*lptr] & T) ! 681: lptr++; ! 682: savechar = *lptr; ! 683: *lptr = '\0'; ! 684: sbp = lookup(t); /* find its symbol bucket */ ! 685: *lptr = savechar; ! 686: sym2: ! 687: if (sbp->attr_s & S_DEF) /* if it's defined, use its value */ ! 688: vp->value_o = sbp->value_s; ! 689: else ! 690: vp->value_o = 0; ! 691: if (sbp->attr_s & S_REG) { ! 692: vp->sym_o = NULL; ! 693: vp->type_o = T_REG; ! 694: } else { ! 695: vp->sym_o = ((sbp->attr_s & S_DEF) && ! 696: (sbp->csect_s == C_UNDEF )) ? 0 : sbp; ! 697: vp->type_o = T_NORMAL; ! 698: } ! 699: return(lptr); ! 700: } ! 701: ! 702: /* check for unary minus */ ! 703: if (i == SUB) { ! 704: lptr = term(++lptr,vp); ! 705: if (vp->sym_o) PROG_ERROR(E_RELOCATE); ! 706: vp->value_o = -(vp->value_o); ! 707: vp->fval_o = -(vp->fval_o); ! 708: vp->dval_o = -(vp->dval_o); ! 709: return(lptr); ! 710: } ! 711: ! 712: /* check for complement */ ! 713: if (i == NOT) { ! 714: lptr = term(++lptr,vp); ! 715: if (vp->sym_o) PROG_ERROR(E_RELOCATE); ! 716: vp->value_o = ~(vp->value_o); ! 717: return(lptr); ! 718: } ! 719: ! 720: /* here for string */ ! 721: if (i == QUO) { ! 722: vp->stringval_o = lptr+1; ! 723: /* scan over the quoted string, being careful of \-stuff */ ! 724: do{ ! 725: i = *++lptr; ! 726: if (i=='\\') ! 727: switch (i = *++lptr){ ! 728: case '"': i = '\\'; /* fake-out loop test by covering up \"*/ ! 729: } ! 730: }while (i!='\n' && i!='"'); ! 731: if (i == '\n'){ ! 732: PROG_ERROR(E_STRING); ! 733: } ! 734: *lptr++ = 0; ! 735: vp->sym_o = NULL; ! 736: vp->type_o = T_STRING; ! 737: return(lptr); ! 738: } ! 739: ! 740: /* new, improved kluge -- parens !! */ ! 741: if (i==LP) { ! 742: lptr = exp(++lptr, vp); ! 743: skipb(lptr); ! 744: if ((i=cinfo[*lptr]) == RP) { ! 745: lptr++; ! 746: } else { ! 747: PROG_ERROR( E_PAREN ); ! 748: } ! 749: return( lptr ); ! 750: } ! 751: ! 752: PROG_ERROR(E_TERM); ! 753: return(lptr); ! 754: } /* end term */ ! 755: ! 756: char lowcase( c ) ! 757: char c ; ! 758: { ! 759: if (('A' <= c) && (c <= 'Z')) return(c+32) ; else return(c) ; ! 760: } ! 761: ! 762: char * ! 763: scan_float( lptr, vp ) ! 764: register char * lptr; ! 765: struct oper *vp; ! 766: { ! 767: /* ! 768: * lptr address a string which is a 'd' or an 'f', followed ! 769: * by a floating-point number. The latter looks like: ! 770: * [+-]nan ! 771: * or [+-]nan( [0-9a-f]+ ) ! 772: * or [+-]inf ! 773: * or [+-][0-9]+[.[0-9]+][e[+-][0-9]+] ! 774: * Upper/lower case may be used interchangeably. ! 775: * For numbers, call atof to do the conversion work. ! 776: * We do not take great care in syntax checking the number. ! 777: */ ! 778: int s=0; ! 779: union{ double d; float f; int x[2]; } fp; ! 780: unsigned nanno, nanno2; ! 781: register char *nbegin; ! 782: char c; ! 783: ! 784: lptr++ ; /* Skip F or f. */ ! 785: nbegin = lptr ; ! 786: again: ! 787: switch (lowcase( *lptr++)){ ! 788: case '+': if (s) goto bad_num; s = 1; goto again; ! 789: case '-': if (s) goto bad_num; s = -1; goto again; ! 790: case 'n': /* nan */ ! 791: if (lowcase(*lptr++) != 'a') goto bad_num; ! 792: if (lowcase(*lptr++) != 'n') goto bad_num; ! 793: nanno = nanno2 = 0; ! 794: if (*lptr == '(') ! 795: { /* nan significand */ ! 796: lptr++ ; /* pass paren */ ! 797: while( isxdigit(c = *lptr++)){ ! 798: if (isdigit(c)) c -= '0'; ! 799: else if (isupper(c)) c -= 'a'-10; ! 800: else c -= 'A'-10; ! 801: nanno2 = (nanno2 << 8) | (nanno >> 24); ! 802: nanno = (nanno<<8) | c; ! 803: } ! 804: if (c != ')') goto bad_num; ! 805: } /* nan significand */ ! 806: if ((nanno | nanno2) == 0) nanno = -1 ; /* avoid zero nan */ ! 807: goto make_indef; ! 808: ! 809: case 'i': /* inf */ ! 810: if (lowcase(*lptr++) != 'n') goto bad_num; ! 811: if (lowcase(*lptr++) != 'f') goto bad_num; ! 812: if (strncmp(lptr,"inity",5) == 0) lptr += 5; ! 813: nanno = nanno2 = 0; ! 814: make_indef: ! 815: fp.x[0] = ((s<0)?0xfff00000:0x7ff00000) | nanno2; ! 816: fp.x[1] = nanno; ! 817: break; ! 818: case '0': case '1': case '2': case '3': case '4': ! 819: case '5': case '6': case '7': case '8': case '9': ! 820: /* scan for more digits */ ! 821: while( isdigit( c = *lptr++ ) ) ! 822: continue; ! 823: if (c != '.' ) ! 824: goto scan_exp; ! 825: /* FALL THROUGH */ ! 826: case '.': ! 827: /* scan for more digits */ ! 828: while( isdigit( c = *lptr++ ) ) ! 829: continue; ! 830: scan_exp: ! 831: s = 0; ! 832: switch(lowcase(c)){ ! 833: case '+': ! 834: case '-': ! 835: s = 1; ! 836: /* FALL THROUGH */ ! 837: case 'e': ! 838: switch ( c= *lptr++ ){ ! 839: case '+': ! 840: case '-': ! 841: if (s) goto bad_num; ! 842: c = *lptr++; ! 843: /* FALL THROUGH */ ! 844: default: ! 845: s = 0; /* count chars: 0 is not ok */ ! 846: while( isdigit(c) ){ ! 847: c = *lptr++; ! 848: s++; ! 849: } ! 850: if (s == 0) goto bad_num; ! 851: break; ! 852: } ! 853: break; ! 854: } ! 855: fp.d = atof( nbegin ); ! 856: lptr--; ! 857: break; ! 858: default: ! 859: bad_num: ! 860: PROG_ERROR( E_BADCHAR ); ! 861: return lptr; ! 862: } ! 863: vp->dval_o = fp.d; ! 864: vp->value_o = (int) fp.d; ! 865: vp->type_o = T_DOUBLE; ! 866: return lptr; ! 867: } ! 868: ! 869: static void ! 870: printoffset( v, s ) ! 871: struct sym_bkt *s; ! 872: { ! 873: if (s != NULL){ ! 874: fputs(s->name_s, stdout); ! 875: if (v) ! 876: printf("+%d", v); ! 877: } else { ! 878: printf("%d", v); ! 879: } ! 880: } ! 881: ! 882: static char *rnames[] = { ! 883: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", ! 884: "a0", "a1", "a2", "a3", "a4", "a5", "a6", ! 885: "sp", "pc", "cc", "sr", "usp", "sfc", "dfc", "vbr", ! 886: }; ! 887: ! 888: static void ! 889: printindex( o ) ! 890: register struct oper *o; ! 891: { ! 892: printf(",%s:%c", rnames[o->value_o], ! 893: o->flags_o&O_WINDEX ? 'w' : 'l'); ! 894: if (o->scale_o != 1) printf(":%d", o->scale_o); ! 895: } ! 896: ! 897: printop( o ) ! 898: register struct oper *o; ! 899: { ! 900: switch (o->type_o){ ! 901: case T_REG: printf("%s", rnames[o->value_o]); break; ! 902: case T_DEFER: printf("%s@", rnames[o->value_o]); break; ! 903: case T_POSTINC: printf("%s@+", rnames[o->value_o]); break; ! 904: case T_PREDEC: printf("%s@-", rnames[o->value_o]); break; ! 905: case T_DISPL: printf("%s@(", rnames[o->reg_o]); ! 906: printoffset(o->value_o, o->sym_o); ! 907: putchar(')'); ! 908: break; ! 909: case T_INDEX: printf("%s@(", (o->flags_o&O_BSUPRESS) ! 910: ? "XX" : rnames[o->reg_o]); ! 911: printoffset(o->disp_o, o->sym_o); ! 912: if (o->flags_o & O_WDISP) fputs(":w", stdout); ! 913: else if (o->flags_o & O_LDISP) fputs(":l", stdout); ! 914: if (o->flags_o&O_PREINDEX) ! 915: printindex( o ); ! 916: putchar(')'); ! 917: if (o->flags_o&O_INDIRECT){ ! 918: fputs("@(", stdout); ! 919: printoffset(o->disp2_o, o->sym2_o); ! 920: if (o->flags_o&O_POSTINDEX) ! 921: printindex( o ); ! 922: putchar(')'); ! 923: } ! 924: break; ! 925: case T_ABSS: ! 926: case T_ABSL: ! 927: printoffset(o->value_o, o->sym_o); ! 928: fputs( (o->type_o == T_ABSS) ? ":w" : ":l", stdout); ! 929: break; ! 930: case T_IMMED: ! 931: putchar('#'); ! 932: /* FALL THROUGH */ ! 933: case T_NORMAL: ! 934: printoffset(o->value_o, o->sym_o); ! 935: break; ! 936: case T_STRING: ! 937: printf("\"%s\"", o->stringval_o); ! 938: break; ! 939: case T_REGPAIR: printf("%s:%s", rnames[o->value_o],rnames[o->reg_o]); ! 940: break; ! 941: case T_FLOAT: ! 942: case T_DOUBLE: printf("0d%g", o->dval_o ); break; ! 943: default: ! 944: printf("UNKNOWN(%d)", o->type_o); ! 945: break; ! 946: } ! 947: if (o->flags_o&O_BFLD){ ! 948: /* bit field */ ! 949: /* first the offset part */ ! 950: if (o->flags_o&O_BFOREG) ! 951: printf("[%s:",rnames[o->bfoffset_o]); ! 952: else ! 953: printf("[#%d:",o->bfoffset_o); ! 954: /* then the width part */ ! 955: if (o->flags_o&O_BFWREG) ! 956: printf("%s]",rnames[o->bfwidth_o]); ! 957: else ! 958: printf("#%d]",o->bfwidth_o); ! 959: } ! 960: putchar('\n'); ! 961: } ! 962: ! 963: int aregs ; /* Contains bits for a7..a0. */ ! 964: int dregs ; /* Contains bits for d7..d0. */ ! 965: int fregs ; /* Contains bits for fp7..fp0. */ ! 966: int cregs ; /* Contains bits for fpc..fpi. */ ! 967: int otheregs ; /* Contains 1 for any other regs encountered. */ ! 968: ! 969: storeg( n ) ! 970: int n ; ! 971: ! 972: { ! 973: if ((A0REG <= n) && (n <= A7REG)) aregs |= 1 << (n-A0REG) ; ! 974: else ! 975: if ((D0REG <= n) && (n <= D7REG)) dregs |= 1 << (n-D0REG) ; ! 976: else ! 977: if ((FP0REG <= n) && (n <= FP7REG)) fregs |= 1 << (n-FP0REG) ; ! 978: else ! 979: if ((FPCREG <= n) && (n <= FPIREG)) cregs |= 1 << (FPIREG-n) ; ! 980: else ! 981: otheregs = 1 ; ! 982: } ! 983: ! 984: storegs( m, n ) ! 985: int m, n ; ! 986: ! 987: { ! 988: int t ; ! 989: ! 990: if (m > n) ! 991: { ! 992: t = m ; ! 993: m = n ; ! 994: n = t ; ! 995: } ! 996: if ((A0REG <= m) && (n <= A7REG)) for (t=m ; t <= n ; ) aregs |= 1 << (t++-A0REG) ; ! 997: else ! 998: if ((D0REG <= m) && (n <= D7REG)) for (t=m ; t<=n ; ) dregs |= 1 << (t++-D0REG) ; ! 999: else ! 1000: if ((FP0REG <= m) && (n <= FP7REG)) for (t=m ; t<=n ; ) fregs |= 1 << (t++-FP0REG) ; ! 1001: else ! 1002: if ((FPCREG <= m) && (n <= FPIREG)) for (t=m ; t<=n ; ) cregs |= 1 << (FPIREG-t++) ; ! 1003: else ! 1004: otheregs = 1 ; ! 1005: } ! 1006: ! 1007: char * reglist ( lptr, arg1 ) ! 1008: ! 1009: char *lptr ; ! 1010: struct oper *arg1 ; ! 1011: ! 1012: /* ! 1013: reglist is called from exp when a register list operand is ! 1014: suspected. If it fails, E_RELOCATE occurs. ! 1015: */ ! 1016: ! 1017: { ! 1018: struct oper arg2 ; ! 1019: ! 1020: aregs = dregs = fregs = cregs = otheregs = 0 ; ! 1021: skipb(lptr) ; ! 1022: lptr = term(lptr, arg1) ; ! 1023: while (arg1->type_o == T_REG) ! 1024: { ! 1025: skipb(lptr) ; ! 1026: switch (cinfo[*lptr]) ! 1027: { ! 1028: case EOL: ! 1029: case COM: /* end of list */ ! 1030: { ! 1031: storeg(arg1->value_o) ; ! 1032: if (otheregs) break ; ! 1033: if ((aregs|dregs) != 0) ! 1034: { /* list of a's and d's */ ! 1035: if ((fregs|cregs) != 0) break ; ! 1036: arg1->type_o = T_REGLIST ; ! 1037: arg1->value_o = dregs | (aregs << 8) ; ! 1038: return(lptr) ; ! 1039: } ! 1040: else ! 1041: if (fregs != 0) ! 1042: { /* list of fp's */ ! 1043: if (cregs != 0) break ; ! 1044: arg1->type_o = T_FREGLIST ; ! 1045: arg1->value_o = fregs ; ! 1046: return(lptr) ; ! 1047: } ! 1048: else ! 1049: if (cregs != 0) ! 1050: { /* list of fc's */ ! 1051: arg1->type_o = T_FCREGLIST ; ! 1052: arg1->value_o = cregs ; ! 1053: return(lptr) ; ! 1054: } ! 1055: break ; ! 1056: } ! 1057: case DIV: /* rn/... */ ! 1058: { ! 1059: storeg(arg1->value_o) ; ! 1060: lptr++ ; ! 1061: skipb(lptr) ; ! 1062: lptr = term(lptr, arg1) ; ! 1063: continue ; ! 1064: } ! 1065: case SUB: /* rn-... */ ! 1066: { ! 1067: lptr = term (++lptr, &arg2) ; ! 1068: if (arg2.type_o != T_REG) break ; ! 1069: storegs(arg1->value_o,arg2.value_o) ; ! 1070: continue ; ! 1071: } ! 1072: } ! 1073: break ; ! 1074: } ! 1075: arg1->type_o = T_NULL ; /* Avoid problems later. */ ! 1076: PROG_ERROR(E_REGLIST) ; ! 1077: return(lptr) ; ! 1078: } ! 1079:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.