|
|
1.1 ! root 1: %{ ! 2: #include <asm.h> ! 3: /* ! 4: * count macro parms. ! 5: */ ! 6: static ! 7: parmCt() ! 8: { ! 9: if(NULL == trueMac) { ! 10: yyerror(".parmct not in macro"); ! 11: /* \fB.parmct\fR returns the number of ! 12: * parameters in the current macro. */ ! 13: return(0); ! 14: } ! 15: else ! 16: return(countList(trueMac->parms)); ! 17: } ! 18: ! 19: /* ! 20: * Verify that 2 symbols have the same segment. ! 21: */ ! 22: static void ! 23: ckseg(s1, s2) ! 24: sym *s1, *s2; ! 25: { ! 26: if(s1->sg != s2->sg) ! 27: yyerror("Arithmetic between addresses on different segments"); ! 28: /* You may only add or subtract addresses if they ! 29: * are in the same segment. */ ! 30: } ! 31: ! 32: /* ! 33: * Create Immediate exps. ! 34: */ ! 35: static expr * ! 36: setImm(val, symRef) ! 37: long val; ! 38: sym *symRef; ! 39: { ! 40: register expr *oper; ! 41: register short w; ! 42: ! 43: oper = xalloc(); ! 44: oper->mode = T_IMM; ! 45: if (NULL != (oper->ref = symRef)) ! 46: oper->ref = symRef->ref; ! 47: w = oper->exp = val; ! 48: if(w == val) ! 49: oper->size = 2; ! 50: else ! 51: oper->size = 4; ! 52: return(oper); ! 53: } ! 54: ! 55: /* ! 56: * Set up for most addressing modes. ! 57: */ ! 58: static expr * ! 59: qbild(val, mode, r1, r2, scale, symRef) ! 60: long val; ! 61: int mode; ! 62: psym *r1, *r2; ! 63: long scale; ! 64: sym *symRef; ! 65: { ! 66: register expr *oper; ! 67: char i; ! 68: ! 69: if (NULL != r1 && T_R != mode) { ! 70: switch((int)r1->size) { ! 71: case 2: ! 72: lflags |= A_SHORT; ! 73: if (!scale) ! 74: break; ! 75: case 1: ! 76: regerror(r1); ! 77: break; ! 78: case 4: ! 79: lflags |= A_LONG; ! 80: break; ! 81: } ! 82: ! 83: if (ORD_REG != r1->flag) /* cant ind via ctl regs */ ! 84: regerror(r1); ! 85: ! 86: if (NULL != r2) { ! 87: if (ORD_REG != r2->flag) ! 88: regerror(r2); ! 89: if (r1->size != r2->size) ! 90: yyerror("Mixed length addressing registers"); ! 91: /* Addressing registers must both be the same length. */ ! 92: } ! 93: } ! 94: else if ((T_R == mode) && (r1->flag == ORD_REG)) { ! 95: switch ((int)r1->size) { ! 96: case 4: ! 97: lflags |= O_LONG; ! 98: break; ! 99: case 2: ! 100: lflags |= O_SHORT; ! 101: } ! 102: } ! 103: ! 104: oper = xalloc(); ! 105: oper->exp = val; ! 106: oper->r1 = r1; ! 107: oper->r2 = r2; ! 108: oper->mode = mode; ! 109: ! 110: i = scale; ! 111: if (i != scale) ! 112: i = 3; /* set a bad scale */ ! 113: ! 114: switch (i) { ! 115: case 0: ! 116: case 1: /* for generated code */ ! 117: oper->scale = 0; break; ! 118: case 2: ! 119: oper->scale = 1; break; ! 120: case 4: ! 121: oper->scale = 2; break; ! 122: case 8: ! 123: oper->scale = 3; break; ! 124: default: ! 125: yyerror("Bad scale"); ! 126: /* Address scale must be 0, 1, 2, 4, or 8. */ ! 127: } ! 128: ! 129: if (NULL != (oper->ref = symRef)) ! 130: oper->ref = symRef->ref; ! 131: return(oper); ! 132: } ! 133: ! 134: /* ! 135: * Floating point register expr. ! 136: */ ! 137: static expr * ! 138: fbild(regno) ! 139: long regno; ! 140: { ! 141: register expr *oper; ! 142: ! 143: if (regno < 0 || regno > 7) { ! 144: regno &= 7; ! 145: yyerror("Invalid floating point register number"); /**/ ! 146: } ! 147: ! 148: oper = xalloc(); ! 149: oper->exp = regno; ! 150: oper->mode = T_FP; ! 151: return (oper); ! 152: } ! 153: ! 154: /* ! 155: * Report register error. ! 156: */ ! 157: regerror(rg) ! 158: psym *rg; ! 159: { ! 160: yyerror("%s is an improper register in this context", rg->name); /**/ ! 161: } ! 162: ! 163: /* ! 164: * Concatinate strings. ! 165: */ ! 166: static char * ! 167: concat(s1, s2) ! 168: char *s1, *s2; ! 169: { ! 170: long l; ! 171: unsigned short u; ! 172: char *res; ! 173: ! 174: u = l = (long)strlen(s1) + (long)strlen(s2) + 1; ! 175: if(u != l) { ! 176: yyerror("Length %ld string range exceeded", l); ! 177: /* Strings may not exceed 32 kilobytes. */ ! 178: return(galloc(1)); ! 179: } ! 180: res = galloc(u); ! 181: sprintf(res, "%s%s", s1, s2); ! 182: return(res); ! 183: } ! 184: ! 185: /* ! 186: * Substring. ! 187: * Assumes that all strings are created from unsigned lengths. ! 188: */ ! 189: static char * ! 190: substr(s, from, len) ! 191: char *s; ! 192: long from, len; ! 193: { ! 194: register char *p, *res; ! 195: unsigned short l; ! 196: ! 197: l = strlen(s); ! 198: s += from; ! 199: from = l - from; /* from now len to end */ ! 200: ! 201: if(len > from) ! 202: len = from; /* since strlen fit unsigned len must */ ! 203: if(len < 0) ! 204: len = 0; ! 205: ! 206: for(p = res = galloc((unsigned)(len + 1)); len--; ) ! 207: *p++ = *s++; ! 208: return(res); ! 209: } ! 210: ! 211: /* ! 212: * String search. ! 213: */ ! 214: static ! 215: stringSearch(s1, s2) ! 216: char *s1, *s2; ! 217: { ! 218: char *p; ! 219: ! 220: if(NULL == (p = strstr(s1, s2))) ! 221: return(-1); ! 222: return(p - s1); ! 223: } ! 224: ! 225: /* ! 226: * Do long comparisons. ! 227: * < > <= >= != == compare operator ! 228: * 1 2 5 6 3 4 t ! 229: */ ! 230: static ! 231: compare(t, v) ! 232: int t; ! 233: long v; ! 234: { ! 235: return(((v < 0) ? t : (v > 0) ? (t >> 1) : (t >> 2)) & 1); ! 236: } ! 237: ! 238: /* ! 239: * Do double comparisons. ! 240: * < > <= >= != == compare operator ! 241: * 1 2 5 6 3 4 t ! 242: */ ! 243: static ! 244: fcompare(t, v) ! 245: int t; ! 246: double v; ! 247: { ! 248: return(((v < 0.0) ? t : (v > 0.0) ? (t >> 1) : (t >> 2)) & 1); ! 249: } ! 250: ! 251: static void ! 252: unmatched(c) ! 253: { ! 254: yyerror("Unmatched '%c'", c); ! 255: /* A delimeter, [, (, ), or ] is unmatched in this command. */ ! 256: } ! 257: ! 258: %} ! 259: %union { ! 260: long val; /* numeric value */ ! 261: double dbl; ! 262: sym *s; /* name size loc bitd bitl flag */ ! 263: opc *o; /* opcode kind */ ! 264: expr *e; /* mode loc size exp bitd bitl chain next */ ! 265: char *t; /* token */ ! 266: parm *p; /* parm */ ! 267: data *d; /* data item */ ! 268: } ! 269: %token PC /* The PC reg */ ! 270: %token <val> NUMBER /* a number */ ! 271: %token <dbl> FNUM /* floating point number */ ! 272: %token <val> COMPARISON /* = < > <= >= !=*/ ! 273: %token <o> OP /* a 386 opcode */ ! 274: %token <o> DATA /* dc.w etc */ ! 275: %token <o> CMD /* an assembler command or macro call */ ! 276: %token <o> DCMD /* a command with string parms */ ! 277: %token <o> ICMD /* an assembler command taking a numexp parm */ ! 278: %token <o> NCMD /* an assembler command without parms */ ! 279: %token <o> ECMD /* an assembler command with a name and an expr */ ! 280: %token <o> ECMDX /* an assembler command with a name and a datalist */ ! 281: %token <s> IDENTIFIER /* a symbol */ ! 282: %token <s> REG /* A register */ ! 283: ! 284: %token DEFINED /* the word .defined */ ! 285: %token SIZEOF /* the word .sizeof */ ! 286: %token SEGMENT /* the word .segment */ ! 287: %token LOCATION /* the word .location */ ! 288: %token PLUS /* + */ ! 289: %token MINUS /* - */ ! 290: %token TIMES /* * */ ! 291: %token DIVIDE /* / */ ! 292: %token REM /* % */ ! 293: %token LSHIFT /* << */ ! 294: %token RSHIFT /* >> */ ! 295: %token AND /* & */ ! 296: %token OR /* | */ ! 297: %token XOR /* ^ */ ! 298: %token COMMA /* , */ ! 299: %token LPAREN /* [ reversed with () */ ! 300: %token RPAREN /* ] */ ! 301: %token LBRACK /* ( */ ! 302: %token RBRACK /* ) */ ! 303: %token AT /* @ */ ! 304: %token D_SIGN /* $ */ ! 305: %token NOT /* ~ */ ! 306: %token BANG /* ! */ ! 307: %token COLON /* : */ ! 308: %token PARMCT /* .parmct */ ! 309: %token TOSTRING /* .string */ ! 310: %token TONUMBER /* .number */ ! 311: %token TOFLOAT /* .float */ ! 312: %token FSTACK /* %st */ ! 313: %token NL /* \n */ ! 314: ! 315: %token <t> TOKEN /* a token in an assembler command or macro call */ ! 316: %type <p> label parm plist ! 317: %type <t> string ! 318: ! 319: %right COMMA /* low presidence to hi */ ! 320: %right COLON ! 321: %right AT P_SIGN ! 322: %left OR ! 323: %left XOR ! 324: %left AND ! 325: %left COMPARISON ! 326: %left LSHIFT RSHIFT ! 327: %left PLUS MINUS ! 328: %left TIMES DIVIDE REM ! 329: %right DEFINED SIZEOF SEGMENT LOCATION NOT LEN BANG ! 330: %right TOKEN ! 331: %left LPAREN LBRACK TOSTRING TONUMBER TOFLOAT ! 332: %right NL ! 333: ! 334: %type <dbl> dblexp ! 335: %type <val> numexp ! 336: /* addressing modes */ ! 337: %type <e> operand oper escoper ! 338: ! 339: %type <s> addexp ! 340: ! 341: /* for dc.? */ ! 342: %type <d> item itemlist ! 343: %% ! 344: ! 345: /* oper types */ ! 346: /* ! 347: * label opcode operand comment NL ! 348: * label and comment eaten by lexer. ! 349: */ ! 350: file : line | file line; ! 351: ! 352: line : label CMD plist NL { /* assembler command with parms */ ! 353: docmd($1, $2, $3); } ! 354: | label DCMD plist NL { /* a command with string parms */ ! 355: docmd($1, $2, $3); } ! 356: | label ECMD parm COMMA item NL { /* command with a name & an expr */ ! 357: ecmd($1, $2, $3, $5); } ! 358: /* command with a name & a datalist */ ! 359: | label ECMDX parm COMMA itemlist NL { ! 360: ecmd($1, $2, $3, $5); } ! 361: | label ECMD NL { ! 362: ecmd($1, $2, NULL, NULL); } ! 363: | label NCMD NL { /* assembler command takes no parms */ ! 364: docmd($1, $2, (parm *)NULL); } ! 365: | label ICMD item NL { /* assembler command with data parm */ ! 366: ncmd($1, $2, $3); } ! 367: | label DATA itemlist NL { /* data list */ ! 368: dcmd($1, $2, $3); } ! 369: | label OP operand NL { /* opcode operands */ ! 370: buildind($1, $2, $3); } ! 371: | label OP OP NL { /* built by rep instr */ ! 372: buildind($1, $2, NULL); ! 373: buildind(NULL, $3, NULL ); } ! 374: | label NL { /* label alone on line */ ! 375: buildlab($1); } ! 376: | error NL { /* syntax error */ ! 377: if (bcnt > 0) ! 378: unmatched('['); ! 379: if (bcnt < 0) ! 380: unmatched(']'); ! 381: if (pcnt > 0) ! 382: unmatched('('); ! 383: if (pcnt < 0) ! 384: unmatched(')'); ! 385: yyerrok; }; ! 386: ! 387: itemlist : item COMMA itemlist { ! 388: $$ = $1; ! 389: $$->next = $3; } ! 390: | item { ! 391: $$ = $1; } ! 392: | { ! 393: $$ = NULL; }; ! 394: ! 395: item : addexp { ! 396: $$ = gitem('y'); ! 397: $$->d.y = $1; } ! 398: | dblexp { ! 399: $$ = gitem('d'); ! 400: $$->d.d = $1; } ! 401: | numexp { ! 402: $$ = gitem('l'); ! 403: $$->d.l = $1; } ! 404: | string { ! 405: $$ = gitem('s'); ! 406: $$->d.s = $1; } ! 407: | numexp P_SIGN item { ! 408: $$ = $3; ! 409: $$->count = $1; }; ! 410: ! 411: plist : parm { /* start parm list */ ! 412: $$ = $1; } ! 413: | parm COMMA plist { /* chain parm list */ ! 414: $$ = $1; ! 415: $$->next = $3; } ! 416: | { ! 417: $$ = NULL; }; ! 418: ! 419: parm : TOKEN { /* start a parm */ ! 420: $$ = (parm *)gcpy($1, offset(parm, str)); }; ! 421: ! 422: label : { ! 423: $$ = NULL; } ! 424: | TOKEN { ! 425: $$ = (parm *)gcpy($1, offset(parm, str)); }; ! 426: ! 427: /* operand may be stuff separated by commas */ ! 428: operand : escoper COMMA operand { ! 429: $$ = $1; ! 430: $$->next = $3; } ! 431: | escoper { ! 432: $$ = $1; } ! 433: | TIMES escoper { ! 434: lflags |= A_INDIR; ! 435: $$ = $2; } ! 436: | { ! 437: $$ = NULL; }; ! 438: ! 439: escoper : oper { ! 440: $$->sg = -1; ! 441: $$ = $1; } ! 442: | REG COLON oper { ! 443: $$ = $3; ! 444: if ($1->flag != SEG_REG) ! 445: regerror($1); ! 446: $$->sg = $1->loc; }; ! 447: ! 448: /* operands are one of these */ ! 449: oper : REG { ! 450: $$ = qbild(0L, T_R, $1, NULL, 0L, NULL); } ! 451: ! 452: | FSTACK { ! 453: $$ = fbild(0L); } ! 454: ! 455: | FSTACK LBRACK numexp RBRACK { ! 456: $$ = fbild($3); } ! 457: ! 458: | LBRACK REG RBRACK { ! 459: $$ = qbild(0L, T_RI, $2, NULL, 0L, NULL); } ! 460: ! 461: | LBRACK REG COMMA numexp RBRACK { ! 462: $$ = qbild(0L, T_RIS, $2, NULL, $4, NULL); } ! 463: ! 464: | LBRACK COMMA REG COMMA numexp RBRACK { ! 465: $$ = qbild(0L, T_RIS, $3, NULL, $5, NULL); } ! 466: ! 467: | LBRACK REG COMMA REG RBRACK { ! 468: $$ = qbild(0L, T_RIX, $2, $4, 0L, NULL); } ! 469: ! 470: | LBRACK REG COMMA REG COMMA numexp RBRACK { ! 471: $$ = qbild(0L, T_RIXS, $2, $4, $6, NULL); } ! 472: ! 473: | numexp LBRACK REG RBRACK { ! 474: $$ = qbild($1, T_RID, $3, NULL, 0L, NULL); } ! 475: ! 476: | numexp LBRACK REG COMMA numexp RBRACK { ! 477: $$ = qbild($1, T_RIDS, $3, NULL, $5, NULL); } ! 478: ! 479: | numexp LBRACK COMMA REG COMMA numexp RBRACK { ! 480: $$ = qbild($1, T_RIDS, $4, NULL, $6, NULL); } ! 481: ! 482: | numexp LBRACK REG COMMA REG RBRACK { ! 483: $$ = qbild($1, T_RIXD, $3, $5, 0L, NULL); } ! 484: ! 485: | numexp LBRACK REG COMMA REG COMMA numexp RBRACK { ! 486: $$ = qbild($1, T_RIXDS, $3, $5, $7, NULL); } ! 487: ! 488: | addexp LBRACK REG RBRACK { ! 489: $$ = qbild($1->loc, T_RID, $3, NULL, 0L, $1); } ! 490: ! 491: | addexp LBRACK REG COMMA numexp RBRACK { ! 492: $$ = qbild($1->loc, T_RIDS, $3, NULL, $5, $1); } ! 493: ! 494: | addexp LBRACK COMMA REG COMMA numexp RBRACK { ! 495: $$ = qbild($1->loc, T_RIDS, $4, NULL, $6, $1); } ! 496: ! 497: | addexp LBRACK REG COMMA REG RBRACK { ! 498: $$ = qbild($1->loc, T_RIXD, $3, $5, 0L, $1); } ! 499: ! 500: | addexp LBRACK REG COMMA REG COMMA numexp RBRACK { ! 501: $$ = qbild($1->loc, T_RIXDS, $3, $5, $7, $1); } ! 502: ! 503: | addexp { ! 504: $$ = qbild($1->loc, T_D, NULL, NULL, 0L, $1); } ! 505: ! 506: | numexp { ! 507: $$ = qbild($1, T_D, NULL, NULL, 0L, NULL); } ! 508: ! 509: | D_SIGN numexp { ! 510: $$ = setImm($2, (sym *)NULL); } ! 511: ! 512: | D_SIGN addexp { ! 513: $$ = setImm($2->loc, $2); }; ! 514: ! 515: ! 516: /* Various expressions */ ! 517: ! 518: addexp : IDENTIFIER { $$ = $1; } ! 519: | LPAREN addexp RPAREN { $$=$2; } ! 520: | addexp PLUS numexp { $$ = copySym($1); $$->loc += $3; } ! 521: | addexp MINUS numexp { $$ = copySym($1); $$->loc -= $3; } ! 522: | numexp PLUS addexp { $$ = copySym($3); $$->loc += $1; }; ! 523: ! 524: /* numeric expressions done here */ ! 525: numexp : NUMBER { ! 526: $$ = $1; } ! 527: | LPAREN numexp RPAREN { ! 528: $$ = $2; } ! 529: | addexp MINUS addexp { ! 530: ckseg($1, $3); $$ = $1->loc - $3->loc; } ! 531: | addexp COMPARISON addexp { ! 532: ckseg($1, $3); $$ = compare((int)$2, $1->loc - $3->loc); } ! 533: | numexp COMPARISON numexp { ! 534: $$ = compare((int)$2, $1 - $3); } ! 535: | string COMPARISON string { ! 536: $$ = compare((int)$2, (long)strcmp($1, $3)); } ! 537: | dblexp COMPARISON dblexp { ! 538: $$ = fcompare((int)$2, $1 - $3); } ! 539: ! 540: | SIZEOF addexp { ! 541: $$ = $2->size; } ! 542: ! 543: | LOCATION addexp { ! 544: $$ = $2->loc; } ! 545: ! 546: | SEGMENT addexp { ! 547: $$ = $2->sg + 1; } ! 548: ! 549: | DEFINED IDENTIFIER { ! 550: $$ = $2->statement && (statement >= $2->statement); } ! 551: | DEFINED NUMBER { ! 552: $$ = 1; } ! 553: | PARMCT { ! 554: $$ = parmCt(); } ! 555: ! 556: | numexp PLUS numexp { ! 557: $$ = $1 + $3; } ! 558: | numexp MINUS numexp { ! 559: $$ = $1 - $3; } ! 560: | numexp TIMES numexp { ! 561: $$ = $1 * $3; } ! 562: | numexp DIVIDE numexp { ! 563: $$ = $1 / $3; } ! 564: | numexp REM numexp { ! 565: $$ = $1 % $3; } ! 566: ! 567: | numexp LSHIFT numexp { ! 568: $$ = $1 << $3; } ! 569: | numexp RSHIFT numexp { ! 570: $$ = $1 >> $3; } ! 571: ! 572: ! 573: | numexp AND numexp { ! 574: $$ = $1 & $3; } ! 575: | numexp OR numexp { ! 576: $$ = $1 | $3; } ! 577: | numexp XOR numexp { ! 578: $$ = $1 ^ $3; } ! 579: | MINUS numexp %prec TIMES { ! 580: $$ = - $2; } ! 581: | BANG numexp { ! 582: $$ = !$2; } ! 583: | NOT numexp { ! 584: $$ = ~$2; } ! 585: ! 586: | string LBRACK numexp RBRACK { ! 587: $$ = ($3 > strlen($1)) ? 0 : $1[(short)$3]; } ! 588: | string AT string { ! 589: $$ = stringSearch($1, $3); } ! 590: | TONUMBER string { ! 591: $$ = atol($2); } ! 592: | TONUMBER dblexp { ! 593: $$ = $2; }; ! 594: ! 595: string : TOKEN { ! 596: $$ = gcpy($1, 0); } ! 597: | LPAREN string RPAREN { ! 598: $$ = $2; } ! 599: | string PLUS string { ! 600: $$ = concat($1, $3); } ! 601: | string LPAREN numexp COMMA numexp RPAREN { ! 602: $$ = substr($1, $3, $5); } ! 603: | string LPAREN numexp RPAREN { ! 604: $$ = substr($1, $3, strlen($1) - $3); } ! 605: | TOSTRING numexp { ! 606: $$ = galloc(12); ! 607: sprintf($$, "%ld", $2); } ! 608: | TOSTRING dblexp { ! 609: $$ = galloc(20); ! 610: sprintf($$, "%g", $2); }; ! 611: ! 612: /* floating point done here */ ! 613: dblexp : FNUM { ! 614: $$ = $1; } ! 615: | LPAREN dblexp RPAREN { ! 616: $$ = $2; } ! 617: | dblexp PLUS dblexp { ! 618: $$ = $1 + $3; } ! 619: | dblexp MINUS dblexp { ! 620: $$ = $1 - $3; } ! 621: | dblexp TIMES dblexp { ! 622: $$ = $1 * $3; } ! 623: | dblexp DIVIDE dblexp { ! 624: $$ = $1 / $3; } ! 625: | MINUS dblexp %prec TIMES { ! 626: $$ = - $2; } ! 627: | TOFLOAT string { ! 628: $$ = strtod($2, (char **)NULL); } ! 629: | TOFLOAT numexp { ! 630: $$ = $2; }; ! 631:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.