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