1 /* mops.c - handle pseudo-ops */
2 
3 #include "syshead.h"
4 #include "const.h"
5 #include "type.h"
6 #include "globvar.h"
7 #include "opcode.h"
8 #include "scan.h"
9 #undef EXTERN
10 #define EXTERN
11 #include "address.h"
12 
13 #define is8bitadr(offset) ((offset_t) offset < 0x100)
14 #define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100)
15 #define pass2 (pass==last_pass)
16 
17 FORWARD void mshort2 P((void));
18 FORWARD reg_pt regchk P((void));
19 FORWARD void reldata P((void));
20 FORWARD void segadj P((void));
21 
22 #ifdef I80386
23 
24 #define iswordadr(offset) ((offset_t) (offset) < 0x10000L)
25 #define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L)
26 #define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL)
27 
28 #define BYTE_SEGWORD        0x00
29 #define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG)
30 
31 #define BASE_MASK   0x07
32 #define BASE_SHIFT     0
33 #define INDEX_MASK  0x38
34 #define INDEX_SHIFT    3
35 #define MOD_MASK    0xC0
36 # define REG_MOD    0xC0
37 # define MEM0_MOD   0x00
38 # define MEM1_MOD   0x40
39 # define MEM2_MOD   0x80
40 #define REG_MASK    0x38
41 #define REG_SHIFT      3
42 #define RM_MASK     0x07
43 #define RM_SHIFT       0
44 # define D16_RM     0x06
45 # define D32_RM     0x05
46 # define SIB_NOBASE 0x05
47 # define SIB_RM     0x04
48 #define SREG_MASK   0x38
49 #define SREG_SHIFT     3
50 #define SS_MASK     0xC0
51 #define SS_SHIFT       6
52 
53 #define SEGMOV      0x04
54 #define SIGNBIT     0x02
55 #define TOREGBIT    0x02
56 #define WORDBIT     0x01
57 
58 PRIVATE opcode_t baseind16[] =
59 {
60     0x00,			/* BP + BP, illegal */
61     0x00,			/* BX + BP, illegal */
62     0x03,			/* DI + BP */
63     0x02,			/* SI + BP */
64     0x00,			/* BP + BX, illegal */
65     0x00,			/* BX + BX, illegal */
66     0x01,			/* DI + BX */
67     0x00,			/* SI + BX */
68     0x03,			/* BP + DI */
69     0x01,			/* BX + DI */
70     0x00,			/* DI + DI, illegal */
71     0x00,			/* SI + DI, illegal */
72     0x02,			/* BP + SI */
73     0x00,			/* BX + SI */
74     0x00,			/* DI + SI, illegal */
75     0x00,			/* SI + SI, illegal */
76 };
77 
78 PRIVATE opcode_t regbits[] =
79 {
80     0x05 << REG_SHIFT,		/* BP */
81     0x03 << REG_SHIFT,		/* BX */
82     0x07 << REG_SHIFT,		/* DI */
83     0x06 << REG_SHIFT,		/* SI */
84 
85     0x00 << REG_SHIFT,		/* EAX */
86     0x05 << REG_SHIFT,		/* EBP */
87     0x03 << REG_SHIFT,		/* EBX */
88     0x01 << REG_SHIFT,		/* ECX */
89     0x07 << REG_SHIFT,		/* EDI */
90     0x02 << REG_SHIFT,		/* EDX */
91     0x06 << REG_SHIFT,		/* ESI */
92     0x04 << REG_SHIFT,		/* ESP */
93 
94     0x00 << REG_SHIFT,		/* AX */
95     0x01 << REG_SHIFT,		/* CX */
96     0x02 << REG_SHIFT,		/* DX */
97     0x04 << REG_SHIFT,		/* SP */
98 
99     0x04 << REG_SHIFT,		/* AH */
100     0x00 << REG_SHIFT,		/* AL */
101     0x07 << REG_SHIFT,		/* BH */
102     0x03 << REG_SHIFT,		/* BL */
103     0x05 << REG_SHIFT,		/* CH */
104     0x01 << REG_SHIFT,		/* CL */
105     0x06 << REG_SHIFT,		/* DH */
106     0x02 << REG_SHIFT,		/* DL */
107 
108     0x01 << REG_SHIFT,		/* CS */
109     0x03 << REG_SHIFT,		/* DS */
110     0x00 << REG_SHIFT,		/* ES */
111     0x04 << REG_SHIFT,		/* FS */
112     0x05 << REG_SHIFT,		/* GS */
113     0x02 << REG_SHIFT,		/* SS */
114 
115     0x00 << REG_SHIFT,		/* CR0 */
116     0x02 << REG_SHIFT,		/* CR2 */
117     0x03 << REG_SHIFT,		/* CR3 */
118 
119     0x00 << REG_SHIFT,		/* DR0 */
120     0x01 << REG_SHIFT,		/* DR1 */
121     0x02 << REG_SHIFT,		/* DR2 */
122     0x03 << REG_SHIFT,		/* DR3 */
123     0x06 << REG_SHIFT,		/* DR6 */
124     0x07 << REG_SHIFT,		/* DR7 */
125 
126     0x03 << REG_SHIFT,		/* TR3 */
127     0x04 << REG_SHIFT,		/* TR4 */
128     0x05 << REG_SHIFT,		/* TR5 */
129     0x06 << REG_SHIFT,		/* TR6 */
130     0x07 << REG_SHIFT,		/* TR7 */
131 
132     0x00 << REG_SHIFT,		/* ST(0) */
133     0x01 << REG_SHIFT,		/* ST(1) */
134     0x02 << REG_SHIFT,		/* ST(2) */
135     0x03 << REG_SHIFT,		/* ST(3) */
136     0x04 << REG_SHIFT,		/* ST(4) */
137     0x05 << REG_SHIFT,		/* ST(5) */
138     0x06 << REG_SHIFT,		/* ST(6) */
139     0x07 << REG_SHIFT,		/* ST(7) */
140 };
141 
142 PRIVATE opsize_t regsize[] =
143 {
144     2,				/* BP */
145     2,				/* BX */
146     2,				/* DI */
147     2,				/* SI */
148 
149     4,				/* EAX */
150     4,				/* EBP */
151     4,				/* EBX */
152     4,				/* ECX */
153     4,				/* EDI */
154     4,				/* EDX */
155     4,				/* ESI */
156     4,				/* ESP */
157 
158     2,				/* AX */
159     2,				/* CX */
160     2,				/* DX */
161     2,				/* SP */
162 
163     1,				/* AH */
164     1,				/* AL */
165     1,				/* BH */
166     1,				/* BL */
167     1,				/* CH */
168     1,				/* CL */
169     1,				/* DH */
170     1,				/* DL */
171 
172     2,				/* CS */
173     2,				/* DS */
174     2,				/* ES */
175     2,				/* FS */
176     2,				/* GS */
177     2,				/* SS */
178 
179     4,				/* CR0 */
180     4,				/* CR2 */
181     4,				/* CR3 */
182 
183     4,				/* DR0 */
184     4,				/* DR1 */
185     4,				/* DR2 */
186     4,				/* DR3 */
187     4,				/* DR6 */
188     4,				/* DR7 */
189 
190     4,				/* TR3 */
191     4,				/* TR4 */
192     4,				/* TR5 */
193     4,				/* TR6 */
194     4,				/* TR7 */
195 
196     10,				/* ST(0) */
197     10,				/* ST(1) */
198     10,				/* ST(2) */
199     10,				/* ST(3) */
200     10,				/* ST(4) */
201     10,				/* ST(5) */
202     10,				/* ST(6) */
203     10,				/* ST(7) */
204 
205     0,				/* NOREG */
206 };
207 
208 PRIVATE opcode_t regsegword[] =
209 {
210     WORDBIT,			/* BP */
211     WORDBIT,			/* BX */
212     WORDBIT,			/* DI */
213     WORDBIT,			/* SI */
214 
215     WORDBIT,			/* EAX */
216     WORDBIT,			/* EBP */
217     WORDBIT,			/* EBX */
218     WORDBIT,			/* ECX */
219     WORDBIT,			/* EDI */
220     WORDBIT,			/* EDX */
221     WORDBIT,			/* ESI */
222     WORDBIT,			/* ESP */
223 
224     WORDBIT,			/* AX */
225     WORDBIT,			/* CX */
226     WORDBIT,			/* DX */
227     WORDBIT,			/* SP */
228 
229     BYTE_SEGWORD,		/* AH */
230     BYTE_SEGWORD,		/* AL */
231     BYTE_SEGWORD,		/* BH */
232     BYTE_SEGWORD,		/* BL */
233     BYTE_SEGWORD,		/* CH */
234     BYTE_SEGWORD,		/* CL */
235     BYTE_SEGWORD,		/* DH */
236     BYTE_SEGWORD,		/* DL */
237 
238     SEGMOV,			/* CS */
239     SEGMOV,			/* DS */
240     SEGMOV,			/* ES */
241     SEGMOV,			/* FS */
242     SEGMOV,			/* GS */
243     SEGMOV,			/* SS */
244 
245     0x20,			/* CR0 */
246     0x20,			/* CR2 */
247     0x20,			/* CR3 */
248 
249     0x21,			/* DR0 */
250     0x21,			/* DR1 */
251     0x21,			/* DR2 */
252     0x21,			/* DR3 */
253     0x21,			/* DR6 */
254     0x21,			/* DR7 */
255 
256     0x24,			/* TR3 */
257     0x24,			/* TR4 */
258     0x24,			/* TR5 */
259     0x24,			/* TR6 */
260     0x24,			/* TR7 */
261 
262     0x00,			/* ST(0) */
263     0x00,			/* ST(1) */
264     0x00,			/* ST(2) */
265     0x00,			/* ST(3) */
266     0x00,			/* ST(4) */
267     0x00,			/* ST(5) */
268     0x00,			/* ST(6) */
269     0x00,			/* ST(7) */
270 
271     0x00,			/* NOREG */
272 };
273 
274 PRIVATE opcode_t rm[] =
275 {
276     0x05,			/* BP */
277     0x03,			/* BX */
278     0x07,			/* DI */
279     0x06,			/* SI */
280 
281     0x00,			/* EAX */
282     0x05,			/* EBP */
283     0x03,			/* EBX */
284     0x01,			/* ECX */
285     0x07,			/* EDI */
286     0x02,			/* EDX */
287     0x06,			/* ESI */
288     0x04,			/* ESP */
289 
290     0x00,			/* AX */
291     0x01,			/* CX */
292     0x02,			/* DX */
293     0x04,			/* SP */
294 
295     0x04,			/* AH */
296     0x00,			/* AL */
297     0x07,			/* BH */
298     0x03,			/* BL */
299     0x05,			/* CH */
300     0x01,			/* CL */
301     0x06,			/* DH */
302     0x02,			/* DL */
303 
304     0x01,			/* CS */
305     0x03,			/* DS */
306     0x00,			/* ES */
307     0x04,			/* FS */
308     0x05,			/* GS */
309     0x02,			/* SS */
310 
311     0x00,			/* CR0 */
312     0x00,			/* CR2 */
313     0x00,			/* CR3 */
314 
315     0x00,			/* DR0 */
316     0x00,			/* DR1 */
317     0x00,			/* DR2 */
318     0x00,			/* DR3 */
319     0x00,			/* DR6 */
320     0x00,			/* DR7 */
321 
322     0x00,			/* TR3 */
323     0x00,			/* TR4 */
324     0x00,			/* TR5 */
325     0x00,			/* TR6 */
326     0x00,			/* TR7 */
327 
328     0x00,			/* ST(0) */
329     0x00,			/* ST(1) */
330     0x00,			/* ST(2) */
331     0x00,			/* ST(3) */
332     0x00,			/* ST(4) */
333     0x00,			/* ST(5) */
334     0x00,			/* ST(6) */
335     0x00,			/* ST(7) */
336 
337     0x04,			/* null index reg for sib only */
338 };
339 
340 PRIVATE opcode_t rmfunny[] =
341 {
342     0x06,			/* BP */
343     0x07,			/* BX */
344     0x05,			/* DI */
345     0x04,			/* SI */
346 };
347 
348 PRIVATE opcode_t segoverride[] =
349 {
350     0x2E,			/* CS */
351     0x3E,			/* DS */
352     0x26,			/* ES */
353     0x64,			/* FS */
354     0x65,			/* GS */
355     0x36,			/* SS */
356 };
357 
358 PRIVATE opcode_t ss[] =		/* scale to ss bits */
359 {
360     0x00,			/* x0, illegal */
361     0x00 << SS_SHIFT,		/* x1 */
362     0x01 << SS_SHIFT,		/* x2 */
363     0x00,			/* x3, illegal */
364     0x02 << SS_SHIFT,		/* x4 */
365     0x00,			/* x5, illegal */
366     0x00,			/* x6, illegal */
367     0x00,			/* x7, illegal */
368     0x03 << SS_SHIFT,		/* x8 */
369 };
370 
371 PRIVATE unsigned char calljmp_kludge;
372 PRIVATE opcode_t direction;
373 PRIVATE bool_t fpreg_allowed;
374 PRIVATE opcode_t segword;
375 /*
376   Values of segword:
377     BYTE_SEGWORD for byte ea's.
378     SEGMOV for segment registers
379     opcode for special registers
380     WORDBIT for other word and dword ea's
381 */
382 
383 PRIVATE struct ea_s source;
384 PRIVATE struct ea_s source2;
385 PRIVATE struct ea_s target;
386 
387 FORWARD void Eb P((struct ea_s *eap));
388 FORWARD void Ew P((struct ea_s *eap));
389 FORWARD void Ev P((struct ea_s *eap));
390 FORWARD void Ex P((struct ea_s *eap));
391 FORWARD void Gd P((struct ea_s *eap));
392 FORWARD void Gw P((struct ea_s *eap));
393 FORWARD void Gv P((struct ea_s *eap));
394 FORWARD void Gx P((struct ea_s *eap));
395 FORWARD void buildea P((struct ea_s *eap));
396 FORWARD void buildfloat P((void));
397 FORWARD void buildfreg P((void));
398 FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag));
399 FORWARD void buildregular P((void));
400 FORWARD void buildsegword P((struct ea_s *eap));
401 FORWARD void buildunary P((opcode_pt opc));
402 FORWARD opsize_pt displsize P((struct ea_s *eap));
403 FORWARD reg_pt fpregchk P((void));
404 FORWARD bool_pt getaccumreg P((struct ea_s *eap));
405 FORWARD void getbinary P((void));
406 FORWARD bool_pt getdxreg P((struct ea_s *eap));
407 FORWARD void getea P((struct ea_s *eap));
408 FORWARD void getimmed P((struct ea_s *eap, count_t immed_count));
409 FORWARD void getindirect P((struct ea_s *eap));
410 FORWARD void getshift P((struct ea_s *eap));
411 FORWARD reg_pt indregchk P((reg_pt matchreg));
412 FORWARD void kgerror P((char * err_str));
413 FORWARD void lbranch P((int backamount));
414 FORWARD void notbytesize P((struct ea_s *eap));
415 FORWARD void notimmed P((struct ea_s *eap));
416 FORWARD void notindirect P((struct ea_s *eap));
417 FORWARD void notsegorspecreg P((struct ea_s *eap));
418 FORWARD void yesimmed P((struct ea_s *eap));
419 FORWARD void yes_samesize P((void));
420 
Eb(eap)421 PRIVATE void Eb(eap)
422 register struct ea_s *eap;
423 {
424     Ex(eap);
425     if (eap->size != 0x1)
426     {
427 #ifndef NODEFAULTSIZE
428 	if (eap->size == 0x0)
429 	    eap->size = 0x1;
430 	else
431 #endif
432 	    kgerror(ILL_SIZE);
433     }
434 }
435 
Ew(eap)436 PRIVATE void Ew(eap)
437 register struct ea_s *eap;
438 {
439     Ex(eap);
440     if (eap->size != 0x2)
441     {
442 #ifndef NODEFAULTSIZE
443 	if (eap->size == 0x0)
444 	    eap->size = 0x2;
445 	else
446 #endif
447 	    kgerror(ILL_SIZE);
448     }
449 }
450 
Ev(eap)451 PRIVATE void Ev(eap)
452 register struct ea_s *eap;
453 {
454     Ex(eap);
455     notbytesize(eap);
456 }
457 
Ex(eap)458 PRIVATE void Ex(eap)
459 register struct ea_s *eap;
460 {
461     getea(eap);
462     notimmed(eap);
463     notsegorspecreg(eap);
464 }
465 
Gd(eap)466 PRIVATE void Gd(eap)
467 register struct ea_s *eap;
468 {
469     Gx(eap);
470     if (eap->size != 0x4)
471 	kgerror(ILL_SIZE);
472 }
473 
Gw(eap)474 PRIVATE void Gw(eap)
475 register struct ea_s *eap;
476 {
477     Gx(eap);
478     if (eap->size != 0x2)
479 	kgerror(ILL_SIZE);
480 }
481 
Gv(eap)482 PRIVATE void Gv(eap)
483 register struct ea_s *eap;
484 {
485     Gx(eap);
486     notbytesize(eap);
487 }
488 
Gx(eap)489 PRIVATE void Gx(eap)
490 register struct ea_s *eap;
491 {
492     Ex(eap);
493     notindirect(eap);
494 }
495 
buildea(eap)496 PRIVATE void buildea(eap)
497 register struct ea_s *eap;
498 {
499     opsize_t asize;
500 
501     ++mcount;
502     lastexp = eap->displ;
503     if (eap->indcount == 0x0)
504 	postb = REG_MOD | rm[eap->base];
505     else
506     {
507 	if (eap->base == NOREG)
508 	{
509 	    if (eap->index == NOREG)
510 	    {
511 		if ((asize = displsize(eap)) > 0x2)
512 		    postb = D32_RM;
513 		else
514 		    postb = D16_RM;
515 	    }
516 	    else
517 	    {
518 		asize = 0x4;
519 		postb = SIB_NOBASE;	/* for sib later */
520 	    }
521 	}
522 	else
523 	{
524 	    if (eap->base > MAX16BITINDREG)
525 	    {
526 		asize = 0x4;
527 		postb = rm[eap->base];
528 	    }
529 	    else
530 	    {
531 		asize = 0x2;
532 		if (!(lastexp.data & UNDBIT) &&
533 		    !iswordorswordoffset(lastexp.offset))
534 		    error(ABOUNDS);
535 		if (eap->index == NOREG)
536 		    postb = rmfunny[eap->base];
537 		else if (eap->base <= MAX16BITINDREG)
538 		    postb = baseind16[eap->base + 0x4 * eap->index];
539 	    }
540 	}
541 	needcpu(asize==4?3:0);
542 	if (asize != defsize)
543 	    aprefix = 0x67;
544 	if (eap->base == NOREG)
545 	    mcount += asize;
546 	else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
547 		 !is8bitsignedoffset(lastexp.offset))
548 	{
549 	    postb |= MEM2_MOD;
550 	    mcount += asize;
551 	}
552 	else if (lastexp.offset != 0x0 ||
553 		 (eap->base == BPREG && eap->index == NOREG) ||
554 		 eap->base == EBPREG)
555 	{
556 	    postb |= MEM1_MOD;
557 	    ++mcount;
558 	}
559 	if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG))
560 	{
561 	    sib = ss[eap->scale] |
562 		(rm[eap->index] << INDEX_SHIFT) |
563 		(postb & RM_MASK);
564 	    postb = (postb & MOD_MASK) | SIB_RM;
565 	    ++mcount;
566 	}
567     }
568 }
569 
buildfloat()570 PRIVATE void buildfloat()
571 {
572     if (mcount != 0x0)
573     {
574 	buildea(&source);
575 	oprefix = 0x0;
576 	postb |= (opcode & 0x07) << REG_SHIFT;
577 	opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
578     }
579 }
580 
buildfreg()581 PRIVATE void buildfreg()
582 {
583     mcount += 0x2;
584     oprefix = 0x0;
585     postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG);
586     opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
587 }
588 
buildimm(eap,signflag)589 PRIVATE void buildimm(eap, signflag)
590 register struct ea_s *eap;
591 bool_pt signflag;
592 {
593     immadr = eap->displ;
594     immcount = eap->size;
595     if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)))
596     {
597 	if (immcount == 0x1)
598 	{
599 	    if ((offset_t) (immadr.offset + 0x80) >= 0x180)
600 		datatoobig();
601 	}
602 	else if (signflag && is8bitsignedoffset(immadr.offset))
603 	{
604 	    opcode |= SIGNBIT;
605 	    immcount = 0x1;
606 	}
607 	else if (immcount == 0x2)
608 	{
609 	    if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L)
610 		datatoobig();
611 	}
612     }
613 }
614 
buildregular()615 PRIVATE void buildregular()
616 {
617     if (mcount != 0x0)
618     {
619 	buildea(&target);
620 	postb |= regbits[source.base];
621     }
622 }
623 
624 /* Check size and build segword. */
625 
buildsegword(eap)626 PRIVATE void buildsegword(eap)
627 register struct ea_s *eap;
628 {
629     if (eap->size == 0x0)
630 #ifdef NODEFAULTSIZE
631 	kgerror(SIZE_UNK);
632 #else
633 	eap->size = defsize;
634 #endif
635     if (eap->indcount != 0x0 || eap->base == NOREG)
636     {
637 	segword = WORDBIT;
638 	if (eap->size == 0x1)
639 	    segword = BYTE_SEGWORD;
640     }
641     else
642 	segword = regsegword[eap->base];
643 }
644 
buildunary(opc)645 PRIVATE void buildunary(opc)
646 opcode_pt opc;
647 {
648     if (mcount != 0x0)
649     {
650 	buildea(&target);
651 	postb |= opcode;
652 	opcode = opc;
653     }
654 }
655 
displsize(eap)656 PRIVATE opsize_pt displsize(eap)
657 register struct ea_s *eap;
658 {
659     opsize_t asize;
660 
661     asize = defsize;
662     if (!(eap->displ.data & UNDBIT))
663     {
664 	if (asize > 0x2)
665 	{
666 	    if (!(eap->displ.data & (FORBIT | RELBIT)) &&
667 		iswordadr(eap->displ.offset))
668 		asize = 0x2;
669 	}
670 	else if (!iswordorswordoffset(eap->displ.offset))
671 				/* should really use iswordadr() */
672 				/* but compiler generates signed offsets */
673 	{
674 	    if (!(eap->displ.data & (FORBIT | RELBIT)))
675 		asize = 0x4;
676 	    else if (pass2)
677 		error(ABOUNDS);
678 	}
679     }
680     return asize;
681 }
682 
fpregchk()683 PRIVATE reg_pt fpregchk()
684 {
685     reg_pt fpreg;
686 
687     fpreg_allowed = TRUE;
688     fpreg = regchk();
689     fpreg_allowed = FALSE;
690     if (fpreg != ST0REG)
691 	return NOREG;
692     getsym();
693     if (sym == LPAREN)
694     {
695 	getsym();
696 	if (sym != INTCONST || (unsigned) number >= 0x8)
697 	    error(ILL_FP_REG);
698 	else
699 	{
700 	    fpreg += number;
701 	    getsym();
702 	    if (sym != RPAREN)
703 		error(RPEXP);
704 	    else
705 		getsym();
706 	}
707     }
708     return fpreg;
709 }
710 
getaccumreg(eap)711 PRIVATE bool_pt getaccumreg(eap)
712 register struct ea_s *eap;
713 {
714     if ((eap->base = regchk()) != AXREG && eap->base != ALREG
715 	&& eap->base != EAXREG)
716 	return FALSE;
717     getsym();
718     if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
719 	oprefix = 0x66;
720     return TRUE;
721 }
722 
723 /*
724   Get binary ea's in target & source (flipped if direction is set).
725   Put size in source if not already.
726   Initialise direction, segword, bump mcount.
727 */
728 
getbinary()729 PRIVATE void getbinary()
730 {
731     ++mcount;
732     getea(&target);
733     if (target.indcount == 0x0 && target.base == NOREG)
734     {
735 	error(ILL_IMM_MODE);
736 	target.base = AXREG;
737 	target.size = defsize;
738     }
739     getcomma();
740     getea(&source);
741     if (source.size == 0x0)
742 	source.size = target.size;
743     else if (target.size != 0x0 && target.size != source.size)
744     {
745 	kgerror(MISMATCHED_SIZE);
746 	return;
747     }
748     if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV)
749 	direction = 0x0;
750     else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV)
751     {
752 	struct ea_s swap;
753 
754 	direction = TOREGBIT;
755 	swap = source;
756 	source = target;
757 	target = swap;
758     }
759     else if (target.indcount != 0x0)
760     {
761 	kgerror(ILL_IND_TO_IND);
762 	return;
763     }
764     else
765     {
766 	kgerror(ILL_SEG_REG);
767 	return;
768     }
769     buildsegword(&source);
770 }
771 
getdxreg(eap)772 PRIVATE bool_pt getdxreg(eap)
773 register struct ea_s *eap;
774 {
775     if ((eap->base = regchk()) != DXREG)
776 	return FALSE;
777     getsym();
778     return TRUE;
779 }
780 
781 /* parse effective address */
782 
783 /*
784   Syntax is restrictive in that displacements must be in the right spots
785   and will not be added up.
786 
787   optional size-type prefix, which is
788     BYTE
789     BYTE PTR
790     WORD
791     WORD PTR
792     DWORD
793     DWORD PTR
794     PTR
795   reg
796   segreg
797   [scaled index]
798   where scaled index =
799     indreg
800     indreg*scale
801     indreg+indreg
802     indreg+indreg*scale
803   [scaled index+displ]
804   [scaled index-displ]
805   optional-immediate-prefix displ[scaled index]
806   [displ]
807   optional-imediate-prefix displ
808   (scaled index)                                   -- anachronism
809   optional-imediate-prefix displ(scaled index)     -- anachronism
810 */
811 
getea(eap)812 PRIVATE void getea(eap)
813 register struct ea_s *eap;
814 {
815     bool_t leading_displ;
816     bool_t leading_immed;
817     register struct sym_s *symptr;
818 
819     leading_immed = leading_displ = lastexp.data = eap->indcount
820 		  = lastexp.offset = 0x0;
821     eap->index = eap->base = NOREG;
822     eap->scale = 0x1;
823     eap->size = mnsize;		/* 0x1 for byte ops, else 0x0 */
824 
825     if (sym == IDENT)
826     {
827 	if ((symptr = gsymptr)->type & MNREGBIT)
828 	{
829 	    if (symptr->data & SIZEBIT)
830 	    {
831 		getsym();
832 		if (symptr->value_reg_or_op.op.opcode == 0x0)
833 		    eap->indcount = 0x2 - calljmp_kludge;
834 		else
835 		{
836 		    if (eap->size != 0x0)
837 		    {
838 			if (eap->size != symptr->value_reg_or_op.op.opcode)
839 			    error(MISMATCHED_SIZE);
840 		    }
841 		    else
842 			eap->size = symptr->value_reg_or_op.op.opcode;
843 		    if (eap->size > 0x1 && eap->size != defsize)
844 			oprefix = 0x66;
845 		    if (sym == IDENT &&
846 			(symptr = gsymptr)->type & MNREGBIT &&
847 			symptr->data & SIZEBIT &&
848 			symptr->value_reg_or_op.op.routine == PTROP)
849 		    {
850 			getsym();
851 			eap->indcount = 0x2 - calljmp_kludge;
852 		    }
853 		}
854 	    }
855 	}
856 	if( last_pass == 1 )
857 	    if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
858 	        symptr->data |= FORBIT;	/* show seen in advance */
859     }
860     if ((eap->base = regchk()) != NOREG)
861     {
862 	getsym();
863 	if (eap->indcount != 0x0)
864 	{
865 	    error(ILL_IND_PTR);
866 	    eap->indcount = 0x0;
867 	}
868 	if (eap->size != 0x0 && eap->size != regsize[eap->base])
869 	    error(MISMATCHED_SIZE);
870 	if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
871 	    oprefix = 0x66;
872 	eap->displ = lastexp;
873         needcpu(eap->size==4?3:0);
874 	return;
875     }
876     if (sym != lindirect)
877     {
878 	if (sym == IMMEDIATE || sym == STAR)
879 	{
880 	    /* context-sensitive, STAR means signed immediate here */
881 	    leading_immed = TRUE;
882 	    getsym();
883 	}
884 	leading_displ = TRUE;
885 	expres();
886 	eap->displ = lastexp;
887     }
888     if (sym == lindirect)
889     {
890 	getsym();
891 	eap->indcount = 0x2 - calljmp_kludge;
892 	if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG)
893 	{
894 	    if (eap->indcount == 0x0 && leading_displ)
895 		error(IND_REQ);
896 	    getsym();
897 	    if (sym == ADDOP)
898 	    {
899 		getsym();
900 		if ((eap->index = indregchk(eap->base)) != NOREG)
901 		    getsym();
902 		else
903 		{
904 		    if (eap->indcount == 0x0)
905 			error(IND_REQ);
906 		    if (leading_displ)
907 			error(REPEATED_DISPL);
908 		    expres();	/* this eats ADDOP, SUBOP, MULOP */
909 		}
910 	    }
911 	    if (sym == STAR)
912 	    {
913                 needcpu(3);
914 		/* context-sensitive, STAR means scaled here*/
915 		if (eap->index == NOREG && eap->base == ESPREG)
916 		{
917 		    error(INDEX_REG_EXP);
918 		    eap->base = EAXREG;
919 		}
920 		getsym();
921 		factor();
922 		chkabs();
923 		if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1)
924 		{
925 		    if (eap->base <= MAX16BITINDREG ||
926 			(lastexp.offset != 0x2 && lastexp.offset != 0x4 &&
927 			lastexp.offset != 0x8))
928 			error(ILL_SCALE);
929 		    else
930 		    {
931 			eap->scale = lastexp.offset;
932 			if (eap->index == NOREG)
933 			{
934 			    eap->index = eap->base;
935 			    eap->base = NOREG;
936 			}
937 		    }
938 		}
939 		lastexp.data = lastexp.offset = 0x0;
940 	    }
941 	    if ((sym == ADDOP || sym == SUBOP))
942 	    {
943 		if (eap->indcount == 0x0)
944 		    error(IND_REQ);
945 		if (leading_displ)
946 		    error(REPEATED_DISPL);
947 		expres();
948 	    }
949 	}
950 	else
951 	{
952 	    if (leading_displ)
953 		error(REPEATED_DISPL);
954 	    expres();
955 	}
956 	if (sym != rindirect)
957 	    error(rindexp);
958 	else
959 	    getsym();
960     }
961     /* RDB */
962     else if (!leading_immed && defsize <= 0x2)
963 	eap->indcount = 0x1;	/* compatibility kludge */
964     if (!leading_displ)
965 	eap->displ = lastexp;
966 
967     needcpu(eap->size==4?3:0);
968 }
969 
getimmed(eap,immed_count)970 PRIVATE void getimmed(eap, immed_count)
971 struct ea_s *eap;
972 count_t immed_count;
973 {
974     getea(eap);
975     yesimmed(eap);
976     if (mcount != 0x0)
977     {
978 	eap->size = immed_count;
979 	buildimm(eap, FALSE);
980     }
981 }
982 
getindirect(eap)983 PRIVATE void getindirect(eap)
984 register struct ea_s *eap;
985 {
986     getea(eap);
987     if (eap->indcount == 0x0)
988 	kgerror(IND_REQ);
989 }
990 
getshift(eap)991 PRIVATE void getshift(eap)
992 register struct ea_s *eap;
993 {
994     getcomma();
995     getea(eap);
996     if (eap->base != CLREG)
997 	yesimmed(eap);
998 }
999 
1000 /*
1001   Check if current symbol is a compatible index register.
1002   Generate error if it is a reg but not a compatible index.
1003   Return register number (adjusted if necessary to a legal index) or NOREG.
1004 */
1005 
indregchk(matchreg)1006 PRIVATE reg_pt indregchk(matchreg)
1007 reg_pt matchreg;
1008 {
1009     reg_pt reg;
1010 
1011     if ((reg = regchk()) != NOREG)
1012     {
1013 	switch (matchreg)
1014 	{
1015 	case BPREG:
1016 	case BXREG:
1017 	    if (reg != DIREG && reg != SIREG)
1018 	    {
1019 		reg = SIREG;
1020 		error(INDEX_REG_EXP);
1021 	    }
1022 	    break;
1023 	case DIREG:
1024 	case SIREG:
1025 	    if (reg != BPREG && reg != BXREG)
1026 	    {
1027 		reg = BXREG;
1028 		error(INDEX_REG_EXP);
1029 	    }
1030 	    break;
1031 	case NOREG:
1032 	    break;
1033 	default:
1034 	    if (reg <= MAX16BITINDREG || reg == ESPREG)
1035 	    {
1036 		reg = EAXREG;
1037 		error(INDEX_REG_EXP);
1038 	    }
1039 	    break;
1040 	}
1041 	if (reg > MAXINDREG && calljmp_kludge == 0x0)
1042 	{
1043 	    if (matchreg != NOREG)
1044 		reg = EAXREG;
1045 	    else
1046 		reg = BXREG;
1047 	    error(INDEX_REG_EXP);
1048 	}
1049     }
1050     return reg;
1051 }
1052 
kgerror(err_str)1053 PRIVATE void kgerror(err_str)
1054 char * err_str;
1055 {
1056     error(err_str);
1057     sprefix = oprefix = aprefix = mcount = 0x0;
1058 }
1059 
lbranch(backamount)1060 PRIVATE void lbranch(backamount)
1061 int backamount;
1062 {
1063     mcount += defsize + 0x1;
1064     segadj();
1065     if (pass2)
1066     {
1067 	reldata();
1068 	if (!(lastexp.data & (RELBIT | UNDBIT)))
1069 	{
1070 	    lastexp.offset = lastexp.offset - lc - lcjump;
1071 	    if ( last_pass<2 && backamount != 0x0 &&
1072 	        !(lastexp.data & IMPBIT) &&
1073 		lastexp.offset + backamount < 0x80 + backamount)
1074 		warning(SHORTB);	/* -0x8? to 0x7F, warning */
1075 	}
1076     }
1077 }
1078 
1079 /* BCC (long branches emulated by short branch over & long jump) */
1080 
mbcc()1081 PUBLIC void mbcc()
1082 {
1083     getea(&target);
1084     if (target.indcount >= 0x2 || target.base != NOREG)
1085 	kgerror(REL_REQ);
1086     else
1087     {
1088 #ifdef iscpu
1089 	if (iscpu(3))
1090 #else
1091 	if (defsize != 0x2)
1092 #endif
1093 	{
1094 	    page = PAGE1_OPCODE;
1095 	    ++mcount;
1096 	    opcode += 0x10;
1097 	    lbranch(0x84);
1098 	}
1099 	else
1100 	{
1101 	    aprefix = opcode ^ 0x1;	/* kludged storage for short branch
1102 					   over */
1103 	    oprefix = defsize + 0x1;
1104 	    mcount += 0x2;
1105 	    opcode = JMP_OPCODE;
1106 	    lbranch(0x83);
1107 	    mcount -= 0x2;
1108 	}
1109     }
1110 }
1111 
1112 /* bswap r32 */
1113 
mbswap()1114 PUBLIC void mbswap()
1115 {
1116     needcpu(4);
1117     ++mcount;
1118     Gd(&target);
1119     opcode |= rm[target.base];
1120 }
1121 
1122 /* BR, CALL, J, JMP */
1123 
mcall()1124 PUBLIC void mcall()
1125 {
1126     opcode_pt far_diff;
1127     bool_t indirect;
1128     register struct sym_s *symptr;
1129 
1130     far_diff = 0x0;
1131     if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT &&
1132 	symptr->data & SIZEBIT )
1133     {
1134         if(symptr->value_reg_or_op.op.routine == FAROP)
1135         {
1136 	    far_diff = 0x8;
1137 	    getsym();
1138         }
1139         if(symptr->value_reg_or_op.op.routine == WORDOP &&
1140 	   opcode == JMP_SHORT_OPCODE)
1141         {
1142 	   opcode = JMP_OPCODE;
1143 	   getsym();
1144 	}
1145     }
1146     indirect = FALSE;
1147 
1148     if (asld_compatible && defsize <= 0x2)
1149     {
1150 	calljmp_kludge = 0x2;
1151 	if (sym == INDIRECT)
1152 	{
1153 	    calljmp_kludge = 0x0;
1154 	    indirect = TRUE;
1155 	    getsym();
1156 	}
1157     }
1158     getea(&target);
1159     if (indirect && target.indcount == 0x1)
1160 	target.indcount = 0x2;
1161     calljmp_kludge = 0x0;
1162     if (sym == COLON)
1163     {
1164         int tsize = target.size?target.size:defsize;
1165 	if (opcode == JMP_SHORT_OPCODE)
1166 	    opcode = JMP_OPCODE;
1167 	++mcount;
1168 	yesimmed(&target);
1169 	getsym();
1170 	getea(&source);
1171 	yesimmed(&source);
1172 	if (mcount != 0x0)
1173 	{
1174 	    if (opcode == JMP_OPCODE)
1175 		opcode = 0xEA;
1176 	    else
1177 		opcode = 0x9A;
1178 	    lastexp = source.displ;
1179 	    if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
1180 		tsize == 0x2 &&
1181 		(offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
1182 		datatoobig();
1183 	    mcount += tsize;
1184 	    target.size = 0x2;
1185 	    buildimm(&target, FALSE);
1186 	}
1187     }
1188     else if (target.indcount >= 0x2 || target.base != NOREG)
1189     {
1190 	++mcount;
1191 	notsegorspecreg(&target);
1192 	if (target.indcount == 0)
1193 	    notbytesize(&target);
1194 	if (mcount != 0x0)
1195 	{
1196 	    if (opcode == JMP_SHORT_OPCODE)
1197 		opcode = JMP_OPCODE;
1198 	    buildea(&target);
1199 	    if (opcode == JMP_OPCODE)
1200 		opcode = 0x20;
1201 	    else
1202 		opcode = 0x10;
1203 	    postb |= opcode + far_diff;
1204 	    opcode = 0xFF;
1205 	}
1206     }
1207     else if (opcode == JMP_SHORT_OPCODE)
1208     {
1209 	if (jumps_long &&
1210 	    ((pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) ||
1211 	     (last_pass==1)))
1212 	{
1213 	    opcode = JMP_OPCODE;
1214 	    lbranch(0x83);
1215 	}
1216 	else
1217 	{
1218 	    lastexp = target.displ;
1219 	    if (lastexp.data & IMPBIT)
1220 	    {
1221 		error(NONIMPREQ);
1222 	        lastexp.data = FORBIT | UNDBIT;
1223     	    }
1224     	    mshort2();
1225 	}
1226     }
1227     else
1228 	lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0);
1229 }
1230 
1231 /* CALLI, JMPI */
1232 
mcalli()1233 PUBLIC void mcalli()
1234 {
1235     bool_t indirect;
1236 
1237     ++mcount;
1238     indirect = FALSE;
1239     if (sym == INDIRECT)
1240     {
1241 	getsym();
1242 	indirect = TRUE;
1243     }
1244     getea(&target);
1245     if (target.indcount >= 0x2 || target.base != NOREG)
1246 	indirect = TRUE;
1247     if (indirect)
1248     {
1249 	buildea(&target);
1250 	if (opcode == 0xEA)
1251 	    opcode = 0x28;
1252 	else
1253 	    opcode = 0x18;
1254 	postb |= opcode;
1255 	opcode = 0xFF;
1256     }
1257     else
1258     {
1259         int tsize = target.size?target.size:defsize;
1260 	getcomma();
1261 	getea(&source);
1262 	yesimmed(&source);
1263 	if (mcount != 0x0)
1264 	{
1265 	    lastexp = target.displ;
1266 	    if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
1267 		tsize == 0x2 &&
1268 		(offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
1269             {
1270 		tsize=4;
1271 	        if( tsize != defsize ) oprefix = 0x66;
1272 		/* datatoobig(); */
1273 	    }
1274 	    needcpu(tsize==4?3:0);
1275 	    mcount += tsize;
1276 	    source.size = 0x2;
1277 	    buildimm(&source, FALSE);
1278 	}
1279     }
1280 }
1281 
1282 /* DIV, IDIV, MUL */
1283 
mdivmul()1284 PUBLIC void mdivmul()
1285 {
1286     if (getaccumreg(&source))
1287     {
1288 	++mcount;
1289 	getcomma();
1290 	Ex(&target);
1291 	yes_samesize();
1292 	buildunary(0xF6 | regsegword[source.base]);
1293     }
1294     else
1295 	mnegnot();
1296 }
1297 
1298 /* ENTER */
1299 
menter()1300 PUBLIC void menter()
1301 {
1302     ++mcount;
1303     getimmed(&target, 0x2);
1304     getcomma();
1305     getimmed(&source, 0x1);
1306     if (mcount != 0x0)
1307     {
1308 	mcount += 2;
1309 	lastexp = target.displ;	/* getimmed(&source) wiped it out */
1310     }
1311     needcpu(1);
1312 }
1313 
1314 /* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */
1315 
mEwGw()1316 PUBLIC void mEwGw()
1317 {
1318     ++mcount;
1319     Ew(&target);
1320     getcomma();
1321     Gw(&source);
1322     oprefix = 0x0;
1323     buildregular();
1324 }
1325 
1326 /* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */
1327 
mExGx()1328 PUBLIC void mExGx()
1329 {
1330     ++mcount;
1331     Ex(&target);
1332     getcomma();
1333     Gx(&source);
1334     yes_samesize();
1335     opcode |= segword;
1336     buildregular();
1337 }
1338 
mf_inher()1339 PUBLIC void mf_inher()
1340 {
1341     mcount += 0x2;
1342     postb = REG_MOD | (opcode & ~REG_MOD);
1343     opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6);
1344     if (opcode == ESCAPE_OPCODE_BASE)
1345 	opcode = ESCAPE_OPCODE_BASE | 0x6;	/* fix up encoding of fcompp */
1346 }
1347 
1348 /* [fldenv fnsave fnstenv frstor] mem */
1349 
mf_m()1350 PUBLIC void mf_m()
1351 {
1352     ++mcount;
1353     getindirect(&source);
1354     if (source.size != 0x0)
1355 	kgerror(ILL_SIZE);
1356     buildfloat();
1357 }
1358 
1359 /* [fldcw fnstcw] mem2i */
1360 
mf_m2()1361 PUBLIC void mf_m2()
1362 {
1363     ++mcount;
1364     getindirect(&source);
1365     if (source.size != 0x0 && source.size != 0x2)
1366 	kgerror(ILL_SIZE);
1367     buildfloat();
1368 }
1369 
1370 /* fnstsw [mem2i ax] */
1371 
mf_m2_ax()1372 PUBLIC void mf_m2_ax()
1373 {
1374     if (getaccumreg(&target))
1375     {
1376 	if (target.base != AXREG)
1377 	    kgerror(ILLREG);
1378 	else
1379 	{
1380 	    opcode = 0x74;
1381 	    target.base = ST0REG;	/* fake, really ax */
1382 	    buildfreg();
1383 	}
1384     }
1385     else
1386 	mf_m2();
1387 }
1388 
1389 /* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */
1390 
mf_m2_m4()1391 PUBLIC void mf_m2_m4()
1392 {
1393     ++mcount;
1394     getindirect(&source);
1395     if (source.size == 0x0)
1396 	kgerror(SIZE_UNK);
1397     else if (source.size == 0x2)
1398 	opcode |= 0x40;
1399     else if (source.size != 0x4)
1400 	kgerror(ILL_SIZE);
1401     buildfloat();
1402 }
1403 
1404 /* [fild fistp] [mem2i mem4i mem8i] */
1405 
mf_m2_m4_m8()1406 PUBLIC void mf_m2_m4_m8()
1407 {
1408     ++mcount;
1409     getindirect(&source);
1410     if (source.size == 0x0)
1411 	kgerror(SIZE_UNK);
1412     else if (source.size == 0x2)
1413 	opcode |= 0x40;
1414     else if (source.size == 0x8)
1415 	opcode |= 0x45;		/* low bits 0 -> 5 and 3 -> 7 */
1416     else if (source.size != 0x4)
1417 	kgerror(ILL_SIZE);
1418     buildfloat();
1419 }
1420 
1421 /* [fcom fcomp] [mem4r mem8r optional-st(i)] */
1422 
mf_m4_m8_optst()1423 PUBLIC void mf_m4_m8_optst()
1424 {
1425     if (sym == EOLSYM)
1426     {
1427 	target.base = ST1REG;
1428 	buildfreg();
1429     }
1430     else
1431 	mf_m4_m8_st();
1432 }
1433 
1434 /* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */
1435 
mf_m4_m8_stst()1436 PUBLIC void mf_m4_m8_stst()
1437 {
1438     target.base = fpregchk();
1439     if (target.base != NOREG)
1440     {
1441 	getcomma();
1442 	source.base = fpregchk();
1443 	if (source.base == NOREG)
1444 	{
1445 	    error(FP_REG_REQ);
1446 	    source.base = ST0REG;
1447 	}
1448 	if (target.base == ST0REG)
1449 	    target.base = source.base;
1450 	else
1451 	{
1452 	    if (source.base != ST0REG)
1453 		error(ILL_FP_REG_PAIR);
1454 	    opcode |= 0x40;
1455 	    if ((opcode & 0x07) >= 0x4)
1456 		opcode ^= 0x01;	/* weird swap of fdiv/fdivr, fsub/fsubr */
1457 	}
1458 	buildfreg();
1459     }
1460     else
1461     {
1462 	++mcount;
1463 	getindirect(&source);
1464 	if (source.size == 0x0)
1465 	    kgerror(SIZE_UNK);
1466 	else if (source.size == 0x8)
1467 	    opcode |= 0x40;
1468 	else if (source.size != 0x4)
1469 	    kgerror(ILL_SIZE);
1470 	buildfloat();
1471     }
1472 }
1473 
1474 /* fst [mem4r mem8r st(i)] */
1475 
mf_m4_m8_st()1476 PUBLIC void mf_m4_m8_st()
1477 {
1478     target.base = fpregchk();
1479     if (target.base != NOREG)
1480     {
1481 	if (opcode == FST_ENCODED)
1482 	    opcode |= 0x40;
1483 	buildfreg();
1484     }
1485     else
1486     {
1487 	++mcount;
1488 	getindirect(&source);
1489 	if (source.size == 0x0)
1490 	    kgerror(SIZE_UNK);
1491 	else if (source.size == 0x8)
1492 	    opcode |= 0x40;
1493 	else if (source.size != 0x4)
1494 	    kgerror(ILL_SIZE);
1495 	buildfloat();
1496     }
1497 }
1498 
1499 /* [fld fstp] [mem4r mem8r mem10r st(i)] */
1500 
mf_m4_m8_m10_st()1501 PUBLIC void mf_m4_m8_m10_st()
1502 {
1503     target.base = fpregchk();
1504     if (target.base != NOREG)
1505     {
1506 	if (opcode == FSTP_ENCODED)
1507 	    opcode |= 0x40;
1508 	buildfreg();
1509     }
1510     else
1511     {
1512 	++mcount;
1513 	getindirect(&source);
1514 	if (source.size == 0x0)
1515 	    kgerror(SIZE_UNK);
1516 	else if (source.size == 0x8)
1517 	    opcode |= 0x40;
1518 	else if (source.size == 0xA)
1519 	    opcode |= 0x25;	/* low bits 0 -> 5 and 3 -> 7 */
1520 	else if (source.size != 0x4)
1521 	    kgerror(ILL_SIZE);
1522 	buildfloat();
1523     }
1524 }
1525 
1526 /* [fbld fbstp] mem10r */
1527 
mf_m10()1528 PUBLIC void mf_m10()
1529 {
1530     ++mcount;
1531     getindirect(&source);
1532     if (source.size != 0xA)
1533 	kgerror(ILL_SIZE);
1534     buildfloat();
1535 }
1536 
1537 /* ffree st(i) */
1538 
mf_st()1539 PUBLIC void mf_st()
1540 {
1541     target.base = fpregchk();
1542     if (target.base == NOREG)
1543 	kgerror(FP_REG_REQ);
1544     buildfreg();
1545 }
1546 
1547 /* [fucom fucomp fxch] optional-st(i) */
1548 
mf_optst()1549 PUBLIC void mf_optst()
1550 {
1551     if (sym == EOLSYM)
1552     {
1553 	target.base = ST1REG;
1554 	buildfreg();
1555     }
1556     else
1557 	mf_st();
1558 }
1559 
1560 /* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */
1561 
mf_stst()1562 PUBLIC void mf_stst()
1563 {
1564     target.base = fpregchk();
1565     if (target.base == NOREG)
1566     {
1567 	kgerror(FP_REG_REQ);
1568 	return;
1569     }
1570     getcomma();
1571     source.base = fpregchk();
1572     if (source.base == NOREG)
1573     {
1574 	kgerror(FP_REG_REQ);
1575 	return;
1576     }
1577     if (source.base != ST0REG)
1578     {
1579 	kgerror(ILL_FP_REG);
1580 	return;
1581     }
1582     buildfreg();
1583 }
1584 
mf_w_inher()1585 PUBLIC void mf_w_inher()
1586 {
1587     sprefix = WAIT_OPCODE;
1588     mf_inher();
1589 }
1590 
1591 /* [fsave fstenv] mem */
1592 
mf_w_m()1593 PUBLIC void mf_w_m()
1594 {
1595     sprefix = WAIT_OPCODE;
1596     mf_m();
1597 }
1598 
1599 /* fstcw mem2i */
1600 
mf_w_m2()1601 PUBLIC void mf_w_m2()
1602 {
1603     sprefix = WAIT_OPCODE;
1604     mf_m2();
1605 }
1606 
1607 /* fstsw [mem2i ax] */
1608 
mf_w_m2_ax()1609 PUBLIC void mf_w_m2_ax()
1610 {
1611     sprefix = WAIT_OPCODE;
1612     mf_m2_ax();
1613 }
1614 
1615 /* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */
1616 
mgroup1()1617 PUBLIC void mgroup1()
1618 {
1619     getbinary();
1620     notsegorspecreg(&source);
1621     if (mcount != 0x0)
1622     {
1623 	if (source.base == NOREG)
1624 	{
1625 	    if (target.indcount == 0x0 && (target.base == ALREG ||
1626 					   target.base == AXREG ||
1627 					  (target.base == EAXREG &&
1628 			  (source.displ.data & (FORBIT | RELBIT | UNDBIT) ||
1629 			   !is8bitsignedoffset(source.displ.offset)))))
1630 	    {
1631 		opcode |= 0x04 | segword;
1632 		buildimm(&source, FALSE);
1633 	    }
1634 	    else
1635 	    {
1636 		buildunary(0x80 | segword);
1637 		buildimm(&source, TRUE);
1638 	    }
1639 	}
1640 	else
1641 	{
1642 	    opcode |= direction | segword;
1643 	    buildregular();
1644 	}
1645     }
1646 }
1647 
1648 /* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */
1649 
mgroup2()1650 PUBLIC void mgroup2()
1651 {
1652     ++mcount;
1653     Ex(&target);
1654     buildsegword(&target);
1655     getshift(&source);
1656     if (mcount != 0x0)
1657     {
1658 	buildunary(0xD0 | segword);
1659 	if (source.base == CLREG)
1660 	    opcode |= 0x2;
1661 	else if (source.displ.offset != 0x1)
1662 	{
1663 	    needcpu(1);
1664 	    opcode -= 0x10;
1665 	    source.size = 0x1;
1666 	    buildimm(&source, FALSE);
1667 	}
1668     }
1669 }
1670 
1671 /* LLDT, LTR, SLDT, STR, VERR, VERW */
1672 
mgroup6()1673 PUBLIC void mgroup6()
1674 {
1675     needcpu(2);
1676     ++mcount;
1677     Ew(&target);
1678     oprefix = 0x0;
1679     buildunary(0x0);
1680 }
1681 
1682 /* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */
1683 
mgroup7()1684 PUBLIC void mgroup7()
1685 {
1686     needcpu(2);	/* I think INVLPG is actually 386 */
1687     ++mcount;
1688     if (opcode == 0x20 || opcode == 0x30)
1689     {
1690 	Ew(&target);
1691 	oprefix = 0x0;
1692     }
1693     else
1694     {
1695 	getindirect(&target);
1696 	oprefix = 0x0;
1697 	if (target.size != 0x0 && target.size != 0x6)
1698 	    error(MISMATCHED_SIZE);	/* XXX - size 6 wrong for INVLPG? */
1699     }
1700     buildunary(0x1);
1701 }
1702 
1703 /* BT, BTR, BTS, BTC */
1704 
mgroup8()1705 PUBLIC void mgroup8()
1706 {
1707     needcpu(3);
1708     ++mcount;
1709     Ev(&target);
1710     getcomma();
1711     /* Gv or Ib */
1712     getea(&source);
1713     notindirect(&source);
1714     notsegorspecreg(&source);
1715     if (mcount != 0x0)
1716     {
1717 	if (source.base == NOREG)
1718 	{
1719 	    buildunary(0xBA);
1720 	    source.size = 0x1;
1721 	    buildimm(&source, TRUE);
1722 	}
1723 	else
1724 	{
1725 	    yes_samesize();
1726 	    opcode += 0x83;
1727 	    buildregular();
1728 	}
1729     }
1730 }
1731 
1732 /* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */
1733 
mGvEv()1734 PUBLIC void mGvEv()
1735 {
1736     needcpu(2);
1737     ++mcount;
1738     Gv(&source);
1739     getcomma();
1740     Ev(&target);
1741     yes_samesize();
1742     buildregular();
1743 }
1744 
1745 /* bound [r16,m16&16 r32,m32&32] */
1746 
mGvMa()1747 PUBLIC void mGvMa()
1748 {
1749     ++mcount;
1750     Gv(&source);
1751     getcomma();
1752     getindirect(&target);
1753     yes_samesize();
1754     buildregular();
1755 }
1756 
1757 /* LDS, LES, LFS, LGS, LSS */
1758 
mGvMp()1759 PUBLIC void mGvMp()
1760 {
1761     ++mcount;
1762     Gv(&source);
1763     getcomma();
1764     getindirect(&target);
1765     if (target.size != 0x0 && target.size != 0x2 + source.size)
1766 	error(MISMATCHED_SIZE);
1767     buildregular();
1768 }
1769 
1770 /* IMUL */
1771 
mimul()1772 PUBLIC void mimul()
1773 {
1774     ++mcount;
1775     Ex(&target);
1776     if (sym != COMMA)
1777     {
1778 	buildsegword(&target);
1779 	buildunary(0xF6 | segword);
1780 	return;
1781     }
1782     getcomma();
1783     notindirect(&target);
1784     source = target;		/* direction is swapped */
1785     getea(&target);
1786     notsegorspecreg(&target);
1787     yes_samesize();
1788     if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG))
1789     {
1790         needcpu(3);
1791 	page = PAGE1_OPCODE;
1792 	++mcount;
1793 	opcode = 0xAF;
1794 	buildregular();
1795     }
1796     else
1797     {
1798 	if (sym == COMMA)
1799 	{
1800 	    getsym();
1801 	    getea(&source2);
1802 	    yesimmed(&source2);
1803 	}
1804 	else
1805 	{
1806 	    source2 = target;
1807 	    target = source;
1808 	}
1809 	source2.size = target.size;
1810 	if (is8bitsignedoffset(source2.displ.offset))
1811 	{
1812 	    source2.size = 0x1;
1813 	    opcode = 0x6B;
1814 	}
1815 	else
1816 	{
1817 	    source2.size = target.size;
1818 	    opcode = 0x69;
1819 	}
1820 	buildregular();
1821 	if (mcount != 0x0)
1822 	    buildimm(&source2, FALSE);
1823     }
1824 }
1825 
1826 /* IN */
1827 
min()1828 PUBLIC void min()
1829 {
1830     ++mcount;
1831     if (opcode & WORDBIT)	/* inw; ind not supported */
1832 	mnsize = 0x2;
1833     if (sym == EOLSYM && mnsize != 0x0)
1834 	    target.size = mnsize;
1835     else
1836     {
1837 	if (getaccumreg(&target))
1838 	{
1839 	    if (mnsize != 0x0 && regsize[target.base] != mnsize)
1840 		error(MISMATCHED_SIZE);
1841 	    getcomma();
1842 	}
1843 	else
1844 	    target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG];
1845 	opcode |= regsegword[target.base];
1846 	if (!getdxreg(&source))
1847 	{
1848 	    getimmed(&source, 0x1);
1849 	    opcode -= 0x8;
1850 	}
1851     }
1852     if (target.size > 0x1 && target.size != defsize)
1853 	oprefix = 0x66;
1854 }
1855 
1856 /* DEC, INC */
1857 
mincdec()1858 PUBLIC void mincdec()
1859 {
1860     ++mcount;
1861     Ex(&target);
1862     buildsegword(&target);
1863     if (target.indcount == 0x0 && segword == WORDBIT)
1864 	opcode |= 0x40 | rm[target.base];
1865     else
1866 	buildunary(0xFE | segword);
1867 }
1868 
1869 /* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */
1870 /* MOVSW, OUTSW, SCASW, STOSW */
1871 
minher16()1872 PUBLIC void minher16()
1873 {
1874     minher();
1875     if (defsize != 0x2)
1876 	oprefix = 0x66;
1877 }
1878 
1879 /* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */
1880 /* MOVSD, OUTSD, SCASD, STOSD */
1881 
minher32()1882 PUBLIC void minher32()
1883 {
1884     minher();
1885     if (defsize != 0x4)
1886 	oprefix = 0x66;
1887     needcpu(3);
1888 }
1889 
1890 /* AAD, AAM */
1891 
minhera()1892 PUBLIC void minhera()
1893 {
1894     ++mcount;
1895     if (sym == EOLSYM)
1896     {
1897 	target.displ.offset = 0xA;
1898 	target.size = 0x1;
1899 	buildimm(&target, FALSE);
1900     }
1901     else
1902 	getimmed(&target, 0x1);
1903 }
1904 
1905 /* INT */
1906 
mint()1907 PUBLIC void mint()
1908 {
1909     ++mcount;
1910     getimmed(&target, 0x1);
1911     if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) &&
1912 	(opcode_t) immadr.offset == 0x3)
1913     {
1914 	immcount = 0x0;
1915 	opcode = 0xCC;
1916     }
1917 }
1918 
1919 /* JCC */
1920 
mjcc()1921 PUBLIC void mjcc()
1922 {
1923     /* First look for j* near */
1924     if (sym == IDENT &&
1925         gsymptr->type & MNREGBIT &&
1926 	gsymptr->data & SIZEBIT &&
1927         gsymptr->value_reg_or_op.op.routine == WORDOP &&
1928 	opcode < 0x80)
1929     {
1930         getsym();
1931         getea(&target);
1932         if (target.indcount >= 0x2 || target.base != NOREG)
1933  	   kgerror(REL_REQ);
1934         else
1935         {
1936             needcpu(3);
1937 	    page = PAGE1_OPCODE;
1938 	    ++mcount;
1939 	    opcode += 0x10;
1940 	    lbranch(0x84);
1941         }
1942     }
1943     else if (!jumps_long || opcode > 0x80) /* above 0x80 means loop, not long */
1944 	mshort();
1945     else  /* mbcc */
1946     {
1947         getea(&target);
1948 	lastexp = target.displ;
1949 
1950 	if ( (pass!=0 && !is8bitsignedoffset(lastexp.offset - lc - 2)) ||
1951 	      last_pass==1)
1952 	{
1953            if (target.indcount >= 0x2 || target.base != NOREG)
1954 	       kgerror(REL_REQ);
1955 
1956 	    aprefix = opcode ^ 0x1;	/* kludged storage for short branch
1957 					   over */
1958 	    oprefix = defsize + 0x1;
1959 	    mcount += 0x2;
1960 	    opcode = JMP_OPCODE;
1961 	    lbranch(0x83);
1962 	    mcount -= 0x2;
1963 	}
1964 	else
1965 	{
1966 	   /* 8 bit */
1967 	    if (lastexp.data & IMPBIT)
1968 	    {
1969 		error(NONIMPREQ);
1970 		lastexp.data = FORBIT | UNDBIT;
1971     	    }
1972     	    mshort2();
1973 	}
1974     }
1975 }
1976 
1977 /* JCXZ, JECXZ */
1978 
mjcxz()1979 PUBLIC void mjcxz()
1980 {
1981     if (opcode != defsize)
1982     {
1983 	aprefix = 0x67;
1984 	++mcount;		/* quick fix - mshort() needs to know */
1985     }
1986     opcode = 0xE3;
1987     mshort();
1988     if (aprefix != 0x0)
1989 	--mcount;		/* quick fix - main routine bumps it again */
1990 }
1991 
1992 /* LEA */
1993 
mlea()1994 PUBLIC void mlea()
1995 {
1996     Gv(&source);		/* back to front */
1997     getcomma();
1998     ++mcount;
1999     getindirect(&target);
2000     yes_samesize();
2001     buildregular();
2002 }
2003 
2004 /* MOV */
2005 
mmov()2006 PUBLIC void mmov()
2007 {
2008     getbinary();
2009     if (segword >= SEGMOV)
2010     {
2011 	oprefix = 0x0;
2012 	notimmed(&target);	/* target is actually the source */
2013 	if (segword > SEGMOV)	/* special reg */
2014 	    notindirect(&target);
2015     }
2016     if (mcount != 0x0)
2017     {
2018 	if (target.base == NOREG && target.index == NOREG &&
2019 	    (source.base == ALREG || source.base == AXREG ||
2020 	     source.base == EAXREG))
2021 	{
2022 	    opcode = 0xA0 | (direction ^ TOREGBIT) | segword;
2023 	    lastexp = target.displ;
2024 	    if ((source.size = displsize(&target)) != defsize)
2025 		aprefix = 0x67;
2026 	    mcount += source.size;
2027 	    needcpu(source.size==4?3:0);
2028 	}
2029 	else if (source.base == NOREG)
2030 	{
2031 	    if (target.indcount == 0x0)
2032 		opcode = 0xB0 | (segword << 0x3) | rm[target.base];
2033 	    else
2034 	    {
2035 		buildea(&target);
2036 		opcode = 0xC6 | segword;
2037 	    }
2038 	    buildimm(&source, FALSE);
2039 	}
2040 	else
2041 	{
2042 	    if (isspecreg(source.base))
2043 	    {
2044 		needcpu(3);
2045 		page = PAGE1_OPCODE;
2046 		++mcount;
2047 		opcode = 0x0;
2048 	    }
2049 	    opcode |= direction | segword;
2050 	    buildregular();
2051 	}
2052     }
2053 }
2054 
2055 /* MOVSX, MOVZX */
2056 
mmovx()2057 PUBLIC void mmovx()
2058 {
2059     ++mcount;
2060     Gv(&source);
2061     getcomma();
2062     Ex(&target);
2063     if (target.size == 0x0)
2064 	kgerror(SIZE_UNK);
2065     if (target.size > 0x2)
2066 	kgerror(ILL_SIZE);
2067     oprefix = 0x0;
2068     if (source.size != defsize)
2069 	oprefix = 0x66;
2070     buildsegword(&target);
2071     opcode |= segword;
2072     buildregular();
2073 }
2074 
2075 /* NEG, NOT */
2076 
mnegnot()2077 PUBLIC void mnegnot()
2078 {
2079     ++mcount;
2080     Ex(&target);
2081     buildsegword(&target);
2082     buildunary(0xF6 | segword);
2083 }
2084 
2085 /* OUT */
2086 
mout()2087 PUBLIC void mout()
2088 {
2089     ++mcount;
2090     if (opcode & WORDBIT)	/* outw; outd not supported */
2091 	mnsize = 0x2;
2092     if (sym == EOLSYM && mnsize != 0x0)
2093 	    source.size = mnsize;
2094     else
2095     {
2096 	if (!getdxreg(&target))
2097 	{
2098 	    getimmed(&target, 0x1);
2099 	    opcode -= 0x8;
2100 	}
2101 	if (sym == COMMA)
2102 	{
2103 	    getsym();
2104 	    if (!getaccumreg(&source))
2105 		kgerror(AL_AX_EAX_EXP);
2106 	    else if (mnsize != 0x0 && regsize[source.base] != mnsize)
2107 		error(MISMATCHED_SIZE);
2108 	}
2109 	else
2110 	    source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG];
2111 	opcode |= regsegword[source.base];
2112     }
2113     if (source.size > 0x1 && source.size != defsize)
2114 	oprefix = 0x66;
2115 }
2116 
2117 /* POP, PUSH */
2118 
mpushpop()2119 PUBLIC void mpushpop()
2120 {
2121     opcode_t oldopcode;
2122 
2123     ++mcount;
2124     getea(&target);
2125     buildsegword(&target);
2126     notbytesize(&target);
2127     if ((oldopcode = opcode) == POP_OPCODE)
2128     {
2129 	notimmed(&target);
2130 	if (target.base == CSREG)
2131 	    kgerror(ILL_SEG_REG);
2132     }
2133     if (mcount != 0x0)
2134     {
2135 	if (target.indcount == 0x0)
2136 	{
2137 	    if (segword == SEGMOV)
2138 	    {
2139 		switch (target.base)
2140 		{
2141 		case CSREG:
2142 		    opcode = 0x0E;
2143 		    break;
2144 		case DSREG:
2145 		    opcode = 0x1E;
2146 		    break;
2147 		case ESREG:
2148 		    opcode = 0x06;
2149 		    break;
2150 		case SSREG:
2151 		    opcode = 0x16;
2152 		    break;
2153 		case FSREG:
2154 		    opcode = 0xA0;
2155 		    page = PAGE1_OPCODE;
2156 		    ++mcount;
2157 		    break;
2158 		case GSREG:
2159 		    opcode = 0xA8;
2160 		    page = PAGE1_OPCODE;
2161 		    ++mcount;
2162 		    break;
2163 		}
2164 		if (oldopcode == POP_OPCODE)
2165 		    ++opcode;
2166 	    }
2167 	    else if (target.base != NOREG)
2168 	    {
2169 		opcode = 0x50 | rm[target.base];
2170 		if (oldopcode == POP_OPCODE)
2171 		    opcode |= 0x8;
2172 	    }
2173 	    else
2174 	    {
2175 		needcpu(1); /* On 8086 PUSH does not allow immediate */
2176 		opcode = 0x68;
2177 		if (oldopcode == POP_OPCODE)
2178 		    ++opcode;
2179 		buildimm(&target, TRUE);
2180 	    }
2181 	}
2182 	else
2183 	{
2184 	    buildea(&target);
2185 	    if (oldopcode == PUSH_OPCODE)
2186 		postb |= 0x6 << REG_SHIFT;
2187 	}
2188     }
2189 }
2190 
2191 /* RET, RETF */
2192 
mret()2193 PUBLIC void mret()
2194 {
2195     ++mcount;
2196     if (sym != EOLSYM)
2197     {
2198 	--opcode;
2199 	getimmed(&target, 0x2);
2200     }
2201 }
2202 
2203 /* SEG CS/DS/ES/FS/GS/SS */
2204 
mseg()2205 PUBLIC void mseg()
2206 {
2207     reg_pt reg;
2208 
2209     if (regsegword[reg = regchk()] != SEGMOV)
2210 	error(SEG_REG_REQ);
2211     else
2212     {
2213 	getsym();
2214 	++mcount;
2215 	opcode = (segoverride - CSREG)[reg];
2216     }
2217 }
2218 
2219 /* SETCC */
2220 
msetcc()2221 PUBLIC void msetcc()
2222 {
2223     ++mcount;
2224     Eb(&target);
2225     if (mcount != 0x0)
2226 	buildea(&target);
2227 }
2228 
2229 /* SHLD, SHRD */
2230 
mshdouble()2231 PUBLIC void mshdouble()
2232 {
2233     needcpu(3);
2234     ++mcount;
2235     Ev(&target);
2236     getcomma();
2237     Gv(&source);
2238     yes_samesize();
2239     buildregular();
2240     getshift(&source2);
2241     lastexp = target.displ;	/* getshift() wiped it out */
2242     if (mcount != 0x0)
2243     {
2244 	if (source2.base == CLREG)
2245 	    opcode |= 0x1;
2246 	else
2247 	{
2248 	    source2.size = 0x1;
2249 	    buildimm(&source2, FALSE);
2250 	}
2251     }
2252 }
2253 
2254 /*
2255   TEST
2256   Similar to the regular group1 operators.
2257   It does not allow the sign extended immediate byte forms
2258   and does not use the relevant direction bit.
2259 */
2260 
mtest()2261 PUBLIC void mtest()
2262 {
2263     getbinary();
2264     notsegorspecreg(&source);
2265     if (source.base == NOREG)
2266     {
2267 	if (mcount != 0x0)
2268 	{
2269 	    if (target.indcount == 0x0
2270 		&& (target.base == ALREG || target.base == AXREG
2271 		    || target.base == EAXREG))
2272 		opcode = 0xA8 | segword;
2273 	    else
2274 	    {
2275 		buildea(&target);
2276 		opcode = 0xF6 | segword;
2277 	    }
2278 	}
2279 	buildimm(&source, FALSE);
2280     }
2281     else
2282     {
2283 	opcode |= segword;
2284 	buildregular();
2285     }
2286 }
2287 
2288 /*
2289   XCHG
2290   Similar to the regular group1 operators.
2291   It does not allow any of the immediate forms
2292   and does not use the irrelevant direction bit.
2293 */
2294 
mxchg()2295 PUBLIC void mxchg()
2296 {
2297     getbinary();
2298     notimmed(&source);
2299     notsegorspecreg(&source);
2300     if (target.indcount == 0x0)
2301     {
2302 	if (target.base == AXREG || target.base == EAXREG)
2303 	{
2304 	    opcode = 0x90 + rm[source.base];
2305 	    return;
2306 	}
2307 	if (source.base == AXREG || source.base == EAXREG)
2308 	{
2309 	    opcode = 0x90 + rm[target.base];
2310 	    return;
2311 	}
2312     }
2313     opcode |= segword;
2314     buildregular();
2315 }
2316 
notbytesize(eap)2317 PRIVATE void notbytesize(eap)
2318 register struct ea_s *eap;
2319 {
2320     if (eap->size == 0x1)
2321 	kgerror(ILL_SIZE);
2322 }
2323 
notimmed(eap)2324 PRIVATE void notimmed(eap)
2325 register struct ea_s *eap;
2326 {
2327     if (eap->indcount == 0x0 && eap->base == NOREG)
2328 	kgerror(ILL_IMM_MODE);
2329 }
2330 
notindirect(eap)2331 PRIVATE void notindirect(eap)
2332 register struct ea_s *eap;
2333 {
2334     if (eap->indcount != 0x0)
2335 	kgerror(ILL_IND);
2336 }
2337 
notsegorspecreg(eap)2338 PRIVATE void notsegorspecreg(eap)
2339 register struct ea_s *eap;
2340 {
2341     if (regsegword[eap->base] >= SEGMOV)
2342 	kgerror(ILLREG);
2343 }
2344 
yesimmed(eap)2345 PRIVATE void yesimmed(eap)
2346 register struct ea_s *eap;
2347 {
2348     if (eap->indcount == 0x1)
2349 	eap->indcount = 0x0;
2350     if (eap->indcount != 0x0 || eap->base != NOREG)
2351 	kgerror(IMM_REQ);
2352 }
2353 
yes_samesize()2354 PRIVATE void yes_samesize()
2355 {
2356     if (target.size == 0x0)
2357 	target.size = source.size;
2358     else if (source.size != 0x0 && target.size != source.size)
2359 	kgerror(MISMATCHED_SIZE);
2360 }
2361 
2362 #endif /* I80386 */
2363 
2364 #ifdef MC6809
2365 
2366 /* 6809 opcode constants */
2367 
2368 /* bits for indexed addressing */
2369 
2370 #define INDIRECTBIT 0x10
2371 #define INDEXBIT    0x80	/* except 5 bit offset */
2372 #define PCRELBIT    0x04	/* PC relative (in certain cases) */
2373 #define RRBITS      0x60	/* register select bits */
2374 
2375 PRIVATE opcode_t rrindex[] =	/* register and index bits for indexed adr */
2376 {
2377     0x60 | INDEXBIT,		/* S */
2378     0x40 | INDEXBIT,		/* U */
2379     0x00 | INDEXBIT,		/* X */
2380     0x20 | INDEXBIT,		/* Y */
2381     PCRELBIT | INDEXBIT,	/* PC */
2382 };
2383 
2384 PRIVATE opcode_t pushpull[] =	/* push/pull codes  */
2385 {
2386     0x40,			/* S */
2387     0x40,			/* U */
2388     0x10,			/* X */
2389     0x20,			/* Y */
2390     0x80,			/* PC */
2391     0x02,			/* A */
2392     0x04,			/* B */
2393     0x01,			/* CC */
2394     0x08,			/* DP */
2395     0x06,			/* D */
2396 };
2397 
2398 PRIVATE opcode_t tfrexg1[] =	/* transfer/exchange codes for source reg */
2399 {
2400     0x40,			/* S */
2401     0x30,			/* U */
2402     0x10,			/* X */
2403     0x20,			/* Y */
2404     0x50,			/* PC */
2405     0x80,			/* A */
2406     0x90,			/* B */
2407     0xA0,			/* CC */
2408     0xB0,			/* DP */
2409     0x00,			/* D */
2410 };
2411 
2412 PRIVATE opcode_t tfrexg2[] =	/* transfer/exchange codes for target reg */
2413 {
2414     0x04,			/* S */
2415     0x03,			/* U */
2416     0x01,			/* X */
2417     0x02,			/* Y */
2418     0x05,			/* PC */
2419     0x08,			/* A */
2420     0x09,			/* B */
2421     0x0A,			/* CC */
2422     0x0B,			/* DP */
2423     0x00,			/* D */
2424 };
2425 
2426 FORWARD void checkpostinc P((void));
2427 FORWARD void doaltind P((void));
2428 FORWARD void do1altind P((void));
2429 FORWARD void fixupind P((void));
2430 FORWARD void getindexnopost P((void));
2431 FORWARD void inderror P((char * err_str));
2432 FORWARD reg_pt indreg P((reg_pt maxindex));
2433 FORWARD void predec1 P((void));
2434 FORWARD void sustack P((reg_pt stackreg));
2435 
checkpostinc()2436 PRIVATE void checkpostinc()
2437 {
2438     if (sym == ADDOP)
2439     {
2440 	if (postb & INDIRECTBIT)
2441 	    inderror(ILLMOD);	/* single-inc indirect illegal */
2442 	else
2443 	{
2444 	    lastexp.offset &= 0xFF00;	/* for printing if postbyte is 0: ,X+ */
2445 	    getsym();
2446 	}
2447     }
2448     else if (sym == POSTINCOP)
2449     {
2450 	postb |= 0x1;
2451 	getsym();
2452     }
2453     else
2454 	postb |= 0x4;
2455     fixupind();
2456 }
2457 
2458 /* common code for all-mode ops, alterable-mode ops, indexed ops */
2459 
doaltind()2460 PRIVATE void doaltind()
2461 {
2462     mcount += 0x2;
2463     if (sym == LBRACKET)
2464     {
2465 	postb = INDIRECTBIT;
2466 	getsym();
2467 	do1altind();
2468 	if (sym != RBRACKET)
2469 	    error(RBEXP);
2470     }
2471     else
2472 	do1altind();
2473 }
2474 
do1altind()2475 PRIVATE void do1altind()
2476 {
2477     bool_t byteflag;		/* set if direct or short indexed adr forced */
2478     char *oldlineptr;
2479     char *oldsymname;
2480     reg_pt reg;
2481     bool_t wordflag;		/* set if extended or long indexed adr forced*/
2482 
2483     if ((reg = regchk()) != NOREG)
2484     {
2485 	switch (reg)
2486 	{
2487 	case AREG:
2488 	    postb |= 0x86;
2489 	    break;
2490 	case BREG:
2491 	    postb |= 0x85;
2492 	    break;
2493 	case DREG:
2494 	    postb |= 0x8B;
2495 	    break;
2496 	default:
2497 	    if (indreg(MAXINDREG) != NOREG)
2498 		checkpostinc();
2499 	    return;
2500 	}
2501 	getsym();
2502 	if (sym != COMMA)
2503 	    inderror(COMEXP);
2504 	else
2505 	    getindexnopost();
2506 	return;
2507     }
2508     else if (sym == SUBOP)	/* could be -R or - in expression */
2509     {
2510 	oldlineptr = lineptr;	/* save state */
2511 	oldsymname = symname;
2512 	getsym();
2513 	reg = regchk();
2514 	lineptr = oldlineptr;
2515 	symname = oldsymname;
2516 	if (reg != NOREG)
2517 	{
2518 	    predec1();		/* it's -R */
2519 	    return;
2520 	}
2521 	sym = SUBOP;
2522     }
2523     else if (sym == COMMA)
2524     {
2525 	postb |= INDEXBIT;
2526 	getsym();
2527 	if (sym == SUBOP)
2528 	{
2529 	    predec1();
2530 	    return;
2531 	}
2532 	else if (sym != PREDECOP)
2533 	{
2534 	    if (indreg(MAXINDREG) != NOREG)
2535 		checkpostinc();
2536 	    return;
2537 	}
2538     }
2539     if (sym == PREDECOP)
2540     {
2541 	postb |= 0x83;
2542 	getindexnopost();
2543 	return;
2544     }
2545 
2546     /* should have expression */
2547 
2548     wordflag = byteflag = FALSE;
2549     if (sym == LESSTHAN)
2550     {
2551 	/* context-sensitive, LESSTHAN means byte-sized here */
2552 	byteflag = TRUE;
2553 	getsym();
2554     }
2555     else if (sym == GREATERTHAN)
2556     {
2557 	/* context-sensitive, GREATERTHAN means word-sized here */
2558 	wordflag = TRUE;
2559 	getsym();
2560     }
2561     expres();
2562     if (sym == COMMA)
2563     {				/* offset from register */
2564 	getsym();
2565 	if ((reg = indreg(PCREG)) == NOREG)
2566 	    return;
2567 	postb |= 0x8;		/* default 8 bit offset */
2568 	if (reg == PCREG)
2569 	{
2570 	    reldata();
2571 	    if (!(lastexp.data & (RELBIT | UNDBIT)))
2572 	    {
2573 		lastexp.offset = lastexp.offset - lc;
2574 		if (page != 0x0)
2575 		    lastexp.offset -= 0x4;	/* extra for instruction */
2576 		else
2577 		    lastexp.offset -= 0x3;	/* 3 byte instruction
2578 						   assuming 8 bit offset */
2579 	    }
2580 	}
2581 	if (byteflag)
2582 	{
2583 	    if (!(lastexp.data & (RELBIT | UNDBIT)) &&
2584 		!is8bitsignedoffset(lastexp.offset))
2585 		error(ABOUNDS);	/* forced short form is impossible */
2586 	    ++mcount;
2587 	}
2588 	else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
2589 		 !is8bitsignedoffset(lastexp.offset))
2590 	{			/* 16 bit offset */
2591 	    if (postb & PCRELBIT && !(lastexp.data & RELBIT))
2592 		--lastexp.offset;	/* instruction 1 longer than already
2593 					   allowed */
2594 	    postb |= 0x1;
2595 	    mcount += 0x2;
2596 	}
2597 	else if (!(postb & PCRELBIT) &&
2598 		 (offset_t) (lastexp.offset + 0x10) < 0x20 &&
2599 		 !(postb & INDIRECTBIT && lastexp.offset != 0x0))
2600 	{			/* 5 bit offset */
2601 	    postb &= RRBITS | INDIRECTBIT;
2602 	    if (lastexp.offset == 0x0)
2603 		postb |= 0x84;	/* index with zero offset */
2604 	    else
2605 		postb |= (lastexp.offset & 0x1F);
2606 	}
2607 	else			/* 8 bit offset */
2608 	    ++mcount;
2609 	fixupind();
2610     }
2611     else if (postb & INDIRECTBIT)
2612     {				/* extended indirect */
2613 	postb = 0x9F;
2614 	mcount += 0x2;
2615 	fixupind();
2616     }
2617     else if (postb & INDEXBIT)
2618 	inderror(ILLMOD);	/* e.g. LEAX	 $10 */
2619     else
2620     {
2621 	if (byteflag || (!wordflag && !(lastexp.data & (FORBIT | RELBIT)) &&
2622 	    (lastexp.offset >> 0x8) == dirpag))
2623 	{			/* direct addressing */
2624 	    if (opcode >= 0x80)
2625 		opcode |= 0x10;
2626 	}
2627 	else			/* extended addressing */
2628 	{
2629 	    if (opcode < 0x80)
2630 		opcode |= 0x70;
2631 	    else
2632 		opcode |= 0x30;
2633 	    ++mcount;
2634 	    if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) &&
2635 		!(lastexp.data & IMPBIT) &&
2636 		lastexp.offset + (0x81 - 0x3) < 0x101)
2637 				/* JSR or JMP could be done with BSR or BRA */
2638 		warning(SHORTB);
2639 	}
2640     }
2641 }
2642 
fixupind()2643 PRIVATE void fixupind()
2644 {
2645     if ((opcode & 0x30) == 0x0)	/* change all but LEA opcodes */
2646     {
2647 	if (opcode < 0x80)
2648 	    opcode |= 0x60;
2649 	else
2650 	    opcode |= 0x20;
2651     }
2652 }
2653 
getindexnopost()2654 PRIVATE void getindexnopost()
2655 {
2656     getsym();
2657     if (indreg(MAXINDREG) != NOREG)
2658 	fixupind();
2659 }
2660 
inderror(err_str)2661 PRIVATE void inderror(err_str)
2662 char * err_str;
2663 {
2664     error(err_str);
2665     if (postb & INDIRECTBIT)
2666 	sym = RBRACKET;		/* fake right bracket to kill further errors */
2667     fixupind();
2668 }
2669 
2670 /* check current symbol is an index register (possibly excepting PC) */
2671 /* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */
2672 /* otherwise generate error, return FALSE */
2673 
indreg(maxindex)2674 PRIVATE reg_pt indreg(maxindex)
2675 reg_pt maxindex;
2676 {
2677     reg_pt reg;
2678 
2679     if ((reg = regchk()) == NOREG)
2680 	inderror(IREGEXP);
2681     else if (reg > maxindex)
2682     {
2683 	inderror(ILLREG);
2684 	reg = NOREG;
2685     }
2686     else
2687     {
2688 	postb |= rrindex[reg];
2689 	getsym();
2690     }
2691     return reg;
2692 }
2693 
2694 /* all-mode ops */
2695 
mall()2696 PUBLIC void mall()
2697 {
2698     if (sym == IMMEDIATE)
2699 	mimmed();
2700     else
2701 	malter();
2702 }
2703 
2704 /* alterable mode ops */
2705 
malter()2706 PUBLIC void malter()
2707 {
2708     postb = 0x0;		/* not yet indexed or indirect */
2709     doaltind();
2710 }
2711 
2712 /* indexed mode ops */
2713 
mindex()2714 PUBLIC void mindex()
2715 {
2716     postb = INDEXBIT;		/* indexed but not yet indirect */
2717     doaltind();
2718 }
2719 
2720 /* immediate ops */
2721 
mimmed()2722 PUBLIC void mimmed()
2723 {
2724     opcode_t nybble;
2725 
2726     mcount += 0x2;
2727     if (sym != IMMEDIATE)
2728 	error(ILLMOD);
2729     else
2730     {
2731 	if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 ||
2732 			       nybble == 0xC || nybble >= 0xE))
2733 	    ++mcount;		/* magic for long immediate */
2734 	symexpres();
2735 	if (pass2 && mcount <= 0x2)
2736 	{
2737 	    chkabs();
2738 	    checkdatabounds();
2739 	}
2740     }
2741 }
2742 
2743 /* long branches */
2744 
mlong()2745 PUBLIC void mlong()
2746 {
2747     mcount += 0x3;		/* may be 0x0 or 0x1 here */
2748     expres();
2749     segadj();
2750     if (pass2)
2751     {
2752 	reldata();
2753 	if (!(lastexp.data & (RELBIT | UNDBIT)))
2754 	{
2755 	    lastexp.offset = lastexp.offset - lc - lcjump;
2756 	    if ( last_pass<2 && !(lastexp.data & IMPBIT) &&
2757 		lastexp.offset + 0x81 < 0x101)
2758 		warning(SHORTB);	/* -0x81 to 0x7F, warning */
2759 	}
2760     }
2761 }
2762 
2763 /* PSHS and PULS */
2764 
msstak()2765 PUBLIC void msstak()
2766 {
2767     sustack(SREG);
2768 }
2769 
2770 /* TFR and EXG */
2771 
mswap()2772 PUBLIC void mswap()
2773 {
2774     reg_pt reg;
2775 
2776     mcount = 0x2;
2777     if ((reg = regchk()) == NOREG)
2778 	error(REGEXP);
2779     else
2780     {
2781 	postb = tfrexg1[reg];
2782 	getsym();
2783 	if (sym != COMMA)
2784 	    error(COMEXP);
2785 	else
2786 	{
2787 	    getsym();
2788 	    if ((reg = regchk()) == NOREG)
2789 		error(REGEXP);
2790 	    else if ((postb |= tfrexg2[reg])
2791 		     & 0x88 && (postb & 0x88) != 0x88)
2792 		error(ILLREG);	/* registers not of same size */
2793 	}
2794     }
2795 }
2796 
2797 /* PSHU and PULU */
2798 
mustak()2799 PUBLIC void mustak()
2800 {
2801     sustack(UREG);
2802 }
2803 
predec1()2804 PRIVATE void predec1()
2805 {
2806     if (postb & INDIRECTBIT)
2807 	inderror(ILLMOD);	/* single-dec indirect illegal */
2808     else
2809     {
2810 	postb |= 0x82;
2811 	getindexnopost();
2812     }
2813 }
2814 
2815 /* common routine for PSHS/PULS/PSHU/PULU */
2816 
sustack(stackreg)2817 PRIVATE void sustack(stackreg)
2818 reg_pt stackreg;
2819 {
2820     reg_pt reg;
2821 
2822     mcount = 0x2;
2823     while ((reg = regchk()) != NOREG)
2824     {
2825 	if (reg == stackreg)
2826 	{
2827 	    error(ILLREG);	/* cannot stack self */
2828 	    break;
2829 	}
2830 	postb |= pushpull[reg];
2831 	getsym();
2832 	if (sym != COMMA)
2833 	    break;
2834 	getsym();
2835     }
2836 }
2837 
2838 #endif /* MC6809 */
2839 
2840 /* routines common to all processors */
2841 
getcomma()2842 PUBLIC void getcomma()
2843 {
2844     if (sym != COMMA)
2845 	error(COMEXP);
2846     else
2847 	getsym();
2848 }
2849 
2850 /* inherent ops */
2851 
2852 /* for I80386 */
2853 /* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */
2854 /* INVD, */
2855 /* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */
2856 /* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */
2857 
minher()2858 PUBLIC void minher()
2859 {
2860     ++mcount;
2861 }
2862 
2863 /* short branches */
2864 
mshort()2865 PUBLIC void mshort()
2866 {
2867     nonimpexpres();
2868     mshort2();
2869 }
2870 
mshort2()2871 PRIVATE void mshort2()
2872 {
2873     mcount += 0x2;
2874     if (pass2)
2875     {
2876 	reldata();
2877 	if (lastexp.data & RELBIT)
2878 	    showrelbad();
2879 	else if (!(lastexp.data & UNDBIT))
2880 	{
2881 	    lastexp.offset = lastexp.offset - lc - mcount;
2882 	    if (!is8bitsignedoffset(lastexp.offset))
2883 		error(ABOUNDS);
2884 	}
2885     }
2886 }
2887 
2888 /* check if current symbol is a register, return register number or NOREG */
2889 
regchk()2890 PRIVATE reg_pt regchk()
2891 {
2892     register struct sym_s *symptr;
2893 
2894     if (sym == IDENT)
2895     {
2896 	if ((symptr = gsymptr)->type & MNREGBIT)
2897 	{
2898 	    if (symptr->data & REGBIT)
2899 	    {
2900 	        int regno = symptr->value_reg_or_op.reg;
2901 #ifdef I80386
2902 		if (regno == ST0REG && !fpreg_allowed)
2903 		    error(FP_REG_NOT_ALLOWED);
2904 
2905 		/* Check cpu */
2906                 needcpu((regno==FSREG||regno==GSREG)?3:0);
2907                 needcpu((regno>=EAXREG && regno<=ESPREG)?3:0);
2908                 needcpu((regno>=CR0REG && regno<=TR7REG)?3:0);
2909 #endif
2910 		return regno;
2911 	    }
2912 	}
2913 	else
2914 	    if( last_pass == 1 )
2915 	        if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
2916 	            symptr->data |= FORBIT;	/* show seen in advance */
2917     }
2918     return NOREG;
2919 }
2920 
2921 /* convert lastexp.data for PC relative */
2922 
reldata()2923 PRIVATE void reldata()
2924 {
2925     if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM))
2926     {
2927 	if ((lastexp.data ^ lcdata) & RELBIT)
2928 	    showrelbad();	/* rel - abs is weird, abs - rel is bad */
2929 	else
2930 	{
2931 	    pcrflag = OBJ_R_MASK;
2932 	    lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT;
2933 				/* segment is that of lastexp.data */
2934 	}
2935     }
2936     else			/* same file, segment and relocation */
2937 	lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM);
2938 }
2939 
segadj()2940 PRIVATE void segadj()
2941 {
2942     if ((lastexp.data & UNDBIT) && textseg >= 0 )
2943     {
2944         lastexp.sym->data &= ~SEGM;
2945         lastexp.sym->data |= (lcdata & SEGM);
2946     }
2947 }
2948