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