fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/e8086/disasm.c *
7 * Created: 2002-05-20 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2002-2017 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <string.h>
24
25#include "e8086.h"
26#include "internal.h"
27
28
29/**************************************************************************
30 * Disassembler functions
31 **************************************************************************/
32
33
34static void e86_disasm_op (e86_disasm_t *op, unsigned char *src);
35
36
37static
38char *d_tab_reg8[8] = {
39 "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"
40};
41
42static
43char *d_tab_reg16[8] = {
44 "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"
45};
46
47static
48char *d_tab_sreg[4] = {
49 "ES", "CS", "SS", "DS"
50};
51
52static
53const char *d_tab_segpre[5] = {
54 "", "ES:", "CS:", "SS:", "DS:"
55};
56
57typedef struct {
58 unsigned cnt;
59 const char *arg;
60} d_tab_ea_t;
61
62static
63d_tab_ea_t d_tab_ea[24] = {
64 { 0, "BX+SI" },
65 { 0, "BX+DI" },
66 { 0, "BP+SI" },
67 { 0, "BP+DI" },
68 { 0, "SI" },
69 { 0, "DI" },
70 { 2, NULL },
71 { 0, "BX" },
72 { 1, "BX+SI" },
73 { 1, "BX+DI" },
74 { 1, "BP+SI" },
75 { 1, "BP+DI" },
76 { 1, "SI" },
77 { 1, "DI" },
78 { 1, "BP" },
79 { 1, "BX" },
80 { 2, "BX+SI" },
81 { 2, "BX+DI" },
82 { 2, "BP+SI" },
83 { 2, "BP+DI" },
84 { 2, "SI" },
85 { 2, "DI" },
86 { 2, "BP" },
87 { 2, "BX" }
88};
89
90
91static
92void disasm_reg8 (char *dst, unsigned r)
93{
94 strcpy (dst, d_tab_reg8[r & 7]);
95}
96
97static
98void disasm_reg16 (char *dst, unsigned r)
99{
100 strcpy (dst, d_tab_reg16[r & 7]);
101}
102
103static
104void disasm_sreg (char *dst, unsigned r)
105{
106 strcpy (dst, d_tab_sreg[r & 3]);
107}
108
109static
110void disasm_uint16 (char *dst, unsigned short v)
111{
112 sprintf (dst, "%04X", v);
113}
114
115static
116void disasm_imm8 (char *dst, const unsigned char *src)
117{
118 sprintf (dst, "%02X", src[0]);
119}
120
121static
122void disasm_simm8 (char *dst, const unsigned char *src)
123{
124 if (src[0] < 0x80) {
125 sprintf (dst, "+%02X", src[0]);
126 }
127 else {
128 sprintf (dst, "-%02X", (~src[0] + 1) & 0xff);
129 }
130}
131
132static
133void disasm_imm16 (char *dst, const unsigned char *src)
134{
135 sprintf (dst, "%04X", e86_mk_uint16 (src[0], src[1]));
136}
137
138static
139void disasm_imm32 (char *dst, const unsigned char *src)
140{
141 sprintf (dst, "%04X:%04X",
142 e86_mk_uint16 (src[2], src[3]),
143 e86_mk_uint16 (src[0], src[1])
144 );
145}
146
147static
148void disasm_addr16 (e86_disasm_t *op, char *dst, const unsigned char *src)
149{
150 sprintf (dst, "[%s%04X]",
151 d_tab_segpre[op->seg],
152 e86_mk_uint16 (src[0], src[1])
153 );
154
155 op->seg = 0;
156}
157
158static
159void disasm_addr16_index (e86_disasm_t *op, char *dst, const char *reg)
160{
161 sprintf (dst, "[%s%s]", d_tab_segpre[op->seg], reg);
162}
163
164static
165unsigned disasm_ea (e86_disasm_t *op, char *str, const unsigned char *src, int s16)
166{
167 unsigned val;
168 unsigned ea;
169 d_tab_ea_t *eat;
170 const char *seg;
171
172 if ((src[0] & 0xc0) == 0xc0) {
173 if (s16) {
174 disasm_reg16 (str, src[0] & 7);
175 }
176 else {
177 disasm_reg8 (str, src[0] & 7);
178 }
179
180 return (1);
181 }
182
183 ea = (src[0] & 7) | ((src[0] & 0xc0) >> 3);
184 eat = &d_tab_ea[ea];
185
186 seg = d_tab_segpre[op->seg];
187
188 op->seg = 0;
189
190 strcpy (str, s16 ? "WORD " : "BYTE ");
191 str += strlen (str);
192
193 if (eat->arg == NULL) {
194 sprintf (str, "[%s%04X]", seg,
195 e86_mk_uint16 (src[1], src[2])
196 );
197 return (3);
198 }
199
200 switch (eat->cnt) {
201 case 0:
202 sprintf (str, "[%s%s]", seg, eat->arg);
203 break;
204
205 case 1:
206 sprintf (str, "[%s%s%c%02X]", seg, eat->arg,
207 (src[1] & 0x80) ? '-' : '+',
208 ((src[1] & 0x80) ? (~src[1] + 1) : src[1]) & 0xff
209 );
210 break;
211
212 case 2:
213 val = e86_mk_uint16 (src[1], src[2]);
214
215 sprintf (str, "[%s%s%c%04X]", seg, eat->arg,
216 (val & 0x8000) ? '-' : '+',
217 ((val & 0x8000) ? (~val + 1) : val) & 0xffff
218 );
219 break;
220
221 default:
222 strcpy (str, "<bad>");
223 break;
224 }
225
226 return (eat->cnt + 1);
227}
228
229static
230unsigned disasm_ea8 (e86_disasm_t *op, char *str, const unsigned char *src)
231{
232 return (disasm_ea (op, str, src, 0));
233}
234
235static
236unsigned disasm_ea16 (e86_disasm_t *op, char *str, const unsigned char *src)
237{
238 return (disasm_ea (op, str, src, 1));
239}
240
241
242static
243void dop_ud (e86_disasm_t *op, unsigned char *src)
244{
245 op->dat_n = 1;
246 op->arg_n = 1;
247
248 strcpy (op->op, "DB");
249 disasm_imm8 (op->arg1, src);
250}
251
252static
253void dop_const (e86_disasm_t *op, const char *sop, unsigned cnt)
254{
255 op->dat_n = cnt;
256 op->arg_n = 0;
257
258 strcpy (op->op, sop);
259}
260
261static
262void dop_ea8_reg8 (e86_disasm_t *op, unsigned char *src, char *sop)
263{
264 unsigned cnt;
265
266 strcpy (op->op, sop);
267 cnt = disasm_ea8 (op, op->arg1, src + 1);
268 disasm_reg8 (op->arg2, (src[1] >> 3) & 7);
269
270 op->dat_n = 1 + cnt;
271 op->arg_n = 2;
272}
273
274static
275void dop_ea16_reg16 (e86_disasm_t *op, unsigned char *src, char *sop)
276{
277 unsigned cnt;
278
279 strcpy (op->op, sop);
280 cnt = disasm_ea16 (op, op->arg1, src + 1);
281 disasm_reg16 (op->arg2, (src[1] >> 3) & 7);
282
283 op->dat_n = 1 + cnt;
284 op->arg_n = 2;
285}
286
287static
288void dop_reg8_ea8 (e86_disasm_t *op, unsigned char *src, char *sop)
289{
290 unsigned cnt;
291
292 strcpy (op->op, sop);
293 disasm_reg8 (op->arg1, (src[1] >> 3) & 7);
294 cnt = disasm_ea8 (op, op->arg2, src + 1);
295
296 op->dat_n = 1 + cnt;
297 op->arg_n = 2;
298}
299
300static
301void dop_reg16_ea16 (e86_disasm_t *op, unsigned char *src, char *sop)
302{
303 unsigned cnt;
304
305 strcpy (op->op, sop);
306 disasm_reg16 (op->arg1, (src[1] >> 3) & 7);
307 cnt = disasm_ea16 (op, op->arg2, src + 1);
308
309 op->dat_n = 1 + cnt;
310 op->arg_n = 2;
311}
312
313static
314void dop_ea8 (e86_disasm_t *op, unsigned char *src, char *sop)
315{
316 unsigned cnt;
317
318 strcpy (op->op, sop);
319 cnt = disasm_ea8 (op, op->arg1, src + 1);
320
321 op->dat_n = 1 + cnt;
322 op->arg_n = 1;
323}
324
325static
326void dop_ea16 (e86_disasm_t *op, unsigned char *src, char *sop)
327{
328 unsigned cnt;
329
330 strcpy (op->op, sop);
331 cnt = disasm_ea16 (op, op->arg1, src + 1);
332
333 op->dat_n = 1 + cnt;
334 op->arg_n = 1;
335}
336
337static
338void dop_seg_prefix (e86_disasm_t *op, unsigned char *src, const char *sop, unsigned i)
339{
340 unsigned tmp;
341
342 tmp = op->seg;
343
344 op->seg = i;
345
346 e86_disasm_op (op, src + 1);
347
348 if (op->seg == 0) {
349 op->dat_n += 1;
350 }
351 else {
352 dop_const (op, sop, 1);
353 }
354
355 op->seg = tmp;
356}
357
358
359/* DOP 00: ADD r/m8, reg8 */
360static
361void dop_00 (e86_disasm_t *op, unsigned char *src)
362{
363 dop_ea8_reg8 (op, src, "ADD");
364}
365
366/* DOP 01: ADD r/m16, reg16 */
367static
368void dop_01 (e86_disasm_t *op, unsigned char *src)
369{
370 dop_ea16_reg16 (op, src, "ADD");
371}
372
373/* DOP 02: ADD reg8, r/m8 */
374static
375void dop_02 (e86_disasm_t *op, unsigned char *src)
376{
377 dop_reg8_ea8 (op, src, "ADD");
378}
379
380/* DOP 03: ADD reg16, r/m16 */
381static void dop_03 (e86_disasm_t *op, unsigned char *src)
382{
383 dop_reg16_ea16 (op, src, "ADD");
384}
385
386/* DOP 04: ADD AL, data8 */
387static void dop_04 (e86_disasm_t *op, unsigned char *src)
388{
389 op->dat_n = 2;
390 op->arg_n = 2;
391
392 strcpy (op->op, "ADD");
393 strcpy (op->arg1, "AL");
394 disasm_imm8 (op->arg2, src + 1);
395}
396
397/* DOP 05: ADD AX, data16 */
398static void dop_05 (e86_disasm_t *op, unsigned char *src)
399{
400 op->dat_n = 3;
401 op->arg_n = 2;
402
403 strcpy (op->op, "ADD");
404 strcpy (op->arg1, "AX");
405 disasm_imm16 (op->arg2, src + 1);
406}
407
408/* DOP 06: PUSH ES */
409static void dop_06 (e86_disasm_t *op, unsigned char *src)
410{
411 op->dat_n = 1;
412 op->arg_n = 1;
413
414 strcpy (op->op, "PUSH");
415 strcpy (op->arg1, "ES");
416}
417
418/* DOP 07: POP ES */
419static void dop_07 (e86_disasm_t *op, unsigned char *src)
420{
421 op->dat_n = 1;
422 op->arg_n = 1;
423
424 strcpy (op->op, "POP");
425 strcpy (op->arg1, "ES");
426}
427
428/* DOP 08: OR r/m8, reg8 */
429static void dop_08 (e86_disasm_t *op, unsigned char *src)
430{
431 dop_ea8_reg8 (op, src, "OR");
432}
433
434/* DOP 09: OR r/m16, reg16 */
435static void dop_09 (e86_disasm_t *op, unsigned char *src)
436{
437 dop_ea16_reg16 (op, src, "OR");
438}
439
440/* DOP 0A: OR reg8, r/m8 */
441static void dop_0a (e86_disasm_t *op, unsigned char *src)
442{
443 dop_reg8_ea8 (op, src, "OR");
444}
445
446/* DOP 0B: OR reg16, r/m16 */
447static void dop_0b (e86_disasm_t *op, unsigned char *src)
448{
449 dop_reg16_ea16 (op, src, "OR");
450}
451
452/* DOP 0C: OR AL, data8 */
453static void dop_0c (e86_disasm_t *op, unsigned char *src)
454{
455 op->dat_n = 2;
456 op->arg_n = 2;
457
458 strcpy (op->op, "OR");
459 strcpy (op->arg1, "AL");
460 disasm_imm8 (op->arg2, src + 1);
461}
462
463/* DOP 0D: OR AX, data16 */
464static void dop_0d (e86_disasm_t *op, unsigned char *src)
465{
466 op->dat_n = 3;
467 op->arg_n = 2;
468
469 strcpy (op->op, "OR");
470 strcpy (op->arg1, "AX");
471 disasm_imm16 (op->arg2, src + 1);
472}
473
474/* DOP 0E: PUSH CS */
475static void dop_0e (e86_disasm_t *op, unsigned char *src)
476{
477 op->dat_n = 1;
478 op->arg_n = 1;
479
480 strcpy (op->op, "PUSH");
481 strcpy (op->arg1, "CS");
482}
483
484/* DOP 0F: POP ES */
485static void dop_0f (e86_disasm_t *op, unsigned char *src)
486{
487 op->dat_n = 1;
488 op->arg_n = 1;
489
490 strcpy (op->op, "POP");
491 strcpy (op->arg1, "CS");
492}
493
494/* DOP 10: ADC r/m8, reg8 */
495static void dop_10 (e86_disasm_t *op, unsigned char *src)
496{
497 dop_ea8_reg8 (op, src, "ADC");
498}
499
500/* DOP 11: ADC r/m16, reg16 */
501static void dop_11 (e86_disasm_t *op, unsigned char *src)
502{
503 dop_ea16_reg16 (op, src, "ADC");
504}
505
506/* DOP 12: ADC reg8, r/m8 */
507static void dop_12 (e86_disasm_t *op, unsigned char *src)
508{
509 dop_reg8_ea8 (op, src, "ADC");
510}
511
512/* DOP 13: ADC reg16, r/m16 */
513static void dop_13 (e86_disasm_t *op, unsigned char *src)
514{
515 dop_reg16_ea16 (op, src, "ADC");
516}
517
518/* DOP 14: ADC AL, data8 */
519static void dop_14 (e86_disasm_t *op, unsigned char *src)
520{
521 op->dat_n = 2;
522 op->arg_n = 2;
523
524 strcpy (op->op, "ADC");
525 strcpy (op->arg1, "AL");
526 disasm_imm8 (op->arg2, src + 1);
527}
528
529/* DOP 15: ADC AX, data16 */
530static void dop_15 (e86_disasm_t *op, unsigned char *src)
531{
532 op->dat_n = 3;
533 op->arg_n = 2;
534
535 strcpy (op->op, "ADC");
536 strcpy (op->arg1, "AX");
537 disasm_imm16 (op->arg2, src + 1);
538}
539
540/* DOP 16: PUSH SS */
541static void dop_16 (e86_disasm_t *op, unsigned char *src)
542{
543 op->dat_n = 1;
544 op->arg_n = 1;
545
546 strcpy (op->op, "PUSH");
547 strcpy (op->arg1, "SS");
548}
549
550/* DOP 17: POP SS */
551static void dop_17 (e86_disasm_t *op, unsigned char *src)
552{
553 op->dat_n = 1;
554 op->arg_n = 1;
555
556 strcpy (op->op, "POP");
557 strcpy (op->arg1, "SS");
558}
559
560/* DOP 18: SBB r/m8, reg8 */
561static
562void dop_18 (e86_disasm_t *op, unsigned char *src)
563{
564 dop_ea8_reg8 (op, src, "SBB");
565}
566
567/* DOP 19: SBB r/m16, reg16 */
568static
569void dop_19 (e86_disasm_t *op, unsigned char *src)
570{
571 dop_ea16_reg16 (op, src, "SBB");
572}
573
574/* DOP 1A: SBB reg8, r/m8 */
575static
576void dop_1a (e86_disasm_t *op, unsigned char *src)
577{
578 dop_reg8_ea8 (op, src, "SBB");
579}
580
581/* DOP 1B: SBB reg16, r/m16 */
582static void dop_1b (e86_disasm_t *op, unsigned char *src)
583{
584 dop_reg16_ea16 (op, src, "SBB");
585}
586
587/* DOP 1C: SBB AL, data8 */
588static void dop_1c (e86_disasm_t *op, unsigned char *src)
589{
590 op->dat_n = 2;
591 op->arg_n = 2;
592
593 strcpy (op->op, "SBB");
594 strcpy (op->arg1, "AL");
595 disasm_imm8 (op->arg2, src + 1);
596}
597
598/* DOP 1D: SBB AX, data16 */
599static void dop_1d (e86_disasm_t *op, unsigned char *src)
600{
601 op->dat_n = 3;
602 op->arg_n = 2;
603
604 strcpy (op->op, "SBB");
605 strcpy (op->arg1, "AX");
606 disasm_imm16 (op->arg2, src + 1);
607}
608
609/* DOP 1E: PUSH DS */
610static void dop_1e (e86_disasm_t *op, unsigned char *src)
611{
612 op->dat_n = 1;
613 op->arg_n = 1;
614
615 strcpy (op->op, "PUSH");
616 strcpy (op->arg1, "DS");
617}
618
619/* DOP 1F: POP SS */
620static void dop_1f (e86_disasm_t *op, unsigned char *src)
621{
622 op->dat_n = 1;
623 op->arg_n = 1;
624
625 strcpy (op->op, "POP");
626 strcpy (op->arg1, "DS");
627}
628
629/* DOP 20: AND r/m8, reg8 */
630static void dop_20 (e86_disasm_t *op, unsigned char *src)
631{
632 dop_ea8_reg8 (op, src, "AND");
633}
634
635/* DOP 21: AND r/m16, reg16 */
636static void dop_21 (e86_disasm_t *op, unsigned char *src)
637{
638 dop_ea16_reg16 (op, src, "AND");
639}
640
641/* DOP 22: AND reg8, r/m8 */
642static void dop_22 (e86_disasm_t *op, unsigned char *src)
643{
644 dop_reg8_ea8 (op, src, "AND");
645}
646
647/* DOP 23: AND reg16, r/m16 */
648static void dop_23 (e86_disasm_t *op, unsigned char *src)
649{
650 dop_reg16_ea16 (op, src, "AND");
651}
652
653/* DOP 24: AND AL, data8 */
654static void dop_24 (e86_disasm_t *op, unsigned char *src)
655{
656 op->dat_n = 2;
657 op->arg_n = 2;
658
659 strcpy (op->op, "AND");
660 strcpy (op->arg1, "AL");
661 disasm_imm8 (op->arg2, src + 1);
662}
663
664/* DOP 25: AND AX, data16 */
665static void dop_25 (e86_disasm_t *op, unsigned char *src)
666{
667 op->dat_n = 3;
668 op->arg_n = 2;
669
670 strcpy (op->op, "AND");
671 strcpy (op->arg1, "AX");
672 disasm_imm16 (op->arg2, src + 1);
673}
674
675/* DOP 26: ES: */
676static
677void dop_26 (e86_disasm_t *op, unsigned char *src)
678{
679 dop_seg_prefix (op, src, "ES:", 1);
680}
681
682/* DOP 27: DAA */
683static
684void dop_27 (e86_disasm_t *op, unsigned char *src)
685{
686 dop_const (op, "DAA", 1);
687}
688
689/* DOP 28: SUB r/m8, reg8 */
690static void dop_28 (e86_disasm_t *op, unsigned char *src)
691{
692 dop_ea8_reg8 (op, src, "SUB");
693}
694
695/* DOP 29: SUB r/m16, reg16 */
696static void dop_29 (e86_disasm_t *op, unsigned char *src)
697{
698 dop_ea16_reg16 (op, src, "SUB");
699}
700
701/* DOP 2A: SUB reg8, r/m8 */
702static void dop_2a (e86_disasm_t *op, unsigned char *src)
703{
704 dop_reg8_ea8 (op, src, "SUB");
705}
706
707/* DOP 2B: SUB reg16, r/m16 */
708static void dop_2b (e86_disasm_t *op, unsigned char *src)
709{
710 dop_reg16_ea16 (op, src, "SUB");
711}
712
713/* DOP 2C: SUB AL, data8 */
714static void dop_2c (e86_disasm_t *op, unsigned char *src)
715{
716 op->dat_n = 2;
717 op->arg_n = 2;
718
719 strcpy (op->op, "SUB");
720 strcpy (op->arg1, "AL");
721 disasm_imm8 (op->arg2, src + 1);
722}
723
724/* DOP 2D: SUB AX, data16 */
725static void dop_2d (e86_disasm_t *op, unsigned char *src)
726{
727 op->dat_n = 3;
728 op->arg_n = 2;
729
730 strcpy (op->op, "SUB");
731 strcpy (op->arg1, "AX");
732 disasm_imm16 (op->arg2, src + 1);
733}
734
735/* DOP 2E: CS: */
736static
737void dop_2e (e86_disasm_t *op, unsigned char *src)
738{
739 dop_seg_prefix (op, src, "CS:", 2);
740}
741
742/* DOP 2F: DAS */
743static
744void dop_2f (e86_disasm_t *op, unsigned char *src)
745{
746 dop_const (op, "DAS", 1);
747}
748
749/* DOP 30: XOR r/m8, reg8 */
750static void dop_30 (e86_disasm_t *op, unsigned char *src)
751{
752 dop_ea8_reg8 (op, src, "XOR");
753}
754
755/* DOP 31: XOR r/m16, reg16 */
756static void dop_31 (e86_disasm_t *op, unsigned char *src)
757{
758 dop_ea16_reg16 (op, src, "XOR");
759}
760
761/* DOP 32: XOR reg8, r/m8 */
762static void dop_32 (e86_disasm_t *op, unsigned char *src)
763{
764 dop_reg8_ea8 (op, src, "XOR");
765}
766
767/* DOP 33: XOR reg16, r/m16 */
768static void dop_33 (e86_disasm_t *op, unsigned char *src)
769{
770 dop_reg16_ea16 (op, src, "XOR");
771}
772
773/* DOP 34: XOR AL, data8 */
774static void dop_34 (e86_disasm_t *op, unsigned char *src)
775{
776 op->dat_n = 2;
777 op->arg_n = 2;
778
779 strcpy (op->op, "XOR");
780 strcpy (op->arg1, "AL");
781 disasm_imm8 (op->arg2, src + 1);
782}
783
784/* DOP 35: XOR AX, data16 */
785static void dop_35 (e86_disasm_t *op, unsigned char *src)
786{
787 op->dat_n = 3;
788 op->arg_n = 2;
789
790 strcpy (op->op, "XOR");
791 strcpy (op->arg1, "AX");
792 disasm_imm16 (op->arg2, src + 1);
793}
794
795/* DOP 36: SS: */
796static
797void dop_36 (e86_disasm_t *op, unsigned char *src)
798{
799 dop_seg_prefix (op, src, "SS:", 3);
800}
801
802/* DOP 37: AAA */
803static
804void dop_37 (e86_disasm_t *op, unsigned char *src)
805{
806 dop_const (op, "AAA", 1);
807}
808
809/* DOP 38: CMP r/m8, reg8 */
810static void dop_38 (e86_disasm_t *op, unsigned char *src)
811{
812 dop_ea8_reg8 (op, src, "CMP");
813}
814
815/* DOP 39: CMP r/m16, reg16 */
816static void dop_39 (e86_disasm_t *op, unsigned char *src)
817{
818 dop_ea16_reg16 (op, src, "CMP");
819}
820
821/* DOP 3A: CMP reg8, r/m8 */
822static void dop_3a (e86_disasm_t *op, unsigned char *src)
823{
824 dop_reg8_ea8 (op, src, "CMP");
825}
826
827/* DOP 3B: CMP reg16, r/m16 */
828static void dop_3b (e86_disasm_t *op, unsigned char *src)
829{
830 dop_reg16_ea16 (op, src, "CMP");
831}
832
833/* DOP 3C: CMP AL, data8 */
834static void dop_3c (e86_disasm_t *op, unsigned char *src)
835{
836 op->dat_n = 2;
837 op->arg_n = 2;
838
839 strcpy (op->op, "CMP");
840 strcpy (op->arg1, "AL");
841 disasm_imm8 (op->arg2, src + 1);
842}
843
844/* DOP 3D: CMP AX, data16 */
845static void dop_3d (e86_disasm_t *op, unsigned char *src)
846{
847 op->dat_n = 3;
848 op->arg_n = 2;
849
850 strcpy (op->op, "CMP");
851 strcpy (op->arg1, "AX");
852 disasm_imm16 (op->arg2, src + 1);
853}
854
855/* DOP 3E: DS: */
856static
857void dop_3e (e86_disasm_t *op, unsigned char *src)
858{
859 dop_seg_prefix (op, src, "DS:", 4);
860}
861
862/* DOP 3F: AAS */
863static
864void dop_3f (e86_disasm_t *op, unsigned char *src)
865{
866 dop_const (op, "AAS", 1);
867}
868
869/* DOP 4x: INC reg16 */
870static void dop_40 (e86_disasm_t *op, unsigned char *src)
871{
872 op->dat_n = 1;
873 op->arg_n = 1;
874
875 strcpy (op->op, "INC");
876 disasm_reg16 (op->arg1, src[0] & 7);
877}
878
879/* DOP 4x: DEC reg16 */
880static void dop_48 (e86_disasm_t *op, unsigned char *src)
881{
882 op->dat_n = 1;
883 op->arg_n = 1;
884
885 strcpy (op->op, "DEC");
886 disasm_reg16 (op->arg1, src[0] & 7);
887}
888
889/* DOP 5x: PUSH reg16 */
890static void dop_50 (e86_disasm_t *op, unsigned char *src)
891{
892 op->dat_n = 1;
893 op->arg_n = 1;
894
895 strcpy (op->op, "PUSH");
896 disasm_reg16 (op->arg1, src[0] & 7);
897}
898
899/* DOP 5x: POP reg16 */
900static void dop_58 (e86_disasm_t *op, unsigned char *src)
901{
902 op->dat_n = 1;
903 op->arg_n = 1;
904
905 strcpy (op->op, "POP");
906 disasm_reg16 (op->arg1, src[0] & 7);
907}
908
909static char *d_tab_70[16] = {
910"JO", "JNO", "JC", "JNC", "JZ", "JNZ", "JBE", "JA",
911"JS", "JNS", "JPE", "JPO", "JL", "JGE", "JLE", "JG"
912};
913
914/* DOP 60: PUSHA */
915static
916void dop_60 (e86_disasm_t *op, unsigned char *src)
917{
918 op->flags |= E86_DFLAGS_186;
919 dop_const (op, "PUSHA", 1);
920}
921
922/* DOP 61: POPA */
923static
924void dop_61 (e86_disasm_t *op, unsigned char *src)
925{
926 op->flags |= E86_DFLAGS_186;
927 dop_const (op, "POPA", 1);
928}
929
930/* DOP 62: BOUND */
931static
932void dop_62 (e86_disasm_t *op, unsigned char *src)
933{
934 op->flags |= E86_DFLAGS_186;
935
936 dop_reg16_ea16 (op, src, "BOUND");
937}
938
939/* DOP 66: PCE HOOK */
940static
941void dop_66 (e86_disasm_t *op, unsigned char *src)
942{
943 if (src[1] != 0x66) {
944 dop_ud (op, src);
945 return;
946 }
947
948 op->dat_n = 4;
949 op->arg_n = 2;
950
951 strcpy (op->op, "PCEH");
952 disasm_imm8 (op->arg1, src + 2);
953 disasm_imm8 (op->arg2, src + 3);
954}
955
956/* DOP 68: PUSH imm16 */
957static
958void dop_68 (e86_disasm_t *op, unsigned char *src)
959{
960 op->flags |= E86_DFLAGS_186;
961
962 op->dat_n = 3;
963 op->arg_n = 1;
964
965 strcpy (op->op, "PUSH");
966 disasm_imm16 (op->arg1, src + 1);
967}
968
969/* DOP 6A: PUSH imm8 */
970static
971void dop_6a (e86_disasm_t *op, unsigned char *src)
972{
973 op->flags |= E86_DFLAGS_186;
974
975 op->dat_n = 2;
976 op->arg_n = 1;
977
978 strcpy (op->op, "PUSH");
979 disasm_simm8 (op->arg1, src + 1);
980}
981
982/* DOP 6C: INSB */
983static
984void dop_6c (e86_disasm_t *op, unsigned char *src)
985{
986 op->flags |= E86_DFLAGS_186;
987 dop_const (op, "INSB", 1);
988}
989
990/* DOP 6D: INSW */
991static
992void dop_6d (e86_disasm_t *op, unsigned char *src)
993{
994 op->flags |= E86_DFLAGS_186;
995 dop_const (op, "INSW", 1);
996}
997
998/* DOP 6E: OUTB */
999static
1000void dop_6e (e86_disasm_t *op, unsigned char *src)
1001{
1002 op->flags |= E86_DFLAGS_186;
1003 dop_const (op, "OUTSB", 1);
1004}
1005
1006/* DOP 6F: OUTW */
1007static
1008void dop_6f (e86_disasm_t *op, unsigned char *src)
1009{
1010 op->flags |= E86_DFLAGS_186;
1011 dop_const (op, "OUTSW", 1);
1012}
1013
1014/* DOP 7x: Jxx imm8 */
1015static void dop_70 (e86_disasm_t *op, unsigned char *src)
1016{
1017 unsigned short t;
1018
1019 op->dat_n = 2;
1020 op->arg_n = 1;
1021
1022 t = 2 + e86_add_sint8 (op->ip, src[1]);
1023
1024 strcpy (op->op, d_tab_70[src[0] & 15]);
1025 disasm_uint16 (op->arg1, t);
1026}
1027
1028static char *d_tab_80[16] = {
1029 "ADD", "OR", "ADC", "SBB",
1030 "AND", "SUB", "XOR", "CMP"
1031};
1032
1033/* DOP 80: xxx r/m8, imm8 */
1034static void dop_80 (e86_disasm_t *op, unsigned char *src)
1035{
1036 unsigned cnt;
1037
1038 strcpy (op->op, d_tab_80[(src[1] >> 3) & 7]);
1039 cnt = disasm_ea8 (op, op->arg1, src + 1);
1040 disasm_imm8 (op->arg2, src + 1 + cnt);
1041
1042 op->dat_n = 2 + cnt;
1043 op->arg_n = 2;
1044}
1045
1046/* DOP 81: xxx r/m16, imm16 */
1047static void dop_81 (e86_disasm_t *op, unsigned char *src)
1048{
1049 unsigned cnt;
1050
1051 strcpy (op->op, d_tab_80[(src[1] >> 3) & 7]);
1052 cnt = disasm_ea16 (op, op->arg1, src + 1);
1053 disasm_imm16 (op->arg2, src + 1 + cnt);
1054
1055 op->dat_n = 3 + cnt;
1056 op->arg_n = 2;
1057}
1058
1059/* DOP 83: xxx r/m16, imm8 */
1060static void dop_83 (e86_disasm_t *op, unsigned char *src)
1061{
1062 unsigned cnt;
1063
1064 strcpy (op->op, d_tab_80[(src[1] >> 3) & 7]);
1065 cnt = disasm_ea16 (op, op->arg1, src + 1);
1066 disasm_simm8 (op->arg2, src + 1 + cnt);
1067
1068 op->dat_n = 2 + cnt;
1069 op->arg_n = 2;
1070}
1071
1072/* DOP 84: TEST r/m8, reg8 */
1073static
1074void dop_84 (e86_disasm_t *op, unsigned char *src)
1075{
1076 dop_ea8_reg8 (op, src, "TEST");
1077}
1078
1079/* DOP 85: TEST r/m16, reg16 */
1080static
1081void dop_85 (e86_disasm_t *op, unsigned char *src)
1082{
1083 dop_ea16_reg16 (op, src, "TEST");
1084}
1085
1086/* DOP 86: XCHG r/m8, reg8 */
1087static void dop_86 (e86_disasm_t *op, unsigned char *src)
1088{
1089 dop_ea8_reg8 (op, src, "XCHG");
1090}
1091
1092/* DOP 87: XCHG r/m16, reg16 */
1093static void dop_87 (e86_disasm_t *op, unsigned char *src)
1094{
1095 dop_ea16_reg16 (op, src, "XCHG");
1096}
1097
1098/* DOP 88: MOV r/m8, reg8 */
1099static void dop_88 (e86_disasm_t *op, unsigned char *src)
1100{
1101 dop_ea8_reg8 (op, src, "MOV");
1102}
1103
1104/* DOP 89: MOV r/m16, reg16 */
1105static void dop_89 (e86_disasm_t *op, unsigned char *src)
1106{
1107 dop_ea16_reg16 (op, src, "MOV");
1108}
1109
1110/* DOP 8A: MOV reg8, r/m8 */
1111static void dop_8a (e86_disasm_t *op, unsigned char *src)
1112{
1113 dop_reg8_ea8 (op, src, "MOV");
1114}
1115
1116/* DOP 8B: MOV reg16, r/m16 */
1117static void dop_8b (e86_disasm_t *op, unsigned char *src)
1118{
1119 dop_reg16_ea16 (op, src, "MOV");
1120}
1121
1122/* DOP 8C: MOV r/m16, sreg */
1123static void dop_8c (e86_disasm_t *op, unsigned char *src)
1124{
1125 unsigned cnt;
1126
1127 strcpy (op->op, "MOV");
1128 cnt = disasm_ea16 (op, op->arg1, src + 1);
1129 disasm_sreg (op->arg2, (src[1] >> 3) & 3);
1130
1131 op->dat_n = 1 + cnt;
1132 op->arg_n = 2;
1133}
1134
1135/* DOP 8D: LEA reg16, r/m16 */
1136static void dop_8d (e86_disasm_t *op, unsigned char *src)
1137{
1138 dop_reg16_ea16 (op, src, "LEA");
1139}
1140
1141/* DOP 8E: MOV sreg, r/m16 */
1142static void dop_8e (e86_disasm_t *op, unsigned char *src)
1143{
1144 unsigned cnt;
1145
1146 strcpy (op->op, "MOV");
1147 disasm_sreg (op->arg1, (src[1] >> 3) & 3);
1148 cnt = disasm_ea16 (op, op->arg2, src + 1);
1149
1150 op->dat_n = cnt + 1;
1151 op->arg_n = 2;
1152}
1153
1154/* DOP 8F: POP r/m16 */
1155static void dop_8f (e86_disasm_t *op, unsigned char *src)
1156{
1157 dop_ea16 (op, src, "POP");
1158}
1159
1160/* DOP 90: NOP */
1161static
1162void dop_90 (e86_disasm_t *op, unsigned char *src)
1163{
1164 dop_const (op, "NOP", 1);
1165}
1166
1167/* DOP 9x: XCHG AX, reg16 */
1168static void dop_91 (e86_disasm_t *op, unsigned char *src)
1169{
1170 strcpy (op->op, "XCHG");
1171 strcpy (op->arg1, "AX");
1172 disasm_reg16 (op->arg2, src[0] & 7);
1173
1174 op->dat_n = 1;
1175 op->arg_n = 2;
1176}
1177
1178/* DOP 98: CBW */
1179static void dop_98 (e86_disasm_t *op, unsigned char *src)
1180{
1181 dop_const (op, "CBW", 1);
1182}
1183
1184/* DOP 99: CWD */
1185static void dop_99 (e86_disasm_t *op, unsigned char *src)
1186{
1187 dop_const (op, "CWD", 1);
1188}
1189
1190/* DOP 9A: CALL imm32 */
1191static
1192void dop_9a (e86_disasm_t *op, unsigned char *src)
1193{
1194 op->flags |= E86_DFLAGS_CALL;
1195
1196 op->dat_n = 5;
1197 op->arg_n = 1;
1198
1199 strcpy (op->op, "CALL");
1200 disasm_imm32 (op->arg1, src + 1);
1201}
1202
1203/* DOP 9B: WAIT */
1204static void dop_9b (e86_disasm_t *op, unsigned char *src)
1205{
1206 dop_const (op, "WAIT", 1);
1207}
1208
1209/* DOP 9C: PUSHF */
1210static void dop_9c (e86_disasm_t *op, unsigned char *src)
1211{
1212 dop_const (op, "PUSHF", 1);
1213}
1214
1215/* DOP 9D: POPF */
1216static void dop_9d (e86_disasm_t *op, unsigned char *src)
1217{
1218 dop_const (op, "POPF", 1);
1219}
1220
1221/* DOP 9E: SAHF */
1222static void dop_9e (e86_disasm_t *op, unsigned char *src)
1223{
1224 dop_const (op, "SAHF", 1);
1225}
1226
1227/* DOP 9F: LAHF */
1228static void dop_9f (e86_disasm_t *op, unsigned char *src)
1229{
1230 dop_const (op, "LAHF", 1);
1231}
1232
1233/* DOP A0: MOV AL, [data16] */
1234static void dop_a0 (e86_disasm_t *op, unsigned char *src)
1235{
1236 op->dat_n = 3;
1237 op->arg_n = 2;
1238
1239 strcpy (op->op, "MOV");
1240 strcpy (op->arg1, "AL");
1241 disasm_addr16 (op, op->arg2, src + 1);
1242}
1243
1244/* DOP A1: MOV AX, [data16] */
1245static void dop_a1 (e86_disasm_t *op, unsigned char *src)
1246{
1247 op->dat_n = 3;
1248 op->arg_n = 2;
1249
1250 strcpy (op->op, "MOV");
1251 strcpy (op->arg1, "AX");
1252 disasm_addr16 (op, op->arg2, src + 1);
1253}
1254
1255/* DOP A2: MOV [data16], AL */
1256static void dop_a2 (e86_disasm_t *op, unsigned char *src)
1257{
1258 op->dat_n = 3;
1259 op->arg_n = 2;
1260
1261 strcpy (op->op, "MOV");
1262 disasm_addr16 (op, op->arg1, src + 1);
1263 strcpy (op->arg2, "AL");
1264}
1265
1266/* DOP A3: MOV [data16], AX */
1267static void dop_a3 (e86_disasm_t *op, unsigned char *src)
1268{
1269 op->dat_n = 3;
1270 op->arg_n = 2;
1271
1272 strcpy (op->op, "MOV");
1273 disasm_addr16 (op, op->arg1, src + 1);
1274 strcpy (op->arg2, "AX");
1275}
1276
1277/* DOP A4: MOVSB */
1278static
1279void dop_a4 (e86_disasm_t *op, unsigned char *src)
1280{
1281 dop_const (op, "MOVSB", 1);
1282
1283 if (op->seg != 0) {
1284 strcpy (op->arg1, "[ES:DI]");
1285 disasm_addr16_index (op, op->arg2, "SI");
1286 op->arg_n = 2;
1287 op->seg = 0;
1288 }
1289}
1290
1291/* DOP A5: MOVSW */
1292static
1293void dop_a5 (e86_disasm_t *op, unsigned char *src)
1294{
1295 dop_const (op, "MOVSW", 1);
1296
1297 if (op->seg != 0) {
1298 strcpy (op->arg1, "[ES:DI]");
1299 disasm_addr16_index (op, op->arg2, "SI");
1300 op->arg_n = 2;
1301 op->seg = 0;
1302 }
1303}
1304
1305/* DOP A6: CMPSB */
1306static
1307void dop_a6 (e86_disasm_t *op, unsigned char *src)
1308{
1309 dop_const (op, "CMPSB", 1);
1310
1311 if (op->seg != 0) {
1312 strcpy (op->arg1, "[ES:DI]");
1313 disasm_addr16_index (op, op->arg2, "SI");
1314 op->arg_n = 2;
1315 op->seg = 0;
1316 }
1317}
1318
1319/* DOP A7: CMPSW */
1320static
1321void dop_a7 (e86_disasm_t *op, unsigned char *src)
1322{
1323 dop_const (op, "CMPSW", 1);
1324
1325 if (op->seg != 0) {
1326 strcpy (op->arg1, "[ES:DI]");
1327 disasm_addr16_index (op, op->arg2, "SI");
1328 op->arg_n = 2;
1329 op->seg = 0;
1330 }
1331}
1332
1333/* DOP A8: TEST AL, data8 */
1334static void dop_a8 (e86_disasm_t *op, unsigned char *src)
1335{
1336 op->dat_n = 2;
1337 op->arg_n = 2;
1338
1339 strcpy (op->op, "TEST");
1340 strcpy (op->arg1, "AL");
1341 disasm_imm8 (op->arg2, src + 1);
1342}
1343
1344/* DOP A9: TEST AX, data16 */
1345static void dop_a9 (e86_disasm_t *op, unsigned char *src)
1346{
1347 op->dat_n = 3;
1348 op->arg_n = 2;
1349
1350 strcpy (op->op, "TEST");
1351 strcpy (op->arg1, "AX");
1352 disasm_imm16 (op->arg2, src + 1);
1353}
1354
1355/* DOP AA: STOSB */
1356static
1357void dop_aa (e86_disasm_t *op, unsigned char *src)
1358{
1359 dop_const (op, "STOSB", 1);
1360}
1361
1362/* DOP AB: STOSW */
1363static
1364void dop_ab (e86_disasm_t *op, unsigned char *src)
1365{
1366 dop_const (op, "STOSW", 1);
1367}
1368
1369/* DOP AC: LODSB */
1370static
1371void dop_ac (e86_disasm_t *op, unsigned char *src)
1372{
1373 dop_const (op, "LODSB", 1);
1374
1375 if (op->seg != 0) {
1376 disasm_addr16_index (op, op->arg1, "SI");
1377 op->arg_n = 1;
1378 op->seg = 0;
1379 }
1380}
1381
1382/* DOP AD: LODSW */
1383static
1384void dop_ad (e86_disasm_t *op, unsigned char *src)
1385{
1386 dop_const (op, "LODSW", 1);
1387
1388 if (op->seg != 0) {
1389 disasm_addr16_index (op, op->arg1, "SI");
1390 op->arg_n = 1;
1391 op->seg = 0;
1392 }
1393}
1394
1395/* DOP AE: SCASB */
1396static
1397void dop_ae (e86_disasm_t *op, unsigned char *src)
1398{
1399 dop_const (op, "SCASB", 1);
1400}
1401
1402/* DOP AF: SCASW */
1403static
1404void dop_af (e86_disasm_t *op, unsigned char *src)
1405{
1406 dop_const (op, "SCASW", 1);
1407}
1408
1409/* DOP Bx: MOV reg8, imm8 */
1410static void dop_b0 (e86_disasm_t *op, unsigned char *src)
1411{
1412 op->dat_n = 2;
1413 op->arg_n = 2;
1414
1415 strcpy (op->op, "MOV");
1416 disasm_reg8 (op->arg1, src[0] & 7);
1417 disasm_imm8 (op->arg2, src + 1);
1418}
1419
1420/* DOP Bx: MOV reg16, imm16 */
1421static void dop_b8 (e86_disasm_t *op, unsigned char *src)
1422{
1423 op->dat_n = 3;
1424 op->arg_n = 2;
1425
1426 strcpy (op->op, "MOV");
1427 disasm_reg16 (op->arg1, src[0] & 7);
1428 disasm_imm16 (op->arg2, src + 1);
1429}
1430
1431static char *d_tab_c0[8] = {
1432 "ROL", "ROR", "RCL", "RCR",
1433 "SHL", "SHR", "???", "SAR"
1434};
1435
1436/* DOP C0: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m8, imm8 */
1437static void dop_c0 (e86_disasm_t *op, unsigned char *src)
1438{
1439 unsigned xop, cnt;
1440
1441 op->flags |= E86_DFLAGS_186;
1442
1443 xop = (src[1] >> 3) & 7;
1444
1445 strcpy (op->op, d_tab_c0[xop]);
1446 cnt = disasm_ea8 (op, op->arg1, src + 1);
1447 disasm_imm8 (op->arg2, src + cnt + 1);
1448
1449 op->dat_n = 2 + cnt;
1450 op->arg_n = 2;
1451}
1452
1453/* DOP C1: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m16, imm8 */
1454static void dop_c1 (e86_disasm_t *op, unsigned char *src)
1455{
1456 unsigned xop, cnt;
1457
1458 op->flags |= E86_DFLAGS_186;
1459
1460 xop = (src[1] >> 3) & 7;
1461
1462 strcpy (op->op, d_tab_c0[xop]);
1463 cnt = disasm_ea16 (op, op->arg1, src + 1);
1464 disasm_imm8 (op->arg2, src + cnt + 1);
1465
1466 op->dat_n = 2 + cnt;
1467 op->arg_n = 2;
1468}
1469
1470/* DOP C2: RET imm16 */
1471static void dop_c2 (e86_disasm_t *op, unsigned char *src)
1472{
1473 op->dat_n = 3;
1474 op->arg_n = 1;
1475
1476 strcpy (op->op, "RETN");
1477 disasm_imm16 (op->arg1, src + 1);
1478}
1479
1480/* DOP C3: RET */
1481static
1482void dop_c3 (e86_disasm_t *op, unsigned char *src)
1483{
1484 dop_const (op, "RETN", 1);
1485}
1486
1487/* DOP C4: LES reg16, r/m16 */
1488static void dop_c4 (e86_disasm_t *op, unsigned char *src)
1489{
1490 dop_reg16_ea16 (op, src, "LES");
1491}
1492
1493/* DOP C5: LDS reg16, r/m16 */
1494static void dop_c5 (e86_disasm_t *op, unsigned char *src)
1495{
1496 dop_reg16_ea16 (op, src, "LDS");
1497}
1498
1499/* DOP C6: MOV r/m8, imm8 */
1500static void dop_c6 (e86_disasm_t *op, unsigned char *src)
1501{
1502 strcpy (op->op, "MOV");
1503 op->dat_n = disasm_ea8 (op, op->arg1, src + 1);
1504 disasm_imm8 (op->arg2, src + 1 + op->dat_n);
1505
1506 op->dat_n += 2;
1507 op->arg_n = 2;
1508}
1509
1510/* DOP C7: MOV r/m16, imm16 */
1511static void dop_c7 (e86_disasm_t *op, unsigned char *src)
1512{
1513 strcpy (op->op, "MOV");
1514 op->dat_n = disasm_ea16 (op, op->arg1, src + 1);
1515 disasm_imm16 (op->arg2, src + 1 + op->dat_n);
1516
1517 op->dat_n += 3;
1518 op->arg_n = 2;
1519}
1520
1521/* DOP C8: ENTER imm16, imm8 */
1522static
1523void dop_c8 (e86_disasm_t *op, unsigned char *src)
1524{
1525 op->flags |= E86_DFLAGS_186;
1526
1527 strcpy (op->op, "ENTER");
1528 disasm_imm16 (op->arg1, src + 1);
1529 disasm_imm8 (op->arg2, src + 3);
1530
1531 op->dat_n = 4;
1532 op->arg_n = 2;
1533}
1534
1535/* DOP C9: LEAVE */
1536static
1537void dop_c9 (e86_disasm_t *op, unsigned char *src)
1538{
1539 op->flags |= E86_DFLAGS_186;
1540 dop_const (op, "LEAVE", 1);
1541}
1542
1543/* DOP CA: RETF imm16 */
1544static
1545void dop_ca (e86_disasm_t *op, unsigned char *src)
1546{
1547 op->dat_n = 3;
1548 op->arg_n = 1;
1549
1550 strcpy (op->op, "RETF");
1551 disasm_imm16 (op->arg1, src + 1);
1552}
1553
1554/* DOP CB: RETF */
1555static
1556void dop_cb (e86_disasm_t *op, unsigned char *src)
1557{
1558 dop_const (op, "RETF", 1);
1559}
1560
1561/* DOP CC: INT3 */
1562static
1563void dop_cc (e86_disasm_t *op, unsigned char *src)
1564{
1565 dop_const (op, "INT3", 1);
1566 op->flags |= E86_DFLAGS_CALL;
1567}
1568
1569/* DOP CD: INT imm8 */
1570static
1571void dop_cd (e86_disasm_t *op, unsigned char *src)
1572{
1573 op->flags |= E86_DFLAGS_CALL;
1574
1575 op->dat_n = 2;
1576 op->arg_n = 1;
1577
1578 strcpy (op->op, "INT");
1579 disasm_imm8 (op->arg1, src + 1);
1580}
1581
1582/* DOP CE: INTO */
1583static
1584void dop_ce (e86_disasm_t *op, unsigned char *src)
1585{
1586 dop_const (op, "INTO", 1);
1587 op->flags |= E86_DFLAGS_CALL;
1588}
1589
1590/* DOP CF: IRET */
1591static
1592void dop_cf (e86_disasm_t *op, unsigned char *src)
1593{
1594 dop_const (op, "IRET", 1);
1595}
1596
1597static char *d_tab_d0[8] = {
1598 "ROL", "ROR", "RCL", "RCR",
1599 "SHL", "SHR", "???", "SAR"
1600};
1601
1602/* DOP D0: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m8, 1 */
1603static void dop_d0 (e86_disasm_t *op, unsigned char *src)
1604{
1605 unsigned xop, cnt;
1606
1607 xop = (src[1] >> 3) & 7;
1608
1609 strcpy (op->op, d_tab_d0[xop]);
1610 cnt = disasm_ea8 (op, op->arg1, src + 1);
1611 strcpy (op->arg2, "1");
1612
1613 op->dat_n = 1 + cnt;
1614 op->arg_n = 2;
1615}
1616
1617/* DOP D1: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m16, 1 */
1618static void dop_d1 (e86_disasm_t *op, unsigned char *src)
1619{
1620 unsigned xop, cnt;
1621
1622 xop = (src[1] >> 3) & 7;
1623
1624 strcpy (op->op, d_tab_d0[xop]);
1625 cnt = disasm_ea16 (op, op->arg1, src + 1);
1626 strcpy (op->arg2, "1");
1627
1628 op->dat_n = 1 + cnt;
1629 op->arg_n = 2;
1630}
1631
1632static char *d_tab_d2[8] = {
1633 "ROL", "ROR", "RCL", "RCR",
1634 "SHL", "SHR", "???", "SAR"
1635};
1636
1637/* DOP D2: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m8, CL */
1638static void dop_d2 (e86_disasm_t *op, unsigned char *src)
1639{
1640 unsigned xop, cnt;
1641
1642 xop = (src[1] >> 3) & 7;
1643
1644 strcpy (op->op, d_tab_d2[xop]);
1645 cnt = disasm_ea8 (op, op->arg1, src + 1);
1646 disasm_reg8 (op->arg2, E86_REG_CL);
1647
1648 op->dat_n = 1 + cnt;
1649 op->arg_n = 2;
1650}
1651
1652/* DOP D3: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m16, CL */
1653static void dop_d3 (e86_disasm_t *op, unsigned char *src)
1654{
1655 unsigned xop, cnt;
1656
1657 xop = (src[1] >> 3) & 7;
1658
1659 strcpy (op->op, d_tab_d2[xop]);
1660 cnt = disasm_ea16 (op, op->arg1, src + 1);
1661 disasm_reg8 (op->arg2, E86_REG_CL);
1662
1663 op->dat_n = 1 + cnt;
1664 op->arg_n = 2;
1665}
1666
1667/* DOP D4: AAM imm8 */
1668static void dop_d4 (e86_disasm_t *op, unsigned char *src)
1669{
1670 strcpy (op->op, "AAM");
1671 disasm_imm8 (op->arg1, src + 1);
1672
1673 op->dat_n = 2;
1674 op->arg_n = 1;
1675}
1676
1677/* DOP D5: AAD imm8 */
1678static void dop_d5 (e86_disasm_t *op, unsigned char *src)
1679{
1680 strcpy (op->op, "AAD");
1681 disasm_imm8 (op->arg1, src + 1);
1682
1683 op->dat_n = 2;
1684 op->arg_n = 1;
1685}
1686
1687/* DOP D7: XLAT */
1688static
1689void dop_d7 (e86_disasm_t *op, unsigned char *src)
1690{
1691 dop_const (op, "XLAT", 1);
1692}
1693
1694static char *d_tab_e0[4] = {
1695 "LOOPNZ", "LOOPZ", "LOOP", "JCXZ"
1696};
1697
1698/* DOP E0-E3: LOOPxx imm8 */
1699static void dop_e0 (e86_disasm_t *op, unsigned char *src)
1700{
1701 unsigned short t;
1702
1703 op->flags |= E86_DFLAGS_LOOP;
1704
1705 op->dat_n = 2;
1706 op->arg_n = 1;
1707
1708 t = 2 + e86_add_sint8 (op->ip, src[1]);
1709
1710 strcpy (op->op, d_tab_e0[src[0] - 0xe0]);
1711 disasm_uint16 (op->arg1, t);
1712}
1713
1714/* DOP E4: IN AL, imm8 */
1715static void dop_e4 (e86_disasm_t *op, unsigned char *src)
1716{
1717 op->dat_n = 2;
1718 op->arg_n = 2;
1719
1720 strcpy (op->op, "IN");
1721 strcpy (op->arg1, "AL");
1722 disasm_imm8 (op->arg2, src + 1);
1723}
1724
1725/* DOP E5: IN AX, imm8 */
1726static void dop_e5 (e86_disasm_t *op, unsigned char *src)
1727{
1728 op->dat_n = 2;
1729 op->arg_n = 2;
1730
1731 strcpy (op->op, "IN");
1732 strcpy (op->arg1, "AX");
1733 disasm_imm8 (op->arg2, src + 1);
1734}
1735
1736/* DOP E6: OUT imm8, AL */
1737static void dop_e6 (e86_disasm_t *op, unsigned char *src)
1738{
1739 op->dat_n = 2;
1740 op->arg_n = 2;
1741
1742 strcpy (op->op, "OUT");
1743 disasm_imm8 (op->arg1, src + 1);
1744 strcpy (op->arg2, "AL");
1745}
1746
1747/* DOP E7: OUT imm8, AX */
1748static void dop_e7 (e86_disasm_t *op, unsigned char *src)
1749{
1750 op->dat_n = 2;
1751 op->arg_n = 2;
1752
1753 strcpy (op->op, "OUT");
1754 disasm_imm8 (op->arg1, src + 1);
1755 strcpy (op->arg2, "AX");
1756}
1757
1758/* DOP E8: CALL imm16 */
1759static
1760void dop_e8 (e86_disasm_t *op, unsigned char *src)
1761{
1762 unsigned short t;
1763
1764 op->flags |= E86_DFLAGS_CALL;
1765
1766 op->dat_n = 3;
1767 op->arg_n = 1;
1768
1769 t = (op->ip + e86_mk_uint16 (src[1], src[2]) + 3) & 0xffff;
1770
1771 strcpy (op->op, "CALL");
1772 disasm_uint16 (op->arg1, t);
1773}
1774
1775/* DOP E9: JMP imm16 */
1776static void dop_e9 (e86_disasm_t *op, unsigned char *src)
1777{
1778 unsigned short t;
1779
1780 op->dat_n = 3;
1781 op->arg_n = 1;
1782
1783 t = (op->ip + e86_mk_uint16 (src[1], src[2]) + 3) & 0xffff;
1784
1785 strcpy (op->op, "JMPN");
1786 disasm_uint16 (op->arg1, t);
1787}
1788
1789/* DOP EA: JMP imm32 */
1790static void dop_ea (e86_disasm_t *op, unsigned char *src)
1791{
1792 op->dat_n = 5;
1793 op->arg_n = 1;
1794
1795 strcpy (op->op, "JMPF");
1796 disasm_imm32 (op->arg1, src + 1);
1797}
1798
1799/* DOP EB: JMP imm8 */
1800static void dop_eb (e86_disasm_t *op, unsigned char *src)
1801{
1802 unsigned short t;
1803
1804 op->dat_n = 2;
1805 op->arg_n = 1;
1806
1807 t = e86_add_sint8 (op->ip + 2, src[1]);
1808
1809 strcpy (op->op, "JMPS");
1810 disasm_uint16 (op->arg1, t);
1811}
1812
1813/* DOP EC: IN AL, DX */
1814static void dop_ec (e86_disasm_t *op, unsigned char *src)
1815{
1816 op->dat_n = 1;
1817 op->arg_n = 2;
1818
1819 strcpy (op->op, "IN");
1820 strcpy (op->arg1, "AL");
1821 strcpy (op->arg2, "DX");
1822}
1823
1824/* DOP ED: IN AX, DX */
1825static void dop_ed (e86_disasm_t *op, unsigned char *src)
1826{
1827 op->dat_n = 1;
1828 op->arg_n = 2;
1829
1830 strcpy (op->op, "IN");
1831 strcpy (op->arg1, "AX");
1832 strcpy (op->arg2, "DX");
1833}
1834
1835/* DOP EE: OUT DX, AL */
1836static
1837void dop_ee (e86_disasm_t *op, unsigned char *src)
1838{
1839 op->dat_n = 1;
1840 op->arg_n = 2;
1841
1842 strcpy (op->op, "OUT");
1843 strcpy (op->arg1, "DX");
1844 strcpy (op->arg2, "AL");
1845}
1846
1847/* DOP EF: OUT DX, AX */
1848static
1849void dop_ef (e86_disasm_t *op, unsigned char *src)
1850{
1851 op->dat_n = 1;
1852 op->arg_n = 2;
1853
1854 strcpy (op->op, "OUT");
1855 strcpy (op->arg1, "DX");
1856 strcpy (op->arg2, "AX");
1857}
1858
1859/* DOP F0: LOCK */
1860static
1861void dop_f0 (e86_disasm_t *op, unsigned char *src)
1862{
1863 char tmp[256];
1864
1865 e86_disasm (op, src + 1, op->ip);
1866
1867 strcpy (tmp, op->op);
1868 strcpy (op->op, "LOCK ");
1869 strcat (op->op, tmp);
1870
1871 op->dat_n += 1;
1872}
1873
1874/* DOP F2: REPNE */
1875static
1876void dop_f2 (e86_disasm_t *op, unsigned char *src)
1877{
1878 char tmp[256];
1879
1880 e86_disasm (op, src + 1, op->ip);
1881
1882 strcpy (tmp, op->op);
1883 strcpy (op->op, "REPNE ");
1884 strcat (op->op, tmp);
1885
1886 op->dat_n += 1;
1887}
1888
1889/* DOP F3: REP */
1890static
1891void dop_f3 (e86_disasm_t *op, unsigned char *src)
1892{
1893 char tmp[256];
1894
1895 e86_disasm (op, src + 1, op->ip);
1896
1897 strcpy (tmp, op->op);
1898 strcpy (op->op, "REP ");
1899 strcat (op->op, tmp);
1900
1901 op->dat_n += 1;
1902}
1903
1904/* DOP F4: HLT */
1905static
1906void dop_f4 (e86_disasm_t *op, unsigned char *src)
1907{
1908 dop_const (op, "HLT", 1);
1909}
1910
1911/* DOP F5: CMC */
1912static
1913void dop_f5 (e86_disasm_t *op, unsigned char *src)
1914{
1915 dop_const (op, "CMC", 1);
1916}
1917
1918/* DOP F6: xxx r/m8 */
1919static
1920void dop_f6 (e86_disasm_t *op, unsigned char *src)
1921{
1922 unsigned xop, cnt;
1923
1924 xop = (src[1] >> 3) & 7;
1925
1926 switch (xop) {
1927 case 0:
1928 strcpy (op->op, "TEST");
1929 cnt = disasm_ea8 (op, op->arg1, src + 1);
1930 disasm_imm8 (op->arg2, src + 1 + cnt);
1931 op->dat_n = cnt + 2;
1932 op->arg_n = 2;
1933 return;
1934
1935 case 1:
1936 dop_ud (op, src);
1937 return;
1938
1939 case 2:
1940 dop_ea8 (op, src, "NOT");
1941 return;
1942
1943 case 3:
1944 dop_ea8 (op, src, "NEG");
1945 return;
1946
1947 case 4:
1948 dop_ea8 (op, src, "MUL");
1949 return;
1950
1951 case 5:
1952 dop_ea8 (op, src, "IMUL");
1953 return;
1954
1955 case 6:
1956 dop_ea8 (op, src, "DIV");
1957 return;
1958
1959 case 7:
1960 dop_ea8 (op, src, "IDIV");
1961 return;
1962
1963 default:
1964 dop_ud (op, src);
1965 return;
1966 }
1967}
1968
1969/* DOP F7: xxx r/m16 */
1970static
1971void dop_f7 (e86_disasm_t *op, unsigned char *src)
1972{
1973 unsigned xop, cnt;
1974
1975 xop = (src[1] >> 3) & 7;
1976
1977 switch (xop) {
1978 case 0:
1979 strcpy (op->op, "TEST");
1980 cnt = disasm_ea16 (op, op->arg1, src + 1);
1981 disasm_imm16 (op->arg2, src + 1 + cnt);
1982 op->dat_n = cnt + 3;
1983 op->arg_n = 2;
1984 return;
1985
1986 case 1:
1987 dop_ud (op, src);
1988 return;
1989
1990 case 2:
1991 dop_ea16 (op, src, "NOT");
1992 return;
1993
1994 case 3:
1995 dop_ea16 (op, src, "NEG");
1996 return;
1997
1998 case 4:
1999 dop_ea16 (op, src, "MUL");
2000 return;
2001
2002 case 5:
2003 dop_ea16 (op, src, "IMUL");
2004 return;
2005
2006 case 6:
2007 dop_ea16 (op, src, "DIV");
2008 return;
2009
2010 case 7:
2011 dop_ea16 (op, src, "IDIV");
2012 return;
2013
2014 default:
2015 dop_ud (op, src);
2016 return;
2017 }
2018}
2019
2020static char *d_tab_f8[6] = {
2021 "CLC", "STC", "CLI", "STI", "CLD", "STD"
2022};
2023
2024/* DOP F8-FD: CLC, STC, CLI, STI, CLD, STD */
2025static void dop_f8 (e86_disasm_t *op, unsigned char *src)
2026{
2027 op->dat_n = 1;
2028 op->arg_n = 0;
2029
2030 strcpy (op->op, d_tab_f8[src[0] - 0xf8]);
2031}
2032
2033/* DOP FE: INC, DEC r/m8 */
2034static void dop_fe (e86_disasm_t *op, unsigned char *src)
2035{
2036 unsigned xop, cnt;
2037
2038 xop = (src[1] >> 3) & 7;
2039
2040 switch (xop) {
2041 case 0: /* INC r/m8 */
2042 strcpy (op->op, "INC");
2043 cnt = disasm_ea8 (op, op->arg1, src + 1);
2044 op->dat_n = cnt + 1;
2045 op->arg_n = 1;
2046 return;
2047
2048 case 1: /* DEC r/m8 */
2049 strcpy (op->op, "DEC");
2050 cnt = disasm_ea8 (op, op->arg1, src + 1);
2051 op->dat_n = cnt + 1;
2052 op->arg_n = 1;
2053 return;
2054
2055 default:
2056 dop_ud (op, src);
2057 return;
2058 }
2059}
2060
2061/* DOP FF: xxx r/m16 */
2062static
2063void dop_ff (e86_disasm_t *op, unsigned char *src)
2064{
2065 unsigned xop;
2066
2067 xop = (src[1] >> 3) & 7;
2068
2069 switch (xop) {
2070 case 0:
2071 dop_ea16 (op, src, "INC");
2072 return;
2073
2074 case 1:
2075 dop_ea16 (op, src, "DEC");
2076 return;
2077
2078 case 2:
2079 dop_ea16 (op, src, "CALL");
2080 op->flags |= E86_DFLAGS_CALL;
2081 return;
2082
2083 case 3:
2084 dop_ea16 (op, src, "CALLF");
2085 op->flags |= E86_DFLAGS_CALL;
2086 return;
2087
2088 case 4:
2089 dop_ea16 (op, src, "JMP");
2090 return;
2091
2092 case 5:
2093 dop_ea16 (op, src, "JMPF");
2094 return;
2095
2096 case 6:
2097 dop_ea16 (op, src, "PUSH");
2098 return;
2099
2100 case 7:
2101 dop_ud (op, src);
2102 return;
2103
2104 default:
2105 dop_ud (op, src);
2106 return;
2107 }
2108}
2109
2110
2111typedef void (*e86_disasm_f) (e86_disasm_t *op, unsigned char *src);
2112
2113static
2114e86_disasm_f dop_list[256] = {
2115 &dop_00, &dop_01, &dop_02, &dop_03, &dop_04, &dop_05, &dop_06, &dop_07,
2116 &dop_08, &dop_09, &dop_0a, &dop_0b, &dop_0c, &dop_0d, &dop_0e, &dop_0f,
2117 &dop_10, &dop_11, &dop_12, &dop_13, &dop_14, &dop_15, &dop_16, &dop_17,
2118 &dop_18, &dop_19, &dop_1a, &dop_1b, &dop_1c, &dop_1d, &dop_1e, &dop_1f,
2119 &dop_20, &dop_21, &dop_22, &dop_23, &dop_24, &dop_25, &dop_26, &dop_27, /* 20 */
2120 &dop_28, &dop_29, &dop_2a, &dop_2b, &dop_2c, &dop_2d, &dop_2e, &dop_2f,
2121 &dop_30, &dop_31, &dop_32, &dop_33, &dop_34, &dop_35, &dop_36, &dop_37, /* 30 */
2122 &dop_38, &dop_39, &dop_3a, &dop_3b, &dop_3c, &dop_3d, &dop_3e, &dop_3f,
2123 &dop_40, &dop_40, &dop_40, &dop_40, &dop_40, &dop_40, &dop_40, &dop_40, /* 40 */
2124 &dop_48, &dop_48, &dop_48, &dop_48, &dop_48, &dop_48, &dop_48, &dop_48,
2125 &dop_50, &dop_50, &dop_50, &dop_50, &dop_50, &dop_50, &dop_50, &dop_50, /* 50 */
2126 &dop_58, &dop_58, &dop_58, &dop_58, &dop_58, &dop_58, &dop_58, &dop_58,
2127 &dop_60, &dop_61, &dop_62, &dop_ud, &dop_ud, &dop_ud, &dop_66, &dop_ud, /* 60 */
2128 &dop_68, &dop_ud, &dop_6a, &dop_ud, &dop_6c, &dop_6d, &dop_6e, &dop_6f,
2129 &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, /* 70 */
2130 &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70, &dop_70,
2131 &dop_80, &dop_81, &dop_80, &dop_83, &dop_84, &dop_85, &dop_86, &dop_87, /* 80 */
2132 &dop_88, &dop_89, &dop_8a, &dop_8b, &dop_8c, &dop_8d, &dop_8e, &dop_8f,
2133 &dop_90, &dop_91, &dop_91, &dop_91, &dop_91, &dop_91, &dop_91, &dop_91, /* 90 */
2134 &dop_98, &dop_99, &dop_9a, &dop_9b, &dop_9c, &dop_9d, &dop_9e, &dop_9f,
2135 &dop_a0, &dop_a1, &dop_a2, &dop_a3, &dop_a4, &dop_a5, &dop_a6, &dop_a7, /* A0 */
2136 &dop_a8, &dop_a9, &dop_aa, &dop_ab, &dop_ac, &dop_ad, &dop_ae, &dop_af,
2137 &dop_b0, &dop_b0, &dop_b0, &dop_b0, &dop_b0, &dop_b0, &dop_b0, &dop_b0, /* B0 */
2138 &dop_b8, &dop_b8, &dop_b8, &dop_b8, &dop_b8, &dop_b8, &dop_b8, &dop_b8,
2139 &dop_c0, &dop_c1, &dop_c2, &dop_c3, &dop_c4, &dop_c5, &dop_c6, &dop_c7, /* C0 */
2140 &dop_c8, &dop_c9, &dop_ca, &dop_cb, &dop_cc, &dop_cd, &dop_ce, &dop_cf,
2141 &dop_d0, &dop_d1, &dop_d2, &dop_d3, &dop_d4, &dop_d5, &dop_ud, &dop_d7, /* D0 */
2142 &dop_ud, &dop_ud, &dop_ud, &dop_ud, &dop_ud, &dop_ud, &dop_ud, &dop_ud,
2143 &dop_e0, &dop_e0, &dop_e0, &dop_e0, &dop_e4, &dop_e5, &dop_e6, &dop_e7, /* E0 */
2144 &dop_e8, &dop_e9, &dop_ea, &dop_eb, &dop_ec, &dop_ed, &dop_ee, &dop_ef,
2145 &dop_f0, &dop_ud, &dop_f2, &dop_f3, &dop_f4, &dop_f5, &dop_f6, &dop_f7, /* F0 */
2146 &dop_f8, &dop_f8, &dop_f8, &dop_f8, &dop_f8, &dop_f8, &dop_fe, &dop_ff
2147};
2148
2149static
2150void e86_disasm_op (e86_disasm_t *op, unsigned char *src)
2151{
2152 dop_list[src[0]] (op, src);
2153}
2154
2155void e86_disasm (e86_disasm_t *op, unsigned char *src, unsigned short ip)
2156{
2157 unsigned i;
2158
2159 op->flags = 0;
2160 op->seg = 0;
2161 op->ip = ip;
2162
2163 e86_disasm_op (op, src);
2164
2165 for (i = 0; i < op->dat_n; i++) {
2166 op->dat[i] = src[i];
2167 }
2168}
2169
2170void e86_disasm_mem (e8086_t *c, e86_disasm_t *op, unsigned short cs, unsigned short ip)
2171{
2172 unsigned i;
2173 unsigned char src[16];
2174
2175 for (i = 0; i < 16; i++) {
2176 src[i] = e86_get_mem8 (c, cs, (ip + i) & 0xffff);
2177 }
2178
2179 e86_disasm (op, src, ip);
2180}
2181
2182void e86_disasm_cur (e8086_t *c, e86_disasm_t *op)
2183{
2184 e86_disasm_mem (c, op, c->sreg[E86_REG_CS], c->ip);
2185}