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