|
|
1.1 ! root 1: /* ! 2: * 80386 assembler commands. ! 3: * ytype function args ! 4: * CMD docmd parms ! 5: * DCMD docmd names ! 6: * ECMD ecmd name, expr ! 7: * NCMD docmd ! 8: * ICMD ncmd expr ! 9: * DATA dcmd data list ! 10: */ ! 11: #include <asm.h> ! 12: #include <symtab.h> ! 13: ! 14: static unsigned short ct; ! 15: ! 16: /* ! 17: * Check parm count. Print msg if one required. ! 18: */ ! 19: static ! 20: ckCount(no) ! 21: { ! 22: if(no == ct) ! 23: return(0); ! 24: yyerror("Found %d parms expected %d", ct, no); /**/ ! 25: return(1); ! 26: } ! 27: ! 28: /* ! 29: * Set up while ! 30: */ ! 31: static void ! 32: setUpWhile() ! 33: { ! 34: register macro *tmp; ! 35: macline *newl; ! 36: ! 37: newl = (macline *)alloc((unsigned)(sizeof(*newl) + strlen(lastL))); ! 38: strcpy(newl->line, lastL); ! 39: ! 40: newLevel(INWDEF); ! 41: ! 42: tmp = new(macro); ! 43: inMacDef = tmp; ! 44: lastDef = inMacDef->first = newl; ! 45: } ! 46: ! 47: /* ! 48: * Do commands with name, expr. ! 49: */ ! 50: ecmd(label, op, p, item) ! 51: opc *op; ! 52: parm *label, *p; ! 53: data *item; ! 54: { ! 55: long n = 0; ! 56: ! 57: labelIgnored(label); ! 58: ! 59: if (NULL != item) { ! 60: switch (item->type) { ! 61: case 'l': ! 62: n = item->d.l; ! 63: break; ! 64: case 'y': ! 65: if (op->kind == S_SET) ! 66: break; ! 67: default: ! 68: yyerror("Invalid operand type"); /**/ ! 69: return; ! 70: } ! 71: } ! 72: ! 73: switch (op->kind) { ! 74: case S_SEGMENT: /* change segments */ ! 75: segment(op, p, n); ! 76: break; ! 77: ! 78: case S_COMM: /* allocate data in a segment */ ! 79: comm(op, p, n); ! 80: break; ! 81: ! 82: case S_SET: ! 83: if(NULL == p) ! 84: yyerror("Name required"); ! 85: /* The format of \fBset\fR is ! 86: * \fB.set name, value\fR */ ! 87: else if (!strcmp(p->str, ".")) ! 88: doOrg(NULL, item); ! 89: else if (item->type == 'l') ! 90: symLookUp(p->str, S_XSYM, n, 0); ! 91: else ! 92: symLookUp(p->str, S_LOCAL, ! 93: item->d.y->loc, item->d.y->sg); ! 94: break; ! 95: ! 96: } ! 97: return 0; ! 98: } ! 99: ! 100: /* ! 101: * Do commands with string parms. ! 102: */ ! 103: docmd(label, op, p) ! 104: opc *op; ! 105: parm *p, *label; ! 106: { ! 107: ct = countList(p); ! 108: ! 109: switch(op->kind) { ! 110: /* ! 111: * This may be name value in some formats to avoid syntax error ! 112: * we bring it in as ytype CMD. We don't do dubug for those formats. ! 113: */ ! 114: case S_DEF: ! 115: labelIgnored(label); ! 116: coffDef(p); ! 117: break; ! 118: ! 119: case S_TAG: ! 120: labelIgnored(label); ! 121: coffTag(p); ! 122: break; ! 123: ! 124: case S_FILE: ! 125: labelIgnored(label); ! 126: coffFile(p); ! 127: break; ! 128: ! 129: case S_ENDF: ! 130: coffEndef(); ! 131: break; ! 132: ! 133: case S_INCLUDE: ! 134: if(ckCount(1)) ! 135: return(1); ! 136: fileOpen(p->str); ! 137: break; ! 138: ! 139: case S_MACRO: ! 140: if(NULL == label) { ! 141: yyerror("Macro definition must have a label"); /**/ ! 142: defMac("***", p, MACTYPE); ! 143: } ! 144: else ! 145: defMac(label->str, p, MACTYPE); ! 146: break; ! 147: ! 148: case S_EQUS: ! 149: defCt++; ! 150: if(NULL == label) { ! 151: yyerror(".define must have a label"); /**/ ! 152: defMac("***", p, MACSTR); ! 153: } ! 154: else ! 155: defMac(label->str, p, MACSTR); ! 156: break; ! 157: ! 158: case S_UNDEFINE: /* kill macro or define */ ! 159: for(; NULL != p; p = p->next) { ! 160: opDelete(p->str); ! 161: macDelete(p->str, MACSTR); ! 162: macDelete(p->str, MACTYPE); ! 163: } ! 164: break; ! 165: ! 166: case S_MEXIT: { ! 167: macctl *m; ! 168: ! 169: if(NULL == trueMac) { ! 170: yyerror(".mexit not in macro"); /**/ ! 171: break; ! 172: } ! 173: m = macExp; /* break out of any whiles */ ! 174: do { ! 175: m->curr = NULL; /* no more lines */ ! 176: } while(m->type != MACTYPE); ! 177: break; ! 178: } ! 179: ! 180: case S_ENDM: ! 181: yyerror("Unexpected .endm ignored"); /**/ ! 182: break; ! 183: ! 184: case S_MAC: ! 185: { ! 186: register macctl *tmp; ! 187: ! 188: umList(p); /* dont trash parms at end of line */ ! 189: tmp = new(macctl); ! 190: tmp->curr = macFound->first; ! 191: tmp->parms = p; ! 192: tmp->names = macFound->names; ! 193: tmp->expno = ++macNo; /* unique non zero macro expansion ct */ ! 194: tmp->type = MACTYPE; ! 195: tmp->prev = macExp; ! 196: trueMac = macExp = tmp; ! 197: if(NULL != label) ! 198: symLookUp(label->str, S_LOCAL, dot.loc, dot.sg); ! 199: } ! 200: break; ! 201: ! 202: case S_ERRATA: ! 203: nswitch = op->code; ! 204: break; ! 205: ! 206: case S_WARNINGS: ! 207: wswitch = op->code; ! 208: break; ! 209: ! 210: case S_OPORDER: ! 211: fswitch = op->code; ! 212: break; ! 213: ! 214: case S_BORDER: ! 215: bswitch = op->code; ! 216: break; ! 217: ! 218: case S_LMODE: ! 219: longMode = op->code; ! 220: break; ! 221: ! 222: case S_LIST: ! 223: if (pass == 2) ! 224: lswitch = op->code & lswitchX; ! 225: break; ! 226: ! 227: case S_ALIGNON: ! 228: alignon = op->code; ! 229: break; ! 230: ! 231: case S_EJECT: ! 232: if (lswitch && (2 == pass) && pswitch) ! 233: while (linect) { ! 234: sTitle(); ! 235: putchar('\n'); ! 236: } ! 237: break; ! 238: ! 239: case S_PAGE: ! 240: pswitch = op->code; ! 241: break; ! 242: ! 243: case S_MLIST: ! 244: if (pass == 2) { ! 245: if(!strcmp("on", p->str)) ! 246: mlistsw = 1; ! 247: else if(!strcmp("off", p->str)) ! 248: mlistsw = 0; ! 249: else ! 250: yyerror( ! 251: "Invalid .mlist option must be on or off"); ! 252: /**/ ! 253: } ! 254: break; ! 255: ! 256: case S_ERROR: ! 257: if (op->code) ! 258: yyerror("%s", p->str); /* NODOC */ ! 259: else ! 260: yywarn("%s", p->str); /* NODOC */ ! 261: break; ! 262: ! 263: case S_CMNT: /* ident and version */ ! 264: if (2 == pass) ! 265: cmnt(op, p); ! 266: break; ! 267: ! 268: case S_SECTION: ! 269: if (!ct) { ! 270: yyerror(".section must have name"); /**/ ! 271: return; ! 272: } ! 273: section(p->str); ! 274: break; ! 275: ! 276: case S_TITLE: { ! 277: static short i = 0; ! 278: ! 279: /* Ignore all but first title on pass 0 */ ! 280: if((2 == pass) || !i) { ! 281: pswitch = i = 1; ! 282: free(title); ! 283: title = scpy(p->str, 0); ! 284: } ! 285: break; ! 286: } ! 287: ! 288: case S_ENDW: ! 289: if((NULL != macExp) && (WHILETYPE == macExp->type)) ! 290: macExp->curr = macExp->first; ! 291: else ! 292: yyerror("Unexpected .endw"); /**/ ! 293: break; ! 294: ! 295: case S_ENDI: ! 296: switch(logic->type) { ! 297: case INIF1: ! 298: freeLevel(); ! 299: break; ! 300: case NORMAL: ! 301: yyerror("Unexpected .endi statement"); /**/ ! 302: break; ! 303: default: ! 304: fatal(".endi detected logic type %d", logic->type); ! 305: /* TECH */ ! 306: } ! 307: break; ! 308: ! 309: case S_ELSE: ! 310: switch(logic->type) { ! 311: case INIF1: ! 312: logic->type = INIF0; ! 313: break; ! 314: case NORMAL: ! 315: yyerror("Unexpected .else statement"); /**/ ! 316: break; ! 317: default: ! 318: fatal(".else detected logic type %d", logic->type); ! 319: /* TECH */ ! 320: } ! 321: break; ! 322: ! 323: default: ! 324: kindErr((unsigned short)op->kind); ! 325: } ! 326: ! 327: return(0); ! 328: } ! 329: ! 330: /* ! 331: * Commands with a numexp as parm. ! 332: */ ! 333: ncmd(label, op, item) ! 334: parm *label; ! 335: opc *op; ! 336: data *item; ! 337: { ! 338: long n; ! 339: data oper; ! 340: ! 341: switch (item->type) { ! 342: case 'l': ! 343: n = item->d.l; ! 344: break; ! 345: case 'y': ! 346: if ((op->kind == S_EQU) || (op->kind == S_VAL)) ! 347: break; ! 348: default: ! 349: yyerror("Invalid operand type"); /* NODOC */ ! 350: return; ! 351: } ! 352: ! 353: switch(op->kind) { ! 354: case S_TYPE: ! 355: coffType(n); ! 356: break; ! 357: case S_VAL: ! 358: coffVal(item); ! 359: break; ! 360: case S_LN: ! 361: coffLn(n); ! 362: break; ! 363: case S_LINE: ! 364: coffLine(n); ! 365: break; ! 366: case S_SIZE: ! 367: coffSize(n); ! 368: break; ! 369: case S_SCL: ! 370: coffScl(n); ! 371: break; ! 372: case S_ZERO: ! 373: buildlab(label); ! 374: while(n--) ! 375: outab(0); ! 376: break; ! 377: ! 378: case S_BLKB: ! 379: buildlab(label); ! 380: oper.d.l = dot.loc + n; ! 381: oper.type = 'l'; ! 382: doOrg(NULL, &oper); ! 383: return; ! 384: case S_SHIFT: ! 385: doShift((short)n); ! 386: break; ! 387: case S_EQU: ! 388: if (NULL == label) ! 389: yyerror("Label required"); /**/ ! 390: else if (!strcmp(label->str, ".")) ! 391: doOrg(NULL, item); ! 392: else if (item->type == 'l') ! 393: symLookUp(label->str, S_XSYM, n, 0); ! 394: else { ! 395: symLookUp(label->str, S_LOCAL, ! 396: item->d.y->loc, item->d.y->sg); ! 397: ! 398: /* forward equate make sure there is an extra pass */ ! 399: if (!pass && (item->d.y->flag & S_UNDEF)) ! 400: xpass = 1; ! 401: ! 402: if (item->d.y->flag & (S_COMMON|S_EXREF)) ! 403: yyerror("Cannot equate to externally defined symbol"); ! 404: /* This would mean creating another symbol. ! 405: * Try using \fB.define\fR. */ ! 406: } ! 407: return; ! 408: case S_PLEN: /* set page length */ ! 409: nlpp = n - 10; ! 410: break; ! 411: case S_LLEN: /* set line length */ ! 412: lineSize = n; ! 413: break; ! 414: case S_IF: ! 415: newLevel(n ? INIF1 : INIF0); ! 416: break; ! 417: case S_WHILE: ! 418: if((NULL != macExp) && ! 419: (WHILETYPE == macExp->type) && ! 420: (macExp->curr == macExp->first->next)) { ! 421: if(!n) { ! 422: freeList((parm *)macExp->first); ! 423: macExp->curr = NULL; ! 424: } ! 425: } ! 426: else ! 427: setUpWhile(); ! 428: break; ! 429: default: ! 430: kindErr((unsigned short)op->kind); ! 431: } ! 432: ! 433: labelIgnored(label); ! 434: } ! 435: /* ! 436: * Make an expression for dataOut. ! 437: */ ! 438: expr * ! 439: makeExp(addr) ! 440: data *addr; ! 441: { ! 442: static expr x; ! 443: ! 444: x.ref = addr->d.y; ! 445: x.exp = x.ref->loc; ! 446: if (x.ref->flag & (S_COMMON|S_EXREF)) ! 447: x.exp <<= 1; /* double we will loose it back */ ! 448: return(&x); ! 449: } ! 450: ! 451: /* ! 452: * Data output for .byte .word .long .string .float .double ! 453: */ ! 454: static void ! 455: dataOut(op, oper) ! 456: opc *op; ! 457: data *oper; ! 458: { ! 459: register char *str, c; ! 460: union { ! 461: long l[2]; ! 462: float f[2]; ! 463: double d; ! 464: } u; ! 465: ! 466: if(op->code && (op->code != 5) && ('s' == oper->type)) { ! 467: yyerror("String must be on .byte"); ! 468: /* For example: ! 469: * .DM ! 470: * .byte "This is how we place a string", 0 ! 471: * .DE */ ! 472: return; ! 473: } ! 474: while(oper->count--) { /* honor repeat count */ ! 475: switch(op->code) { /* set by option */ ! 476: case 5: /* .string */ ! 477: if ('s' != oper->type) { ! 478: yyerror("Improper .string operand"); ! 479: return; ! 480: } ! 481: for(str = oper->d.s; c = *str++; ) ! 482: outab((unsigned short)c); ! 483: outab(0); ! 484: break; ! 485: case 0: /* .byte */ ! 486: switch(oper->type) { ! 487: case 's': ! 488: for(str = oper->d.s; c = *str++; ) ! 489: outab((unsigned short)c); ! 490: break; ! 491: case 'y': ! 492: outrb(makeExp(oper), 0); ! 493: break; ! 494: case 'l': ! 495: outab((unsigned)oper->d.l); ! 496: break; ! 497: case 'd': ! 498: outab((unsigned)oper->d.d); ! 499: break; ! 500: } ! 501: break; ! 502: case 1: /* .word or .value */ ! 503: switch(oper->type) { ! 504: case 'y': ! 505: outrw(makeExp(oper), 0); ! 506: break; ! 507: case 'l': ! 508: outaw((unsigned)oper->d.l); ! 509: break; ! 510: case 'd': ! 511: outaw((unsigned)oper->d.d); ! 512: break; ! 513: } ! 514: break; ! 515: case 2: /* .long */ ! 516: switch(oper->type) { ! 517: case 'y': ! 518: outrl(makeExp(oper), 0); ! 519: break; ! 520: case 'l': ! 521: outal(oper->d.l); ! 522: break; ! 523: case 'd': ! 524: outal((long)oper->d.d); ! 525: break; ! 526: } ! 527: break; ! 528: case 3: /* .float */ ! 529: switch(oper->type) { ! 530: case 'y': ! 531: yyerror("Symbol may not be float"); ! 532: /* You may not convert a symbol to ! 533: * a floating-point value. */ ! 534: return; ! 535: case 'l': ! 536: u.f[0] = oper->d.l; ! 537: break; ! 538: case 'd': ! 539: u.f[0] = oper->d.d; ! 540: } ! 541: #if _DECVAX ! 542: ieee_f(u.f, u.f); /* DECVAX to IEEE */ ! 543: #endif ! 544: outal(u.l[0]); ! 545: break; ! 546: case 4: /* .double */ ! 547: switch(oper->type) { ! 548: case 'y': ! 549: yyerror("Symbol may not be double"); ! 550: /* You may not convert a symbol to ! 551: * a floating-point value. */ ! 552: return; ! 553: case 'l': ! 554: u.d = oper->d.l; ! 555: break; ! 556: case 'd': ! 557: u.d = oper->d.d; ! 558: } ! 559: #if _DECVAX ! 560: ieee_d(&u.d, &u.d); /* DECVAX to IEEE */ ! 561: #endif ! 562: outal(u.l[0]); ! 563: outal(u.l[1]); ! 564: ! 565: break; ! 566: } ! 567: } ! 568: } ! 569: ! 570: /* ! 571: * Output alignment bytes. ! 572: */ ! 573: static int ! 574: alignOut(seg, byte, n) ! 575: { ! 576: int rv = 0; ! 577: ! 578: switch (seg) { ! 579: case 0: /* fill selected by user */ ! 580: while (dot.loc & n) { ! 581: rv = 1; ! 582: outab(byte); ! 583: } ! 584: break; ! 585: case 1: /* text */ ! 586: while (dot.loc & n) { ! 587: rv = 1; ! 588: outab(0x90); ! 589: } ! 590: break; ! 591: case 2: /* data */ ! 592: while (dot.loc & n) { ! 593: rv = 1; ! 594: outab(0); ! 595: } ! 596: break; ! 597: } ! 598: return rv; ! 599: } ! 600: ! 601: /* ! 602: * Commands with a list of data as parm. ! 603: */ ! 604: dcmd(label, op, oper) ! 605: parm *label; ! 606: opc *op; ! 607: data *oper; ! 608: { ! 609: register sym *sp = NULL; ! 610: register sym *y; ! 611: long start, n; ! 612: char b, s; ! 613: ! 614: switch (op->kind) { ! 615: case S_ORG: ! 616: return(doOrg(label, oper)); ! 617: ! 618: case S_EVEN: /* this is here to fall into .align */ ! 619: s = dot.sg; ! 620: n = 1; ! 621: goto even; ! 622: ! 623: case S_ALIGN: ! 624: if (NULL == oper) { ! 625: yyerror("Missing operand"); ! 626: /* \fB\&.align\fR must have 1 or 2 operands */ ! 627: return(1); ! 628: } ! 629: switch (oper->type) { ! 630: case 'l': ! 631: n = oper->d.l; ! 632: break; ! 633: default: ! 634: yyerror("Invalid operand type"); /* NODOC */ ! 635: return(1); ! 636: } ! 637: if ((3 != (s = dot.sg)) && (NULL != (oper = oper->next))) { ! 638: switch (oper->type) { ! 639: case 'l': ! 640: s = 0; ! 641: b = oper->d.l; ! 642: break; ! 643: default: ! 644: yyerror("Invalid operand type"); /* NODOC */ ! 645: return(1); ! 646: } ! 647: } ! 648: ! 649: if (!--n) ! 650: return; ! 651: if ((1 != n) && (3 != n)) { ! 652: yyerror(".align must be 1, 2 or 4"); ! 653: /* \fB\&.align\fR must work after the link. ! 654: * These are the only values for which this can be true. */ ! 655: return(1); ! 656: } ! 657: ! 658: even: if (3 == dot.sg) { ! 659: oper.d.l = (dot.loc + n) & ~n; ! 660: oper.type = 'l'; ! 661: doOrg(NULL, &oper); ! 662: } ! 663: else ! 664: alignOut(s, b, n); ! 665: return(0); ! 666: ! 667: case S_DATA: ! 668: /* If alignment on and data and not .string or .byte */ ! 669: if (!alignon) ! 670: break; ! 671: switch (op->code) { ! 672: case 1: ! 673: s = alignOut(dot.sg, 0, 1); ! 674: break; ! 675: case 2: ! 676: case 3: ! 677: case 4: ! 678: s = alignOut(dot.sg, 0, 3); ! 679: } ! 680: if (s) /* Alignment stuff went out */ ! 681: outLine("", ' '); ! 682: } ! 683: ! 684: if(NULL != label) { ! 685: switch (op->kind) { ! 686: case S_DATA: ! 687: case S_UDATA: ! 688: sp = symLookUp(label->str, S_LOCAL, ! 689: (start = dot.loc), dot.sg); ! 690: break; ! 691: default: ! 692: labelIgnored(label); ! 693: } ! 694: } ! 695: ! 696: for(b = 0; NULL != oper; oper = oper->next) { ! 697: switch (op->kind) { ! 698: case S_DATA: ! 699: case S_UDATA: ! 700: dataOut(op, oper); ! 701: continue; ! 702: case S_DIM: ! 703: if ('l' != oper->type) { ! 704: yyerror("Invalid data type, must be number"); ! 705: /**/ ! 706: continue; ! 707: } ! 708: coffDim(oper->d.l, b++); ! 709: continue; ! 710: case S_GLOBL: /* .globl */ ! 711: if('y' != oper->type) { ! 712: yyerror("Invalid data type, must be symbol"); ! 713: /**/ ! 714: continue; ! 715: } ! 716: y = oper->d.y; ! 717: if(!(y->flag & S_ASYM)) { ! 718: yyerror("Illegal use of of predefined symbol %s.", ! 719: (psym *)y->name); /**/ ! 720: continue; ! 721: } ! 722: if (NULL != strchr(y->name, ';')) { ! 723: yyerror("Illegal use of local symbol"); /**/ ! 724: continue; ! 725: } ! 726: if (y->flag & S_UNDEF) { ! 727: y->loc = 0; ! 728: y->sg = 0; ! 729: y->flag = S_EXREF; ! 730: } ! 731: else ! 732: y->flag |= S_EXDEF; ! 733: continue; ! 734: default: ! 735: kindErr((unsigned short)op->kind); ! 736: return(1); ! 737: } ! 738: } ! 739: ! 740: if(NULL != sp) /* finish label building */ ! 741: sp->size = dot.loc - start; ! 742: return(0); ! 743: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.