|
|
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.