|
|
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: #if AS
33: char *ll_format = "*%c%06d";
34: #else C2
35: char *ll_format = "LX%c%06d";
36: #endif
37:
38: int ll_val[10];
39:
40: static struct suffix {
41: int indx_sx; /* index register */
42: int scale_sx; /* index scaling */
43: long disp_sx; /* displacement */
44: struct sym_bkt *sym_sx; /* symbolic displacement */
45: unsigned flags_sx; /* see below */
46: } fix [2];
47:
48: static struct suffix zero_suffix = { 0 };
49:
50: /* flags_sx values */
51: #define SX_INDXW 1 /* word-size index specified */
52: #define SX_INDXL 2 /* long-size index specified */
53: #define SX_DISPW 4 /* word-size displacement specified */
54: #define SX_DISPL 8 /* long-size displacement specified */
55: #define SX_GOTINDEX 020 /* index register specified */
56: #define SX_GOTDISP 040 /* displacement specified */
57: #if C2
58: #define SX_CXDISP 0100 /* displacement is complex */
59: #endif
60:
61: static struct oper zero_oper = { T_NULL, 0, 0, NULL, 0, 0, 0};
62:
63: char *suffix(), *exp(), *term(), *scan_reg_or_immed();
64: char * scan_float();
65: double atof();
66:
67: /*
68: * Fetches operand value and register subfields and loads them into
69: * the operand structure. This routine will fetch only one set of value
70: * and register subfields. It will move line pointer to first untouched char.
71: */
72: char *
73: soperand(lptr,opnd)
74: register char *lptr;
75: struct oper *opnd;
76: {
77: struct oper spare_oper;
78: int v;
79:
80: *opnd = zero_oper;
81: spare_oper = zero_oper;
82:
83: if ((v=cinfo[*lptr]) == IMM) {
84: lptr = exp(++lptr,opnd);
85: if (opnd->type_o == T_REG)
86: PROG_ERROR(E_REG);
87: if (opnd->type_o == T_FLOAT)
88: /* immediate value is floating-point */
89: opnd->flags_o |= O_FLOAT;
90: opnd->type_o = T_IMMED;
91: } else if (v == IND) {
92: /* index mode, omitted base */
93: /* expecting LP next */
94: lptr += 1;
95: skipb(lptr);
96: if (cinfo[*lptr] == LP)
97: goto index_mode;
98: else
99: PROG_ERROR(E_OPERAND);
100: } else {
101: lptr = exp(lptr,opnd);
102: skipb(lptr);
103: switch (opnd->type_o){
104: case T_REG:
105: switch (cinfo[*lptr]){
106: case COL:
107: /* should be a register pair */
108: lptr = exp( ++lptr, &spare_oper);
109: if (spare_oper.type_o != T_REG)
110: PROG_ERROR(E_OPERAND);
111: #if AS
112: if (!ext_instruction_set)
113: PROG_ERROR(E_OPERAND);
114: #endif
115: opnd->type_o = T_REGPAIR;
116: opnd->reg_o = spare_oper.value_o;
117: break;
118: case IND:
119: if (!(areg(opnd->value_o)||pcreg(opnd->value_o)))
120: PROG_ERROR(E_OPERAND);
121: lptr += 1;
122: skipb(lptr);
123: switch (cinfo[*lptr]){
124: default:
125: opnd->type_o = T_DEFER;
126: break;
127: case ADD:
128: opnd->type_o = T_POSTINC;
129: lptr++;
130: break;
131: case SUB:
132: opnd->type_o = T_PREDEC;
133: lptr++;
134: break;
135: case LP:
136: /* defer or indexing coming up here */
137: index_mode:
138: lptr = suffix( lptr, &fix[0] );
139: if (cinfo[*lptr] != IND){
140: simplify1( opnd, &fix[0] );
141: } else {
142: lptr = suffix( ++lptr, &fix[1] );
143: simplify2( opnd, &fix[0], &fix[1] );
144: }
145: break;
146: case IND:
147: lptr = suffix( ++lptr, &fix[1] );
148: simplify2( opnd, &zero_suffix, &fix[1] );
149: break;
150: }
151: #if AS
152: if (opnd->type_o == T_INDEX && !ext_instruction_set)
153: if ( (opnd->flags_o&(O_BSUPRESS|O_INDIRECT|O_WDISP|O_LDISP)) ||
154: opnd->scale_o != 1 || !(opnd->flags_o&O_PREINDEX))
155: PROG_ERROR( E_OPERAND );
156: #endif
157: /* flow through */
158: default:
159: break;
160: }
161: break;
162: case T_NORMAL:
163: if (cinfo[*lptr] == COL ){
164: switch (*++lptr) {
165: case 'W':
166: case 'w': opnd->type_o = T_ABSS;
167: lptr++;
168: break;
169: case 'L':
170: case 'l': opnd->type_o = T_ABSL;
171: lptr++;
172: break;
173: }
174: }
175: if (cinfo[*lptr] == IND)
176: goto index_mode;
177: break;
178: }
179: }
180: skipb( lptr );
181: if ( cinfo[ *lptr ] == LB ) {
182: /* oh, boy, bitfields */
183: opnd->flags_o |= O_BFLD;
184: spare_oper = zero_oper;
185: lptr = scan_reg_or_immed( lptr+1, &spare_oper);
186: v = spare_oper.value_o;
187: if (spare_oper.type_o == T_REG){
188: opnd->flags_o |= O_BFOREG;
189: } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) || v < 0 || v > 31){
190: PROG_ERROR(E_CONSTANT);
191: }
192: opnd->bfoffset_o = v;
193: skipb( lptr );
194: if ( cinfo[ *lptr ] == COL)
195: lptr ++;
196: else
197: PROG_ERROR(E_OPERAND);
198: spare_oper = zero_oper;
199: lptr = scan_reg_or_immed( lptr, &spare_oper);
200: v = spare_oper.value_o;
201: if (spare_oper.type_o == T_REG){
202: opnd->flags_o |= O_BFWREG;
203: } else if ((spare_oper.sym_o && !(spare_oper.sym_o->attr_s&S_DEF)) || v < 0 || v > 31){
204: PROG_ERROR(E_CONSTANT);
205: }
206: opnd->bfwidth_o = v;
207: skipb( lptr );
208: if ( cinfo[ *lptr ] == RB )
209: lptr++;
210: else
211: PROG_ERROR(E_OPERAND);
212: }
213: return(lptr);
214: } /* end soperand */
215:
216: static char *
217: scan_reg_or_immed( lptr, o )
218: register char *lptr;
219: register struct oper *o;
220: {
221: skipb( lptr );
222: if (cinfo[*lptr] == IMM) {
223: lptr = exp(++lptr,o);
224: if (o->type_o == T_REG)
225: PROG_ERROR(E_REG);
226: if (o->sym_o && !(o->sym_o->attr_s&S_DEF))
227: PROG_ERROR(E_REG);
228: o->type_o = T_IMMED;
229: } else {
230: lptr = exp( lptr, o );
231: if ( o->type_o != T_REG || o->value_o > D7REG)
232: PROG_ERROR(E_OPERAND);
233: }
234: return lptr;
235: }
236:
237: static char *
238: opt_length( lptr, fp, wflag, lflag )
239: register char * lptr;
240: struct suffix * fp;
241: {
242: char * save = lptr;
243: if (cinfo[ *lptr ] == COL){
244: lptr++;
245: skipb( lptr );
246: switch ( *lptr ){
247: case 'l':
248: case 'L':
249: fp->flags_sx |= lflag;
250: lptr++;
251: break;
252: case 'w':
253: case 'W':
254: fp->flags_sx |= wflag;
255: lptr++;
256: break;
257: default: return save; /* : yes, length, no: may be scale */
258: }
259: }
260: return lptr;
261: }
262: static char *
263: opt_scale( lptr, fp )
264: char * lptr;
265: struct suffix * fp;
266: {
267: fp->scale_sx = 1;
268: if (cinfo[ *lptr ] == COL){
269: lptr++;
270: skipb( lptr );
271: switch ( *lptr ){
272: case '1':
273: case '2':
274: case '4':
275: case '8':
276: fp->scale_sx = *lptr - '0';
277: lptr++;
278: break;
279: default: PROG_ERROR(E_OPERAND);
280: }
281: }
282: return lptr;
283: }
284:
285: static char *
286: suffix( lptr, fixp )
287: register char * lptr;
288: register struct suffix * fixp;
289: {
290: /*
291: * scan for open paran. look for displacement, optional length
292: * specifier, then index register, optional length specifier, optional
293: * scale specifier.
294: * fill in suffix structure with what we find.
295: */
296: struct oper o;
297: o = zero_oper;
298: *fixp = zero_suffix;
299: skipb( lptr );
300: if (cinfo[ *lptr ] == LP )
301: lptr += 1;
302: else
303: return lptr; /* guess that null suffix might be ok */
304: lptr = exp( lptr , &o );
305: if ( o.type_o == T_NORMAL ){
306: fixp->disp_sx = o.value_o;
307: fixp->sym_sx = o.sym_o;
308: fixp->flags_sx |= SX_GOTDISP;
309: #if C2
310: if (o.flags_o&O_COMPLEX)
311: fixp->flags_sx |= SX_CXDISP;
312: #endif
313: lptr = opt_length( lptr, fixp, SX_DISPW, SX_DISPL );
314: skipb( lptr );
315: if (cinfo[ *lptr ] == COM)
316: lptr = exp( ++lptr, &o );
317: else
318: goto scan_rp;
319: }
320: /* now we're talking index */
321: if ( o.type_o != T_REG ){
322: PROG_ERROR( E_OPERAND);
323: }
324: fixp->flags_sx |= SX_GOTINDEX;
325: fixp->indx_sx = o.value_o;
326: lptr = opt_length( lptr, fixp, SX_INDXW, SX_INDXL );
327: lptr = opt_scale( lptr, fixp );
328: scan_rp:
329: skipb( lptr );
330: if (cinfo[ *lptr ] == RP)
331: lptr ++;
332: else
333: PROG_ERROR( E_OPERAND);
334: return lptr;
335: }
336:
337: static
338: simplify1( oper, fp )
339: register struct oper * oper;
340: register struct suffix *fp;
341: {
342: register bval = oper->value_o;
343: /* we have some form of deferred or indexed addressing here */
344: /* try to make the best of it. */
345: /*
346: * examples are:
347: * a0@(disp)
348: * a0@(disp,d0:w:2)
349: * a0@(d0:w:2)
350: * pc@(disp)
351: * pc@(disp,d0:w:2)
352: * pc@(d0:w:2)
353: * @(d0)
354: * @(disp,d0)
355: */
356: switch (oper->type_o){
357: case T_REG:
358: if( !(fp->flags_sx&(SX_GOTINDEX|SX_DISPL)) ){
359: /* displacement mode */
360: oper->type_o = T_DISPL;
361: oper->reg_o = bval;
362: oper->value_o = fp->disp_sx;
363: oper->sym_o = fp->sym_sx;
364: } else {
365: /* index mode */
366: imode:
367: oper->type_o = T_INDEX;
368: oper->reg_o = bval;
369: oper->disp_o = fp->disp_sx;
370: oper->sym_o = fp->sym_sx;
371: if (fp->flags_sx&SX_GOTINDEX){
372: oper->value_o = fp->indx_sx;
373: oper->scale_o = fp->scale_sx;
374: if (fp->flags_sx&SX_INDXW)
375: oper->flags_o|= O_WINDEX|O_PREINDEX;
376: else
377: oper->flags_o|= O_LINDEX|O_PREINDEX;
378: } else {
379: oper->value_o = 0;
380: oper->scale_o = 0;
381: }
382: if (fp->flags_sx & SX_DISPL)
383: oper->flags_o|= O_LDISP;
384: else if (fp->flags_sx & SX_DISPW)
385: oper->flags_o|= O_WDISP;
386: /* else short form indexing */
387: }
388: break;
389: case T_NULL:
390: /* @(disp,d0) */
391: /* @(d0) */
392: /* index mode, supressed base */
393: oper->type_o= T_INDEX;
394: oper->flags_o|= O_BSUPRESS;
395: oper->reg_o = A0REG; /* Supress THIS register */
396: oper->disp_o= fp->disp_sx;
397: oper->sym_o= fp->sym_sx;
398: if(fp->flags_sx & SX_DISPL)
399: oper->flags_o |= O_LDISP;
400: else if (fp->flags_sx & SX_DISPW)
401: oper->flags_o |= O_WDISP;
402: do_index:
403: if (fp->flags_sx & SX_GOTINDEX){
404: oper->value_o = fp->indx_sx;
405: oper->scale_o = fp->scale_sx;
406: if (fp->flags_sx & (SX_INDXW) )
407: oper->flags_o |= O_PREINDEX|O_WINDEX;
408: else
409: oper->flags_o |= O_PREINDEX|O_LINDEX;
410: } else {
411: oper->value_o = 0;
412: oper->scale_o = 0;
413: }
414: break;
415: case T_ABSS:
416: oper->flags_o = O_WDISP;
417: goto normal;
418: case T_ABSL:
419: oper->flags_o = O_LDISP;
420: goto normal;
421: case T_NORMAL:
422: /* disp@ */
423: /* disp@(d0) */
424: /* index mode, supressed base */
425: oper->flags_o = 0;
426: normal:
427: oper->type_o = T_INDEX;
428: oper->flags_o|= O_BSUPRESS;
429: oper->reg_o = A0REG; /* Supress THIS register */
430: oper->disp_o = oper->value_o;
431: if (fp->flags_sx&SX_GOTDISP)
432: PROG_ERROR(E_OPERAND);
433: goto do_index;
434: default:
435: PROG_ERROR(E_OPERAND);
436: }
437: #if C2
438: if (fp->flags_sx&SX_CXDISP)
439: oper->flags_o |= O_COMPLEX;
440: #endif
441: }
442:
443: static
444: simplify2( oper, fp, dfp )
445: register struct oper * oper;
446: struct suffix *fp;
447: register struct suffix *dfp;
448: {
449: /*
450: * we have a memory indirect operand.
451: * examples:
452: * a0@(disp:l,d0:l:4)@(disp:w)
453: * a0@(disp)@(disp,d0:l:4)
454: * a0@@
455: * @(disp,d0)@(disp)
456: * @(d0)@
457: * @(disp)@
458: * @(disp,d0)@
459: * @(disp)@(d0)
460: */
461: simplify1( oper, fp );
462: if (oper->type_o == T_DISPL){
463: oper->type_o = T_INDEX;
464: oper->disp_o = oper->value_o;
465: oper->value_o = 0;
466: }
467: /* now build on that with second suffix */
468: oper->flags_o |= O_INDIRECT;
469: oper->disp2_o = dfp->disp_sx;
470: oper->sym2_o = dfp->sym_sx;
471: if (dfp->flags_sx & SX_DISPL)
472: oper->flags_o |= O_LDISP2;
473: else if (dfp->flags_sx & SX_DISPW)
474: oper->flags_o |= O_WDISP2;
475: if (dfp->flags_sx & SX_GOTINDEX){
476: if (oper->flags_o&O_PREINDEX)
477: PROG_ERROR(E_OPERAND);
478: oper->value_o = dfp->indx_sx;
479: oper->flags_o |= O_POSTINDEX;
480: oper->scale_o = dfp->scale_sx;
481: if (dfp->flags_sx&SX_INDXW)
482: oper->flags_o |= O_WINDEX;
483: else
484: oper->flags_o |= O_LINDEX;
485: }
486:
487: #if C2
488: if (fp->flags_sx&SX_CXDISP)
489: oper->flags_o |= O_COMPLEX2;
490: #endif
491: }
492:
493: /* read expression */
494: char *
495: exp(lptr, arg1)
496: register char *lptr;
497: register struct oper *arg1;
498: {
499: struct oper arg2; /* holds value of right hand term */
500: register int i;
501: static struct oper zero_opr;
502: #if AS
503: # define MKCOMPLEX( op )
504: #endif
505: #if C2
506: # define MKCOMPLEX( op ) if (arg1->sym_o&&arg2.sym_o || \
507: arg1->flags_o&O_COMPLEX || arg2.flags_o&O_COMPLEX){ \
508: ocomplex( op, arg1, &arg2 ); continue; \
509: }
510: #endif
511:
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 AS
529: if (arg1->sym_o && arg2.sym_o)
530: if (pass==2) break;
531: #endif
532: MKCOMPLEX( ADD );
533: if (arg2.sym_o)
534: arg1->sym_o = arg2.sym_o;
535: arg1->value_o += arg2.value_o;
536: arg1->flags_o |= arg2.flags_o&O_COMPLEX;
537: continue;
538:
539: case MUL: lptr = term(++lptr,&arg2);
540: if (arg1->type_o==T_REG || arg2.type_o==T_REG)
541: break;
542: #if AS
543: if (arg1->sym_o || arg2.sym_o)
544: if (pass==2) break;
545: #endif
546: MKCOMPLEX( MUL );
547: arg1->value_o *= arg2.value_o;
548: arg1->flags_o |= arg2.flags_o&O_COMPLEX;
549: continue;
550:
551: case DIV: lptr = term( ++lptr, &arg2 );
552: if (arg1->type_o==T_REG || arg2.type_o==T_REG)
553: break;
554: #if AS
555: if (arg1->sym_o || arg2.sym_o)
556: if (pass==2) break;
557: else if (arg2.value_o == 0) arg2.value_o = 1;
558: #endif
559: MKCOMPLEX( DIV );
560: arg1->value_o /= arg2.value_o;
561: arg1->flags_o |= arg2.flags_o&O_COMPLEX;
562: continue;
563:
564: case SUB: lptr = term( ++lptr, &arg2 );
565: if (arg1->type_o==T_REG || arg2.type_o==T_REG)
566: break;
567: if (arg2.sym_o){ /* if B is relocatable, */
568: if (arg1->sym_o){ /* and A is relocatable, */
569: #if AS
570: if (arg2.sym_o->csect_s != arg1->sym_o->csect_s
571: && pass == 2){
572: break; /* break into error */
573: } else {
574: /* result is absolute (no offset) */
575: arg1->sym_o = NULL;
576: /* but not a simple address for sdi's */
577: arg1->flags_o |= O_COMPLEX;
578: }
579: #endif
580: #if C2
581: /* operand cannot be understood at this time */
582: ocomplex( SUB, arg1, &arg2 );
583: continue;
584: #endif
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: #undef MKCOMPLEX
598: } /* end exp <read expression> */
599:
600: /* read term: either symbol, constant, or unary minus */
601: char *
602: term( lptr, vp )
603: register char *lptr;
604: register struct oper *vp;
605: {
606: register struct sym_bkt *sbp;
607: register int base = 10;
608: register long val;
609: register char *p;
610: register int i;
611: char savechar, *t;
612: char token[50];
613:
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 'f':
639: /*
640: * be careful not to confuse the floating-point
641: * constant 0f0.0 with the local label reference * 0f .
642: * for legitimate floating constants, the next
643: * character can be a digit, a decimal point,
644: * a negative sign, or one of the letters
645: * 'n', 'N', 'i', or 'I'.
646: */
647: switch (*(lptr+1)){
648: case '0':case '1':case '2':case '3':case '4':
649: case '5': case '6':case '7':case '8':case '9':
650: case '.': case '-': case '+':
651: case 'n':case 'N': case 'i':case 'I':
652: break;
653: default:
654: val = 0;
655: goto got_a_number;
656: }
657: /* FALL THROUGH */
658: case 'F':
659: case 'R':
660: case 'r':
661: lptr = scan_float( lptr, vp );
662: return (lptr);
663: default:
664: /* octal number */
665: while (cinfo[*lptr] & D){
666: if (*lptr == '8' || *lptr == '9')
667: PROG_ERROR(E_CONSTANT);
668: val = val*8 + *lptr++ - '0';
669: }
670: }
671: } else {
672: /* decimal number */
673: while (cinfo[*lptr] & D)
674: val = val*10 + *lptr++ - '0';
675: }
676: got_a_number:
677: if (*lptr == '$')
678: { lptr = p; goto sym; }
679: if (*lptr == 'b' || *lptr == 'f'){
680: /* local label reference, of form [0-9][bh] */
681: /* single digits only */
682: if (lptr > p+1 ){
683: PROG_ERROR(E_SYMLEN);
684: }
685: val = ll_val[*p-'0'] + (*lptr++=='f');
686: if (val < 0 ) PROG_ERROR(E_SYMDEF);
687: sprintf(token, ll_format, *p, val);
688: sbp = lookup(token);
689: goto sym2;
690:
691: }
692: vp->value_o = val;
693: vp->sym_o = NULL;
694: vp->type_o = T_NORMAL;
695: return(lptr);
696: }
697:
698: /* here for symbol name */
699: if (i & S) {
700: sym: t = lptr;
701: while (cinfo[*lptr] & T)
702: lptr++;
703: savechar = *lptr;
704: *lptr = '\0';
705: sbp = lookup(t); /* find its symbol bucket */
706: *lptr = savechar;
707: sym2:
708: #if C2
709: sbp->nuse_s++;
710: #endif
711: if (sbp->attr_s & S_DEF
712: #if C2
713: && sbp->csect_s == C_UNDEF
714: #endif
715: ){
716: /* if it's defined, use its value */
717: vp->value_o = sbp->value_s;
718: } else
719: vp->value_o = 0;
720: if (sbp->attr_s & S_REG){
721: vp->type_o = T_REG;
722: vp->sym_o = NULL;
723: } else {
724: vp->sym_o = ((sbp->attr_s & S_DEF) &&
725: (sbp->csect_s == C_UNDEF )) ? 0 : sbp;
726: vp->type_o = T_NORMAL;
727: }
728: return(lptr);
729: }
730:
731: /* check for unary minus */
732: if (i == SUB) {
733: lptr = term(++lptr,vp);
734: if (vp->sym_o){
735: #if AS
736: PROG_ERROR(E_RELOCATE);
737: #endif
738: #if C2
739: if (vp->sym_o){
740: ocomplex( SUB, vp, 0);
741: return(lptr);
742: }
743: #endif
744: }
745: vp->value_o = -(vp->value_o);
746: return(lptr);
747: }
748:
749: /* check for complement */
750: if (i == NOT) {
751: lptr = term(++lptr,vp);
752: if (vp->sym_o){
753: #if AS
754: PROG_ERROR(E_RELOCATE);
755: #endif
756: #if C2
757: if (vp->sym_o){
758: ocomplex( NOT, vp, 0);
759: return(lptr);
760: }
761: #endif
762: }
763: vp->value_o = ~(vp->value_o);
764: return(lptr);
765: }
766:
767: /* here for string */
768: if (i == QUO) {
769: vp->stringval_o = lptr+1;
770: /* scan over the quoted string, being careful of \-stuff */
771: do{
772: i = *++lptr;
773: if (i=='\\')
774: switch (i = *++lptr){
775: case '"': i = '\\'; /* fake-out loop test by covering up \"*/
776: }
777: }while (i!='\n' && i!='"');
778: if (i == '\n'){
779: PROG_ERROR(E_STRING);
780: }
781: *lptr++ = 0;
782: vp->sym_o = NULL;
783: vp->type_o = T_STRING;
784: return(lptr);
785: }
786:
787: /* new, improved kluge -- parens !! */
788: if (i==LP) {
789: lptr = exp(++lptr, vp);
790: skipb(lptr);
791: if ((i=cinfo[*lptr]) == RP) {
792: lptr++;
793: } else {
794: PROG_ERROR( E_PAREN );
795: }
796: return( lptr );
797: }
798:
799: PROG_ERROR(E_TERM);
800: return(lptr);
801: } /* end term */
802:
803: char *
804: scan_float( lptr, vp )
805: register char * lptr;
806: struct oper *vp;
807: {
808: /*
809: * lptr address a string which is a 'd' or an 'f', followed
810: * by a floating-point number. The latter looks like:
811: * [+-]nan( [0-9a-f]+ )
812: * or [+-]inf
813: * or [+-][0-9]+[.[0-9]+][e[+-][0-9]+]
814: * in the latter case, we call atof to do the conversion work.
815: * We do not take great care in syntax checking the number.
816: */
817: int s=0;
818: union{ double d; float f; int x[2]; } fp;
819: unsigned nanno, nanno2;
820: register char *nbegin;
821: char c;
822:
823: lptr++; /* skip the f */
824: nbegin = lptr;
825: again:
826: switch ( *lptr++){
827: case '+': if (s) goto bad_num; s = 1; goto again;
828: case '-': if (s) goto bad_num; s = -1; goto again;
829: case 'N':
830: case 'n': /* nan */
831: if (*lptr++ != 'a') goto bad_num;
832: if (*lptr++ != 'n') goto bad_num;
833: if (*lptr++ != '(') goto bad_num;
834: nanno = nanno2 = 0;
835: while( isxdigit(c = *lptr++)){
836: if (isdigit(c)) c -= '0';
837: else if (isupper(c)) c -= 'a'-10;
838: else c -= 'A'-10;
839: nanno2 = (nanno2 << 8) | (nanno >> 24);
840: nanno = (nanno<<8) | c;
841: }
842: if (c != ')') goto bad_num;
843: goto make_indef;
844:
845: case 'I':
846: case 'i': /* inf */
847: if (*lptr++ != 'n') goto bad_num;
848: if (*lptr++ != 'f') goto bad_num;
849: if (strncmp(lptr,"inity",5) == 0)
850: lptr += 5;
851: nanno = nanno2 = 0;
852: make_indef:
853: fp.x[0] = ((s<0)?0xfff00000:0x7ff00000) | nanno2;
854: fp.x[1] = nanno;
855: break;
856: case '0': case '1': case '2': case '3': case '4':
857: case '5': case '6': case '7': case '8': case '9':
858: /* scan for more digits */
859: while( isdigit( c = *lptr++ ) )
860: continue;
861: if (c != '.' )
862: goto scan_exp;
863: /* FALL THROUGH */
864: case '.':
865: /* scan for more digits */
866: while( isdigit( c = *lptr++ ) )
867: continue;
868: scan_exp:
869: s = 0;
870: switch(c){
871: case '+':
872: case '-':
873: s = 1;
874: /* FALL THROUGH */
875: case 'e':
876: case 'E':
877: switch ( c= *lptr++ ){
878: case '+':
879: case '-':
880: if (s) goto bad_num;
881: c = *lptr++;
882: /* FALL THROUGH */
883: default:
884: s = 0; /* count chars: 0 is not ok */
885: while( isdigit(c) ){
886: c = *lptr++;
887: s++;
888: }
889: if (s == 0) goto bad_num;
890: break;
891: }
892: break;
893: }
894: fp.d = atof( nbegin );
895: lptr--;
896: break;
897: default:
898: bad_num:
899: PROG_ERROR( E_BADCHAR );
900: return lptr;
901: }
902: vp->fval_o = fp.d;
903: vp->type_o = T_FLOAT;
904: return lptr;
905: }
906:
907:
908: static void
909: printoffset( value, sym, cmplx )
910: int value;
911: struct sym_bkt *sym;
912: int cmplx;
913: {
914: register struct optree *ot;
915: register char c = '?';
916: struct oper *op;
917: if (cmplx){
918: ot = (struct optree*)sym;
919: if (ot->right_t == NULL){
920: /* unary operation */
921: switch(ot->op_t){
922: case SUB: c = '-'; break;
923: case NOT: c = '~'; break;
924: }
925: printf("%c(",c);
926: op=ot->left_t;
927: printoffset(op->value_o, op->sym_o, op->flags_o&O_COMPLEX);
928: putchar(')');
929: } else {
930: /* binary */
931: putchar('(');
932: op=ot->left_t;
933: printoffset(op->value_o, op->sym_o, op->flags_o&O_COMPLEX);
934: switch(ot->op_t){
935: case ADD: c = '+'; break;
936: case SUB: c = '-'; break;
937: case MUL: c = '*'; break;
938: case DIV: c = '/'; break;
939: }
940: printf(")%c(", c);
941: op=ot->right_t;;
942: printoffset(op->value_o, op->sym_o, op->flags_o&O_COMPLEX);
943: putchar(')');
944: }
945: return;
946: }
947: if (sym != NULL){
948: fputs(sym->name_s, stdout);
949: if (value)
950: printf("+%d", value);
951: } else {
952: printf("%d", value);
953: }
954: }
955:
956:
957: char *rnames[] = {
958: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
959: "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
960: "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7",
961: "cc", "fcc", "pc", "sr", "usp", "sfc", "dfc", "vbr",
962: "cacr", "caar", "msp", "isp", "fpc", "fps", "fpi"
963: };
964:
965: static void
966: printindex( o )
967: register struct oper *o;
968: {
969: printf("%s:%c", rnames[o->value_o], o->flags_o&O_WINDEX ? 'w' : 'l');
970: if (o->scale_o != 1) printf(":%d", o->scale_o);
971: }
972:
973: printoperand( o )
974: register struct oper *o;
975: {
976: switch (o->type_o){
977: case T_REG: printf("%s", rnames[o->value_o]); break;
978: case T_DEFER: printf("%s@", rnames[o->value_o]); break;
979: case T_POSTINC: printf("%s@+", rnames[o->value_o]); break;
980: case T_PREDEC: printf("%s@-", rnames[o->value_o]); break;
981: case T_DISPL: printf("%s@(", rnames[o->reg_o]);
982: printoffset(o->value_o, o->sym_o, o->flags_o&O_COMPLEX);
983: putchar(')');
984: break;
985: case T_INDEX:
986: if (!(o->flags_o&O_BSUPRESS)){
987: printf("%s@", rnames[o->reg_o]);
988: }
989: putchar('(');
990: printoffset(o->disp_o, o->sym_o, o->flags_o&O_COMPLEX);
991: if (o->flags_o & O_WDISP) fputs(":w", stdout);
992: else if (o->flags_o & O_LDISP) fputs(":l", stdout);
993: if (o->flags_o&O_PREINDEX){
994: putchar(',');
995: printindex( o );
996: }
997: putchar(')');
998: if (o->flags_o&O_INDIRECT){
999: putchar('@');
1000: if (o->disp2_o || o->sym2_o || o->flags_o&O_POSTINDEX){
1001: putchar('(');
1002: if (o->disp2_o || o->sym2_o ){
1003: printoffset(o->disp2_o, o->sym2_o, o->flags_o&O_COMPLEX2);
1004: if (o->flags_o&O_POSTINDEX)
1005: putchar(',');
1006: }
1007: if (o->flags_o&O_POSTINDEX){
1008: printindex( o );
1009: }
1010: putchar(')');
1011: }
1012: }
1013: break;
1014: case T_ABSS:
1015: case T_ABSL:
1016: printoffset(o->value_o, o->sym_o, o->flags_o&O_COMPLEX);
1017: fputs( (o->type_o == T_ABSS) ? ":w" : ":l", stdout);
1018: break;
1019: case T_IMMED:
1020: putchar('#');
1021: if (o->flags_o & O_FLOAT) goto float_val;
1022: /* FALL THROUGH */
1023: case T_NORMAL:
1024: printoffset(o->value_o, o->sym_o, o->flags_o&O_COMPLEX);
1025: break;
1026: case T_STRING:
1027: printf("\"%s\"", o->stringval_o);
1028: break;
1029: case T_REGPAIR: printf("%s:%s", rnames[o->value_o],rnames[o->reg_o]);
1030: break;
1031: float_val:
1032: case T_FLOAT: printf("0r%.17e", o->fval_o);
1033: break;
1034: default:
1035: printf("UNKNOWN(%d)", o->type_o);
1036: break;
1037: }
1038: if (o->flags_o&O_BFLD){
1039: /* bit field */
1040: /* first the offset part */
1041: if (o->flags_o&O_BFOREG)
1042: printf("{%s:",rnames[o->bfoffset_o]);
1043: else
1044: printf("{#%d:",o->bfoffset_o);
1045: /* then the width part */
1046: if (o->flags_o&O_BFWREG)
1047: printf("%s}",rnames[o->bfwidth_o]);
1048: else
1049: printf("#%d}",o->bfwidth_o);
1050: }
1051: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.