|
|
1.1 root 1: head 1.2;
2: access ;
3: symbols ;
4: locks bin:1.2;
5: comment @ * @;
6:
7:
8: 1.2
9: date 91.02.06.20.44.23; author bin; state Exp;
10: branches ;
11: next 1.1;
12:
13: 1.1
14: date 91.02.06.20.44.12; author bin; state Exp;
15: branches ;
16: next ;
17:
18:
19: desc
20: @steve 2/6/91
21: Initial MWC RCS revision.
22: @
23:
24:
25: 1.2
26: log
27: @steve 2/6/91
28: Extensive changes from cef: descriptive error messages, bug fixes,
29: who knows what else.
30: @
31: text
32: @/*
33: * Instruction formatting
34: * and decoding. This is for the Intel
35: * iAPX-86 microprocessor.
36: * Small addressing model (perhaps with
37: * separated CS and SS,DS,ES).
38: * No formatting for the large model calls,
39: * returns or jumps.
40: */
41: #include "asm.h"
42:
43: /*
44: * Branch map.
45: */
46: int *bp;
47: int bm;
48: int bb[NB];
49:
50: /*
51: * Read and format machine instructions.
52: * The argument `sp' is a pointer to the symbol
53: * table entry of the opcode. The `s_kind' field
54: * holds the operation kind; this determines the
55: * format and the semantics of the operation.
56: */
57: machine(sp)
58: struct sym *sp;
59: {
60: register op, m1, m2;
61: struct expr e1, e2;
62: int disp, flag, ob, rf, si, rn;
63:
64: op = sp->s_addr;
65: switch (sp->s_kind) {
66:
67: case S_EVEN:
68: if ((dot->s_addr&01) != 0) {
69: if (inbss == 0)
70: outab(0);
71: else
72: ++dot->s_addr;
73: }
74: lmode = ALIST;
75: break;
76:
77: case S_ODD:
78: if ((dot->s_addr&01) == 0) {
79: if (inbss == 0)
80: outab(0);
81: else
82: ++dot->s_addr;
83: }
84: lmode = ALIST;
85: break;
86:
87: case S_INH:
88: outab(op);
89: if (op==AAM || op==AAD) /* Need suffix byte */
90: outab(APB);
91: break;
92:
93: case S_INT:
94: expr(&e1, 0);
95: if (isabsn(&e1, 3)) {
96: outab(INT3);
97: break;
98: }
99: outab(INT);
100: outrb(&e1, 0);
101: break;
102:
103: case S_SYS:
104: expr(&e1, 0);
105: if (e1.e_type == E_ACON) {
106: outab(INT);
107: e1.e_addr += 128;
108: outrb(&e1, 0);
109: break;
110: }
111: aerr("expected constant");
112: break;
113:
114: case S_OVER:
115: if (addr(&e1) == SEGR) {
116: out3(SEGPFX, rof(e1));
117: break;
118: }
119: aerr("segment override by non-segment register");
120: break;
121:
122: case S_RET:
123: if (more() == 0) {
124: outab(op);
125: break;
126: }
127: expr(&e1, 0);
128: outab(op-1); /* Use ret n form */
129: outrw(&e1, 0);
130: break;
131:
132: case S_PUSH:
133: m1 = addr(&e1);
134: rn = rof(e1);
135: if (m1 == SEGR) {
136: if (op == PUSH)
137: out3(PUSHSR, rn);
138: else {
139: if (e1.e_mode == CS) /* No pop CS */
140: aerr("no 'pop CS' instruction");
141: out3(POPSR, rn);
142: }
143: break;
144: }
145: if (m1 == WR) {
146: if (op == PUSH)
147: outab(PUSHR | rn);
148: else
149: outab(POPR | rn);
150: break;
151: }
152: if ( m1 == IM ) {
153: if ( (e1.e_type == E_ACON)
154: && ( ((e1.e_addr & 0xFF80) == 0xFF80)
155: || ((e1.e_addr & 0xFF80) == 0x0000) ) ) {
156: outab( PUSHIB );
157: outab( e1.e_addr );
158: }
159: else {
160: outab( PUSHIW );
161: outrw(&e1, 0);
162: }
163: break;
164: }
165: outgen(op, ((op==PUSH) ? 6 : 0), &e1);
166: break;
167:
168: case S_IN:
169: m1 = addr(&e1);
170: comma();
171: m2 = addr(&e2);
172: IN_OUT:
173: if (m1 == WR && rof(e1) == AX)
174: op |= W;
175: else if (m1 == BR && rof(e1) == reg(AL))
176: op &= ~W;
177: else {
178: aerr("(in|out)(b|) must use AX or AL");
179: break;
180: }
181: if (m2 == WR && rof(e2) == DX) {
182: outab(op|010);
183: break;
184: } else if (m2 == DIR) {
185: outab(op);
186: outrb(&e2, 0);
187: break;
188: }
189: aerr("(in|out)(b|) must use DX or constant");
190: break;
191:
192: case S_OUT:
193: m2 = addr(&e2);
194: comma();
195: m1 = addr(&e1);
196: goto IN_OUT;
197:
198: case S_SHL:
199: case S_SHLB:
200: m1 = addr(&e1);
201: comma();
202: m2 = addr(&e2);
203: ob = SHL;
204: if (sp->s_kind == S_SHL)
205: ob |= W;
206: bytecheck(ob, m1, NONE);
207: if (m2 == BR && e2.e_addr == CL)
208: ob |= V;
209: else if ( (m2 == IM) && (e2.e_type == E_ACON) ) {
210: if ( e2.e_addr != 1 )
211: ob = (ob & W) ? (SHLI|W) : SHLI;
212: }
213: else
214: aerr("Improper shift amount");
215: outgen(ob, op, &e1);
216: if ( (ob & ~W) == SHLI )
217: outab( e2.e_addr );
218: break;
219:
220: case S_JMP:
221: if (addr(&e1) != DIR)
222: aerr("jmp must be direct address");
223: if (pass == 0) {
224: dot->s_addr += 3;
225: if (op != JMP)
226: dot->s_addr += 2;
227: } else if (pass == 1) {
228: if (e1.e_type != E_DIR
229: || e1.e_base.e_lp != dot->s_base.s_lp) {
230: /* long */
231: dot->s_addr += 3;
232: if (op != JMP)
233: dot->s_addr += 2;
234: flag = 1;
235: } else {
236: if (e1.e_addr >= dot->s_addr)
237: e1.e_addr -= fuzz;
238: dot->s_addr += 2;
239: disp = e1.e_addr - dot->s_addr;
240: flag = 0;
241: if (disp<-128 || disp>127) {
242: /* long */
243: flag = 1;
244: ++dot->s_addr;
245: if (op != JMP)
246: dot->s_addr += 2;
247: }
248: }
249: setbit(flag);
250: } else if (getbit()) {
251: if (op != JMP) {
252: outab(op ^ 01);
253: outab(03);
254: }
255: outab(0xE9);
256: outrw(&e1, 1);
257: } else {
258: disp = e1.e_addr - dot->s_addr - 2;
259: outab(op);
260: outab(disp);
261: }
262: break;
263:
264: case S_REL:
265: if (addr(&e1) != DIR
266: || e1.e_type != E_DIR
267: || e1.e_base.e_lp != dot->s_base.s_lp)
268: aerr("not a direct address in this segment");
269: disp = e1.e_addr - dot->s_addr - 2;
270: if (disp<-128 || disp>127)
271: aerr("address out of range");
272: outab(op);
273: outab(disp);
274: break;
275:
276: case S_IJMP:
277: addr(&e1);
278: outgen(IJORC, op, &e1);
279: break;
280:
281: case S_CALL:
282: if (addr(&e1) != DIR)
283: aerr("not a direct address");
284: outab(DCALL);
285: outrw(&e1, 1);
286: break;
287:
288: case S_DOP:
289: m1 = addr(&e1);
290: comma();
291: m2 = addr(&e2);
292: bytecheck(op, m1, m2);
293: if (m2 == IM) {
294: si = 0;
295: if (isalax(&e1)) {
296: if (op == TESTW)
297: op = TESTAW;
298: else if (op == TESTB)
299: op = TESTAB;
300: else
301: op |= 04;
302: outab(op);
303: } else {
304: if (op==TESTW || op==TESTB) {
305: rf = 0;
306: if (op == TESTW)
307: op = TESTMW;
308: else
309: op = TESTMB;
310: } else {
311: rf = (op&070)>>3;
312: op = (op&W)|0200;
313: if (ishort(sp, &e2)) {
314: ++si;
315: op |= S;
316: }
317: }
318: outgen(op, rf, &e1);
319: }
320: if (si || (op&W)==0)
321: outrb(&e2, 0);
322: else
323: outrw(&e2, 0);
324: break;
325: }
326: /* Dest is reg */
327: if (m1==BR || m1==WR) {
328: if (op!=TESTB && op!=TESTW)
329: op |= D;
330: outgen(op, rof(e1), &e2);
331: break;
332: }
333: /* Dest is mem */
334: outgen(op, rof(e2), &e1);
335: break;
336:
337: case S_XCHG:
338: m1 = addr(&e1);
339: comma();
340: m2 = addr(&e2);
341: bytecheck(op, m1, m2);
342: if (m1==WR && m2==WR) {
343: if (isalax(&e1)) {
344: outab(XCHGR | rof(e2));
345: break;
346: }
347: if (isalax(&e2)) {
348: outab(XCHGR | rof(e1));
349: break;
350: }
351: }
352: if (m1==BR || m1==WR) {
353: outgen(op, rof(e1), &e2);
354: break;
355: }
356: if (m2==BR || m2==WR) {
357: outgen(op, rof(e2), &e1);
358: break;
359: }
360: aerr("improper operand pair");
361: break;
362:
363: case S_SOP:
364: case S_SOPB:
365: m1 = addr(&e1);
366: ob = (op < 2) ? INCDEC : NOTNEG;
367: if (sp->s_kind == S_SOP)
368: ob |= W;
369: bytecheck(ob, m1, NONE);
370: if (op<2 && m1==WR) {
371: outab(IDREG | (op<<3) | rof(e1));
372: break;
373: }
374: outgen(ob, op, &e1);
375: break;
376:
377: case S_ESC:
378: addr(&e1);
379: outgen(ESC, 0, &e1);
380: break;
381:
382: case S_LEA:
383: m1 = addr(&e1);
384: comma();
385: m2 = addr(&e2);
386: if (m1!=WR)
387: aerr("must load address into register");
388: if(m2!=DIR && m2!=X)
389: aerr("must load direct address");
390: outgen(op, rof(e1), &e2);
391: break;
392:
393: case S_MOV:
394: m1 = addr(&e1);
395: comma();
396: m2 = addr(&e2);
397: bytecheck(op, m1, m2);
398: if (m2 == IM) {
399: if (m1 == BR) {
400: outab(MVIB | rof(e1));
401: outrb(&e2, 0);
402: break;
403: }
404: if (m1 == WR) {
405: outab(MVIW | rof(e1));
406: outrw(&e2, 0);
407: break;
408: }
409: /* To memory */
410: outgen((MVI|(op&W)), 0, &e1);
411: if ((op&W) == 0)
412: outrb(&e2, 0);
413: else
414: outrw(&e2, 0);
415: break;
416: }
417: /* Quick load */
418: if (isalax(&e1) && m2==DIR) {
419: outab(MOVMA|(op&W));
420: outrw(&e2, 0);
421: break;
422: }
423: /* Quick store */
424: if (m1==DIR && isalax(&e2)) {
425: outab(MOVAM|(op&W));
426: outrw(&e1, 0);
427: break;
428: }
429: if (m1 == SEGR)
430: outgen(MOVSEG|D, rof(e1), &e2);
431: else if (m2 == SEGR)
432: outgen(MOVSEG, rof(e2), &e1);
433: else if (m1==WR || m1==BR)
434: outgen(op|D, rof(e1), &e2);
435: else
436: outgen(op, rof(e2), &e1);
437: break;
438:
439: case S_MUL:
440: case S_MULB:
441: m1 = addr(&e1);
442: ob = MULDIV;
443: if (sp->s_kind == S_MUL)
444: ob |= W;
445: bytecheck(ob, m1, NONE);
446: outgen(ob, op, &e1);
447: break;
448: case S_PROT0:
449: case S_PROT1:
450: /*
451: * Protection control.
452: */
453: m1 = addr(&e1);
454: if ( (m1 != WR) && (m1 != DIR) && (m1 != X) )
455: aerr();
456: outab( 0x0F );
457: outgen( (sp->s_kind == S_PROT0) ? 0x00 : 0x01, op, &e1 );
458: break;
459:
460: case S_PROTR:
461: /*
462: * Protection control to register.
463: */
464: if ( op == ARPL ) {
465: m2 = addr(&e2);
466: comma();
467: m1 = addr(&e1 );
468: }
469: else if ( op == CLTS ) {
470: outab( 0x0F );
471: outab( op );
472: break;
473: }
474: else {
475: m1 = addr(&e1);
476: comma();
477: m2 = addr(&e2);
478: }
479: if (m1!=WR || (m2!=WR &&m2!=DIR && m2!=X))
480: aerr("Improper operand");
481: if ( op != ARPL )
482: outab( 0x0F );
483: outgen(op, rof(e1), &e2);
484: break;
485:
486: case S_ENTER:
487: m1 = addr(&e1);
488: comma();
489: m2 = addr(&e2);
490: if ( (m1 != DIR) || (e1.e_type != E_ACON)
491: || (m2 != DIR) || (e2.e_type != E_ACON) )
492: aerr();
493: outab( op );
494: outrw( &e1, 0);
495: outrb( &e2, 0 );
496: break;
497:
498: /* Floating point operations. */
499: /* No operands. */
500: case S_FP_F:
501: outab((sp->s_flag==S_NW) ? FNOP : FWAIT);
502: outab(BYTE1(op));
503: outab(BYTE2(op));
504: break;
505: /* Memory operand. */
506: case S_FP_M:
507: outab((sp->s_flag==S_NW) ? FNOP : FWAIT);
508: m1 = addr(&e1);
509: if (m1 != DIR && m1 != X)
510: qerr("invalid operand type");
511: outgen(BYTE1(op), BYTE2(op), &e1);
512: break;
513: /* Two optional fp stack operands. */
514: /* The opcode in the table is for the format "f<op> st<n>,st". */
515: /* Some nasty fudging here; thanks again, Intel. */
516: case S_FP_S:
517: outab(FWAIT);
518: if (fp_reg2(&e1, &e2)) {
519: if (e1.e_mode == ST) {
520: /* "f<op> st,st<n>". */
521: /* Change BYTE1 from 0xDC to 0xD8. */
522: outab(BYTE1(op)^4);
523: if (sp->s_flag == S_FIX)
524: outab((BYTE2(op)^8)|rof(e2));
525: else
526: outab(BYTE2(op)|rof(e2));
527: }
528: else {
529: /* "f<op> st<n>,st". */
530: outab(BYTE1(op));
531: outab(BYTE2(op)|rof(e1));
532: }
533: }
534: else { /* No args supplied; "f<op>" means "f<op>p st1,st". */
535: /* Change BYTE1 from 0xDC to 0xDE. */
536: outab(BYTE1(op)|2);
537: outab(BYTE2(op)|1);
538: }
539: break;
540: /* Two optional fp stack operands. */
541: case S_FP_SP:
542: fp_reg2(&e1, &e2);
543: if (e2.e_mode != ST)
544: qerr("invalid operand type");
545: outab(FWAIT);
546: outab(BYTE1(op));
547: outab((BYTE2(op))|rof(e1));
548: break;
549: /* One optional fp stack operand (default: ST). */
550: case S_FP_S1:
551: fp_reg(&e1);
552: outab(FWAIT);
553: outab(BYTE1(op));
554: outab(BYTE2(op)|rof(e1));
555: break;
556:
557: default:
558: err('o', "unknown operator");
559: }
560: }
561:
562: /*
563: * Check if the next non blank
564: * character is a comma. Give an error if
565: * not (and give up).
566: */
567: comma()
568: {
569: if (getnb() != ',')
570: qerr("expected comma");
571: }
572:
573: /*
574: * Output `general' format instructions.
575: * `Op' is the opcode, `r' is the general
576: * register (bits 3-5 of the postbyte) and
577: * `esp' is an address.
578: * The address must not be the flags, a
579: * segment register, (dx) or an immediate
580: * thing.
581: */
582: outgen(op, r, esp)
583: register struct expr *esp;
584: {
585: register disp, mode, regm;
586:
587: outab(op);
588: mode = esp->e_mode & MMASK;
589: regm = esp->e_mode & RMASK;
590: if (mode==IDX || mode==ICL || mode==IM || mode==SEGR) {
591: aerr("invalid operand");
592: return;
593: }
594: if (mode==BR || mode==WR) {
595: outab(0300 | (r<<3) | regm);
596: return;
597: }
598: if (mode == DIR) {
599: outab(0006 | (r<<3));
600: outrw(esp, 0);
601: return;
602: }
603: /* Mode is X */
604: if (esp->e_type == E_ACON) {
605: disp = esp->e_addr; /* Displacement */
606: if (regm!=6 && disp==0) {
607: outab((r<<3) | regm);
608: return;
609: }
610: if (disp>=-128 && disp<=127) {
611: outab(0100 | (r<<3) | regm);
612: outab(disp);
613: return;
614: }
615: }
616: outab(0200 | (r<<3) | regm);
617: outrw(esp, 0);
618: }
619:
620: /*
621: * Output a byte that looks like
622: * `bbbbbaaa'; this is a somewhat common
623: * format on the iAPX-86.
624: */
625: out3(a, b)
626: {
627: outab(a | (b<<3));
628: }
629:
630: /*
631: * Some consistancy checks.
632: * The `op' is an opcode with a valid `W' bit.
633: * `m1' and `m2' are modes.
634: */
635: bytecheck(op, m1, m2)
636: register op, m1, m2;
637: {
638: register bad;
639:
640: bad = 0;
641: if (m1 == BR) {
642: if ((op&W) != 0)
643: ++bad;
644: if (m2==WR || m2==SEGR)
645: ++bad;
646: }
647: if (m1==WR || m1==SEGR) {
648: if ((op&W) == 0)
649: ++bad;
650: if (m2 == BR)
651: ++bad;
652: }
653: if (m2 == BR) {
654: if ((op&W) != 0)
655: ++bad;
656: if (m1==WR || m1==SEGR)
657: ++bad;
658: }
659: if (m2==WR || m2==SEGR) {
660: if ((op&W) == 0)
661: ++bad;
662: if (m1 == BR)
663: ++bad;
664: }
665: if (bad)
666: aerr("invalid operand");
667: }
668:
669: /*
670: * Check to see if an address is
671: * one of the two machine accumulator registers.
672: * (AX or AL).
673: * True return if so.
674: */
675: isalax(esp)
676: register struct expr *esp;
677: {
678: if (esp->e_mode==AX || esp->e_mode==AL)
679: return (1);
680: return (0);
681: }
682:
683: /*
684: * Set up the big bit table
685: * used by the branch adjustment code.
686: */
687: minit()
688: {
689: bp = bb;
690: bm = 1;
691: }
692:
693: /*
694: * Store `b' in the next slot of the
695: * bit table.
696: * If no room, throw it away.
697: */
698: setbit(b)
699: {
700: if (bp >= &bb[NB])
701: return;
702: if (b)
703: *bp |= bm;
704: bm <<= 1;
705: if (bm == 0) {
706: bm = 1;
707: ++bp;
708: }
709: }
710:
711: /*
712: * Get the next bit from the bit
713: * table.
714: * If none left, return a `1'.
715: * This will get the long form of
716: * branches.
717: */
718: getbit()
719: {
720: register f;
721:
722: if (bp >= &bb[NB])
723: return (1);
724: f = *bp & bm;
725: bm <<= 1;
726: if (bm == 0) {
727: bm = 1;
728: ++bp;
729: }
730: return (f);
731: }
732:
733: /*
734: * This routine checks if the expression
735: * pointed to by `esp' is an absolute expression
736: * and has value `n'. This is used to check out
737: * the address fields of shifts and of interrupt
738: * request instructions.
739: */
740: isabsn(esp, n)
741: register struct expr *esp;
742: {
743: if (esp->e_type==E_ACON && esp->e_addr==n)
744: return (1);
745: return (0);
746: }
747:
748: /*
749: * This routine checks if an immediate
750: * operand fits in 8 bits. It is used to check
751: * for immediate length in instructions that
752: * can take the w:s immediate.
753: */
754: ishort(sp, esp)
755: register struct sym *sp;
756: register struct expr *esp;
757: {
758: register n;
759:
760: if ((sp->s_flag&S_OBL) == 0)
761: return (0);
762: if (esp->e_type != E_ACON)
763: return (0);
764: n = esp->e_addr&0177600;
765: if (n!=0 && n!=0177600)
766: return (0);
767: return (1);
768: }
769:
770: /*
771: * Make up the initial set of
772: * location counters.
773: * Poke one in every nonsegmented
774: * space. Add a special one for
775: * the C compiler's strings.
776: */
777: locinit()
778: {
779: struct loc *locdef();
780:
781: defloc = locdef(".shri", L_SHRI);
782: locdef(".prvi", L_PRVI);
783: locdef(".bssi", L_BSSI);
784: locdef(".shrd", L_SHRD);
785: locdef(".prvd", L_PRVD);
786: locdef(".bssd", L_BSSD);
787: locdef(".strn", L_PRVD);
788: locdef(".symt", L_DEBUG);
789: nloc = NLSEG;
790: }
791:
792: struct loc *
793: locdef(cp, t)
794: char *cp;
795: {
796: register char *cp1, *cp2;
797: register struct loc *lp;
798: struct sym *sp;
799: struct loc *lp1, *lp2;
800: int c;
801: char id[NCPLN];
802:
803: lp = (struct loc *) new(sizeof(struct loc));
804: lp->l_seg = t;
805: lp->l_lp = NULL;
806: lp->l_fuzz = 0;
807: lp->l_break = 0;
808: lp->l_offset = 0;
809: lp1 = NULL;
810: lp2 = loc[t];
811: while (lp2 != NULL) {
812: lp1 = lp2;
813: lp2 = lp2->l_lp;
814: }
815: if (lp1 == NULL)
816: loc[t] = lp; else
817: lp1->l_lp = lp;
818: cp1 = cp;
819: cp2 = &id[0];
820: while (c = *cp1++)
821: if (cp2 < &id[NCPLN])
822: *cp2++ = c;
823: while (cp2 < &id[NCPLN])
824: *cp2++ = 0;
825: sp = lookup(id, 1);
826: sp->s_kind = S_LOC;
827: sp->s_flag = 0;
828: sp->s_addr = (address)lp;
829: return (lp);
830: }
831: @
832:
833:
834: 1.1
835: log
836: @Initial revision
837: @
838: text
839: @d80 1
840: a80 1
841: aerr();
842: d88 1
843: a88 1
844: aerr();
845: d109 1
846: a109 1
847: aerr();
848: d121 13
849: d147 1
850: a147 1
851: aerr();
852: d158 1
853: a158 1
854: aerr();
855: d178 6
856: a183 2
857: else if (m2!=IM || !isabsn(&e2, 1))
858: aerr();
859: d185 2
860: d191 1
861: a191 1
862: aerr();
863: d237 1
864: a237 1
865: aerr();
866: d240 1
867: a240 1
868: aerr();
869: d252 1
870: a252 1
871: aerr();
872: d329 1
873: a329 1
874: aerr();
875: d355 4
876: a358 2
877: if (m1!=WR || (m2!=DIR && m2!=X))
878: aerr();
879: d417 11
880: d429 97
881: d527 1
882: a527 1
883: err('o');
884: d539 1
885: a539 1
886: qerr();
887: d560 1
888: a560 1
889: aerr();
890: d635 1
891: a635 1
892: aerr();
893: d797 1
894: a797 1
895: sp->s_addr = lp;
896: @
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.