Apply Nindent to all .c and .h files
[platform/upstream/nasm.git] / disasm.c
1 /* disasm.c   where all the _work_ gets done in the Netwide Disassembler
2  *
3  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4  * Julian Hall. All rights reserved. The software is
5  * redistributable under the licence given in the file "Licence"
6  * distributed in the NASM archive.
7  *
8  * initial version 27/iii/95 by Simon Tatham
9  */
10
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "nasm.h"
15 #include "disasm.h"
16 #include "sync.h"
17 #include "insns.h"
18
19 #include "names.c"
20
21 extern struct itemplate **itable[];
22
23 /*
24  * Flags that go into the `segment' field of `insn' structures
25  * during disassembly.
26  */
27 #define SEG_RELATIVE 1
28 #define SEG_32BIT 2
29 #define SEG_RMREG 4
30 #define SEG_DISP8 8
31 #define SEG_DISP16 16
32 #define SEG_DISP32 32
33 #define SEG_NODISP 64
34 #define SEG_SIGNED 128
35
36 static int whichreg(long regflags, int regval)
37 {
38 #include "regdis.c"
39
40     if (!(REG_AL & ~regflags))
41         return R_AL;
42     if (!(REG_AX & ~regflags))
43         return R_AX;
44     if (!(REG_EAX & ~regflags))
45         return R_EAX;
46     if (!(REG_DL & ~regflags))
47         return R_DL;
48     if (!(REG_DX & ~regflags))
49         return R_DX;
50     if (!(REG_EDX & ~regflags))
51         return R_EDX;
52     if (!(REG_CL & ~regflags))
53         return R_CL;
54     if (!(REG_CX & ~regflags))
55         return R_CX;
56     if (!(REG_ECX & ~regflags))
57         return R_ECX;
58     if (!(FPU0 & ~regflags))
59         return R_ST0;
60     if (!(REG_CS & ~regflags))
61         return (regval == 1) ? R_CS : 0;
62     if (!(REG_DESS & ~regflags))
63         return (regval == 0 || regval == 2
64                 || regval == 3 ? sreg[regval] : 0);
65     if (!(REG_FSGS & ~regflags))
66         return (regval == 4 || regval == 5 ? sreg[regval] : 0);
67     if (!(REG_SEG67 & ~regflags))
68         return (regval == 6 || regval == 7 ? sreg[regval] : 0);
69
70     /* All the entries below look up regval in an 8-entry array */
71     if (regval < 0 || regval > 7)
72         return 0;
73
74     if (!((REGMEM | BITS8) & ~regflags))
75         return reg8[regval];
76     if (!((REGMEM | BITS16) & ~regflags))
77         return reg16[regval];
78     if (!((REGMEM | BITS32) & ~regflags))
79         return reg32[regval];
80     if (!(REG_SREG & ~regflags))
81         return sreg[regval];
82     if (!(REG_CREG & ~regflags))
83         return creg[regval];
84     if (!(REG_DREG & ~regflags))
85         return dreg[regval];
86     if (!(REG_TREG & ~regflags))
87         return treg[regval];
88     if (!(FPUREG & ~regflags))
89         return fpureg[regval];
90     if (!(MMXREG & ~regflags))
91         return mmxreg[regval];
92     if (!(XMMREG & ~regflags))
93         return xmmreg[regval];
94
95     return 0;
96 }
97
98 static const char *whichcond(int condval)
99 {
100     static int conds[] = {
101         C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A,
102         C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G
103     };
104     return conditions[conds[condval]];
105 }
106
107 /*
108  * Process an effective address (ModRM) specification.
109  */
110 static unsigned char *do_ea(unsigned char *data, int modrm, int asize,
111                             int segsize, operand * op)
112 {
113     int mod, rm, scale, index, base;
114
115     mod = (modrm >> 6) & 03;
116     rm = modrm & 07;
117
118     if (mod == 3) {             /* pure register version */
119         op->basereg = rm;
120         op->segment |= SEG_RMREG;
121         return data;
122     }
123
124     op->addr_size = 0;
125
126     if (asize == 16) {
127         /*
128          * <mod> specifies the displacement size (none, byte or
129          * word), and <rm> specifies the register combination.
130          * Exception: mod=0,rm=6 does not specify [BP] as one might
131          * expect, but instead specifies [disp16].
132          */
133         op->indexreg = op->basereg = -1;
134         op->scale = 1;          /* always, in 16 bits */
135         switch (rm) {
136         case 0:
137             op->basereg = R_BX;
138             op->indexreg = R_SI;
139             break;
140         case 1:
141             op->basereg = R_BX;
142             op->indexreg = R_DI;
143             break;
144         case 2:
145             op->basereg = R_BP;
146             op->indexreg = R_SI;
147             break;
148         case 3:
149             op->basereg = R_BP;
150             op->indexreg = R_DI;
151             break;
152         case 4:
153             op->basereg = R_SI;
154             break;
155         case 5:
156             op->basereg = R_DI;
157             break;
158         case 6:
159             op->basereg = R_BP;
160             break;
161         case 7:
162             op->basereg = R_BX;
163             break;
164         }
165         if (rm == 6 && mod == 0) {      /* special case */
166             op->basereg = -1;
167             if (segsize != 16)
168                 op->addr_size = 16;
169             mod = 2;            /* fake disp16 */
170         }
171         switch (mod) {
172         case 0:
173             op->segment |= SEG_NODISP;
174             break;
175         case 1:
176             op->segment |= SEG_DISP8;
177             op->offset = (signed char)*data++;
178             break;
179         case 2:
180             op->segment |= SEG_DISP16;
181             op->offset = *data++;
182             op->offset |= ((unsigned)*data++) << 8;
183             break;
184         }
185         return data;
186     } else {
187         /*
188          * Once again, <mod> specifies displacement size (this time
189          * none, byte or *dword*), while <rm> specifies the base
190          * register. Again, [EBP] is missing, replaced by a pure
191          * disp32 (this time that's mod=0,rm=*5*). However, rm=4
192          * indicates not a single base register, but instead the
193          * presence of a SIB byte...
194          */
195         op->indexreg = -1;
196         switch (rm) {
197         case 0:
198             op->basereg = R_EAX;
199             break;
200         case 1:
201             op->basereg = R_ECX;
202             break;
203         case 2:
204             op->basereg = R_EDX;
205             break;
206         case 3:
207             op->basereg = R_EBX;
208             break;
209         case 5:
210             op->basereg = R_EBP;
211             break;
212         case 6:
213             op->basereg = R_ESI;
214             break;
215         case 7:
216             op->basereg = R_EDI;
217             break;
218         }
219         if (rm == 5 && mod == 0) {
220             op->basereg = -1;
221             if (segsize != 32)
222                 op->addr_size = 32;
223             mod = 2;            /* fake disp32 */
224         }
225         if (rm == 4) {          /* process SIB */
226             scale = (*data >> 6) & 03;
227             index = (*data >> 3) & 07;
228             base = *data & 07;
229             data++;
230
231             op->scale = 1 << scale;
232             switch (index) {
233             case 0:
234                 op->indexreg = R_EAX;
235                 break;
236             case 1:
237                 op->indexreg = R_ECX;
238                 break;
239             case 2:
240                 op->indexreg = R_EDX;
241                 break;
242             case 3:
243                 op->indexreg = R_EBX;
244                 break;
245             case 4:
246                 op->indexreg = -1;
247                 break;
248             case 5:
249                 op->indexreg = R_EBP;
250                 break;
251             case 6:
252                 op->indexreg = R_ESI;
253                 break;
254             case 7:
255                 op->indexreg = R_EDI;
256                 break;
257             }
258
259             switch (base) {
260             case 0:
261                 op->basereg = R_EAX;
262                 break;
263             case 1:
264                 op->basereg = R_ECX;
265                 break;
266             case 2:
267                 op->basereg = R_EDX;
268                 break;
269             case 3:
270                 op->basereg = R_EBX;
271                 break;
272             case 4:
273                 op->basereg = R_ESP;
274                 break;
275             case 6:
276                 op->basereg = R_ESI;
277                 break;
278             case 7:
279                 op->basereg = R_EDI;
280                 break;
281             case 5:
282                 if (mod == 0) {
283                     mod = 2;
284                     op->basereg = -1;
285                 } else
286                     op->basereg = R_EBP;
287                 break;
288             }
289         }
290         switch (mod) {
291         case 0:
292             op->segment |= SEG_NODISP;
293             break;
294         case 1:
295             op->segment |= SEG_DISP8;
296             op->offset = (signed char)*data++;
297             break;
298         case 2:
299             op->segment |= SEG_DISP32;
300             op->offset = *data++;
301             op->offset |= ((unsigned)*data++) << 8;
302             op->offset |= ((long)*data++) << 16;
303             op->offset |= ((long)*data++) << 24;
304             break;
305         }
306         return data;
307     }
308 }
309
310 /*
311  * Determine whether the instruction template in t corresponds to the data
312  * stream in data. Return the number of bytes matched if so.
313  */
314 static int matches(struct itemplate *t, unsigned char *data, int asize,
315                    int osize, int segsize, int rep, insn * ins)
316 {
317     unsigned char *r = (unsigned char *)(t->code);
318     unsigned char *origdata = data;
319     int a_used = FALSE, o_used = FALSE;
320     int drep = 0;
321
322     if (rep == 0xF2)
323         drep = P_REPNE;
324     else if (rep == 0xF3)
325         drep = P_REP;
326
327     while (*r) {
328         int c = *r++;
329         if (c >= 01 && c <= 03) {
330             while (c--)
331                 if (*r++ != *data++)
332                     return FALSE;
333         }
334         if (c == 04) {
335             switch (*data++) {
336             case 0x07:
337                 ins->oprs[0].basereg = 0;
338                 break;
339             case 0x17:
340                 ins->oprs[0].basereg = 2;
341                 break;
342             case 0x1F:
343                 ins->oprs[0].basereg = 3;
344                 break;
345             default:
346                 return FALSE;
347             }
348         }
349         if (c == 05) {
350             switch (*data++) {
351             case 0xA1:
352                 ins->oprs[0].basereg = 4;
353                 break;
354             case 0xA9:
355                 ins->oprs[0].basereg = 5;
356                 break;
357             default:
358                 return FALSE;
359             }
360         }
361         if (c == 06) {
362             switch (*data++) {
363             case 0x06:
364                 ins->oprs[0].basereg = 0;
365                 break;
366             case 0x0E:
367                 ins->oprs[0].basereg = 1;
368                 break;
369             case 0x16:
370                 ins->oprs[0].basereg = 2;
371                 break;
372             case 0x1E:
373                 ins->oprs[0].basereg = 3;
374                 break;
375             default:
376                 return FALSE;
377             }
378         }
379         if (c == 07) {
380             switch (*data++) {
381             case 0xA0:
382                 ins->oprs[0].basereg = 4;
383                 break;
384             case 0xA8:
385                 ins->oprs[0].basereg = 5;
386                 break;
387             default:
388                 return FALSE;
389             }
390         }
391         if (c >= 010 && c <= 012) {
392             int t = *r++, d = *data++;
393             if (d < t || d > t + 7)
394                 return FALSE;
395             else {
396                 ins->oprs[c - 010].basereg = d - t;
397                 ins->oprs[c - 010].segment |= SEG_RMREG;
398             }
399         }
400         if (c == 017)
401             if (*data++)
402                 return FALSE;
403         if (c >= 014 && c <= 016) {
404             ins->oprs[c - 014].offset = (signed char)*data++;
405             ins->oprs[c - 014].segment |= SEG_SIGNED;
406         }
407         if (c >= 020 && c <= 022)
408             ins->oprs[c - 020].offset = *data++;
409         if (c >= 024 && c <= 026)
410             ins->oprs[c - 024].offset = *data++;
411         if (c >= 030 && c <= 032) {
412             ins->oprs[c - 030].offset = *data++;
413             ins->oprs[c - 030].offset |= (((unsigned)*data++) << 8);
414         }
415         if (c >= 034 && c <= 036) {
416             ins->oprs[c - 034].offset = *data++;
417             ins->oprs[c - 034].offset |= (((unsigned)*data++) << 8);
418             if (osize == 32) {
419                 ins->oprs[c - 034].offset |= (((long)*data++) << 16);
420                 ins->oprs[c - 034].offset |= (((long)*data++) << 24);
421             }
422             if (segsize != asize)
423                 ins->oprs[c - 034].addr_size = asize;
424         }
425         if (c >= 040 && c <= 042) {
426             ins->oprs[c - 040].offset = *data++;
427             ins->oprs[c - 040].offset |= (((unsigned)*data++) << 8);
428             ins->oprs[c - 040].offset |= (((long)*data++) << 16);
429             ins->oprs[c - 040].offset |= (((long)*data++) << 24);
430         }
431         if (c >= 044 && c <= 046) {
432             ins->oprs[c - 044].offset = *data++;
433             ins->oprs[c - 044].offset |= (((unsigned)*data++) << 8);
434             if (asize == 32) {
435                 ins->oprs[c - 044].offset |= (((long)*data++) << 16);
436                 ins->oprs[c - 044].offset |= (((long)*data++) << 24);
437             }
438             if (segsize != asize)
439                 ins->oprs[c - 044].addr_size = asize;
440         }
441         if (c >= 050 && c <= 052) {
442             ins->oprs[c - 050].offset = (signed char)*data++;
443             ins->oprs[c - 050].segment |= SEG_RELATIVE;
444         }
445         if (c >= 060 && c <= 062) {
446             ins->oprs[c - 060].offset = *data++;
447             ins->oprs[c - 060].offset |= (((unsigned)*data++) << 8);
448             ins->oprs[c - 060].segment |= SEG_RELATIVE;
449             ins->oprs[c - 060].segment &= ~SEG_32BIT;
450         }
451         if (c >= 064 && c <= 066) {
452             ins->oprs[c - 064].offset = *data++;
453             ins->oprs[c - 064].offset |= (((unsigned)*data++) << 8);
454             if (osize == 32) {
455                 ins->oprs[c - 064].offset |= (((long)*data++) << 16);
456                 ins->oprs[c - 064].offset |= (((long)*data++) << 24);
457                 ins->oprs[c - 064].segment |= SEG_32BIT;
458             } else
459                 ins->oprs[c - 064].segment &= ~SEG_32BIT;
460             ins->oprs[c - 064].segment |= SEG_RELATIVE;
461             if (segsize != osize) {
462                 ins->oprs[c - 064].type =
463                     (ins->oprs[c - 064].type & NON_SIZE)
464                     | ((osize == 16) ? BITS16 : BITS32);
465             }
466         }
467         if (c >= 070 && c <= 072) {
468             ins->oprs[c - 070].offset = *data++;
469             ins->oprs[c - 070].offset |= (((unsigned)*data++) << 8);
470             ins->oprs[c - 070].offset |= (((long)*data++) << 16);
471             ins->oprs[c - 070].offset |= (((long)*data++) << 24);
472             ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
473         }
474         if (c >= 0100 && c < 0130) {
475             int modrm = *data++;
476             ins->oprs[c & 07].basereg = (modrm >> 3) & 07;
477             ins->oprs[c & 07].segment |= SEG_RMREG;
478             data = do_ea(data, modrm, asize, segsize,
479                          &ins->oprs[(c >> 3) & 07]);
480         }
481         if (c >= 0130 && c <= 0132) {
482             ins->oprs[c - 0130].offset = *data++;
483             ins->oprs[c - 0130].offset |= (((unsigned)*data++) << 8);
484         }
485         if (c >= 0140 && c <= 0142) {
486             ins->oprs[c - 0140].offset = *data++;
487             ins->oprs[c - 0140].offset |= (((unsigned)*data++) << 8);
488             ins->oprs[c - 0140].offset |= (((long)*data++) << 16);
489             ins->oprs[c - 0140].offset |= (((long)*data++) << 24);
490         }
491         if (c >= 0200 && c <= 0277) {
492             int modrm = *data++;
493             if (((modrm >> 3) & 07) != (c & 07))
494                 return FALSE;   /* spare field doesn't match up */
495             data = do_ea(data, modrm, asize, segsize,
496                          &ins->oprs[(c >> 3) & 07]);
497         }
498         if (c >= 0300 && c <= 0302) {
499             if (asize)
500                 ins->oprs[c - 0300].segment |= SEG_32BIT;
501             else
502                 ins->oprs[c - 0300].segment &= ~SEG_32BIT;
503             a_used = TRUE;
504         }
505         if (c == 0310) {
506             if (asize == 32)
507                 return FALSE;
508             else
509                 a_used = TRUE;
510         }
511         if (c == 0311) {
512             if (asize == 16)
513                 return FALSE;
514             else
515                 a_used = TRUE;
516         }
517         if (c == 0312) {
518             if (asize != segsize)
519                 return FALSE;
520             else
521                 a_used = TRUE;
522         }
523         if (c == 0320) {
524             if (osize == 32)
525                 return FALSE;
526             else
527                 o_used = TRUE;
528         }
529         if (c == 0321) {
530             if (osize == 16)
531                 return FALSE;
532             else
533                 o_used = TRUE;
534         }
535         if (c == 0322) {
536             if (osize != segsize)
537                 return FALSE;
538             else
539                 o_used = TRUE;
540         }
541         if (c == 0330) {
542             int t = *r++, d = *data++;
543             if (d < t || d > t + 15)
544                 return FALSE;
545             else
546                 ins->condition = d - t;
547         }
548         if (c == 0331) {
549             if (rep)
550                 return FALSE;
551         }
552         if (c == 0332) {
553             if (drep == P_REP)
554                 drep = P_REPE;
555         }
556         if (c == 0333) {
557             if (rep != 0xF3)
558                 return FALSE;
559             drep = 0;
560         }
561     }
562
563     /*
564      * Check for unused rep or a/o prefixes.
565      */
566     ins->nprefix = 0;
567     if (drep)
568         ins->prefixes[ins->nprefix++] = drep;
569     if (!a_used && asize != segsize)
570         ins->prefixes[ins->nprefix++] = (asize == 16 ? P_A16 : P_A32);
571     if (!o_used && osize != segsize)
572         ins->prefixes[ins->nprefix++] = (osize == 16 ? P_O16 : P_O32);
573
574     return data - origdata;
575 }
576
577 long disasm(unsigned char *data, char *output, int outbufsize, int segsize,
578             long offset, int autosync, unsigned long prefer)
579 {
580     struct itemplate **p, **best_p;
581     int length, best_length = 0;
582     char *segover;
583     int rep, lock, asize, osize, i, slen, colon;
584     unsigned char *origdata;
585     int works;
586     insn tmp_ins, ins;
587     unsigned long goodness, best;
588
589     /*
590      * Scan for prefixes.
591      */
592     asize = osize = segsize;
593     segover = NULL;
594     rep = lock = 0;
595     origdata = data;
596     for (;;) {
597         if (*data == 0xF3 || *data == 0xF2)
598             rep = *data++;
599         else if (*data == 0xF0)
600             lock = *data++;
601         else if (*data == 0x2E || *data == 0x36 || *data == 0x3E ||
602                  *data == 0x26 || *data == 0x64 || *data == 0x65) {
603             switch (*data++) {
604             case 0x2E:
605                 segover = "cs";
606                 break;
607             case 0x36:
608                 segover = "ss";
609                 break;
610             case 0x3E:
611                 segover = "ds";
612                 break;
613             case 0x26:
614                 segover = "es";
615                 break;
616             case 0x64:
617                 segover = "fs";
618                 break;
619             case 0x65:
620                 segover = "gs";
621                 break;
622             }
623         } else if (*data == 0x66)
624             osize = 48 - segsize, data++;
625         else if (*data == 0x67)
626             asize = 48 - segsize, data++;
627         else
628             break;
629     }
630
631     tmp_ins.oprs[0].segment = tmp_ins.oprs[1].segment =
632         tmp_ins.oprs[2].segment =
633         tmp_ins.oprs[0].addr_size = tmp_ins.oprs[1].addr_size =
634         tmp_ins.oprs[2].addr_size = (segsize == 16 ? 0 : SEG_32BIT);
635     tmp_ins.condition = -1;
636     best = ~0UL;                /* Worst possible */
637     best_p = NULL;
638     for (p = itable[*data]; *p; p++) {
639         if ((length = matches(*p, data, asize, osize,
640                               segsize, rep, &tmp_ins))) {
641             works = TRUE;
642             /*
643              * Final check to make sure the types of r/m match up.
644              */
645             for (i = 0; i < (*p)->operands; i++) {
646                 if (
647                        /* If it's a mem-only EA but we have a register, die. */
648                        ((tmp_ins.oprs[i].segment & SEG_RMREG) &&
649                         !(MEMORY & ~(*p)->opd[i])) ||
650                        /* If it's a reg-only EA but we have a memory ref, die. */
651                        (!(tmp_ins.oprs[i].segment & SEG_RMREG) &&
652                         !(REGNORM & ~(*p)->opd[i]) &&
653                         !((*p)->opd[i] & REG_SMASK)) ||
654                        /* Register type mismatch (eg FS vs REG_DESS): die. */
655                        ((((*p)->opd[i] & (REGISTER | FPUREG)) ||
656                          (tmp_ins.oprs[i].segment & SEG_RMREG)) &&
657                         !whichreg((*p)->opd[i],
658                                   tmp_ins.oprs[i].basereg))) {
659                     works = FALSE;
660                     break;
661                 }
662             }
663
664             if (works) {
665                 goodness = ((*p)->flags & IF_PFMASK) ^ prefer;
666                 if (goodness < best) {
667                     /* This is the best one found so far */
668                     best = goodness;
669                     best_p = p;
670                     best_length = length;
671                     ins = tmp_ins;
672                 }
673             }
674         }
675     }
676
677     if (!best_p)
678         return 0;               /* no instruction was matched */
679
680     /* Pick the best match */
681     p = best_p;
682     length = best_length;
683
684     slen = 0;
685
686     /* TODO: snprintf returns the value that the string would have if
687      *      the buffer were long enough, and not the actual length of 
688      *      the returned string, so each instance of using the return
689      *      value of snprintf should actually be checked to assure that
690      *      the return value is "sane."  Maybe a macro wrapper could
691      *      be used for that purpose.
692      */
693     if (lock)
694         slen += snprintf(output + slen, outbufsize - slen, "lock ");
695     for (i = 0; i < ins.nprefix; i++)
696         switch (ins.prefixes[i]) {
697         case P_REP:
698             slen += snprintf(output + slen, outbufsize - slen, "rep ");
699             break;
700         case P_REPE:
701             slen += snprintf(output + slen, outbufsize - slen, "repe ");
702             break;
703         case P_REPNE:
704             slen += snprintf(output + slen, outbufsize - slen, "repne ");
705             break;
706         case P_A16:
707             slen += snprintf(output + slen, outbufsize - slen, "a16 ");
708             break;
709         case P_A32:
710             slen += snprintf(output + slen, outbufsize - slen, "a32 ");
711             break;
712         case P_O16:
713             slen += snprintf(output + slen, outbufsize - slen, "o16 ");
714             break;
715         case P_O32:
716             slen += snprintf(output + slen, outbufsize - slen, "o32 ");
717             break;
718         }
719
720     for (i = 0; i < elements(ico); i++)
721         if ((*p)->opcode == ico[i]) {
722             slen +=
723                 snprintf(output + slen, outbufsize - slen, "%s%s", icn[i],
724                          whichcond(ins.condition));
725             break;
726         }
727     if (i >= elements(ico))
728         slen +=
729             snprintf(output + slen, outbufsize - slen, "%s",
730                      insn_names[(*p)->opcode]);
731     colon = FALSE;
732     length += data - origdata;  /* fix up for prefixes */
733     for (i = 0; i < (*p)->operands; i++) {
734         output[slen++] = (colon ? ':' : i == 0 ? ' ' : ',');
735
736         if (ins.oprs[i].segment & SEG_RELATIVE) {
737             ins.oprs[i].offset += offset + length;
738             /*
739              * sort out wraparound
740              */
741             if (!(ins.oprs[i].segment & SEG_32BIT))
742                 ins.oprs[i].offset &= 0xFFFF;
743             /*
744              * add sync marker, if autosync is on
745              */
746             if (autosync)
747                 add_sync(ins.oprs[i].offset, 0L);
748         }
749
750         if ((*p)->opd[i] & COLON)
751             colon = TRUE;
752         else
753             colon = FALSE;
754
755         if (((*p)->opd[i] & (REGISTER | FPUREG)) ||
756             (ins.oprs[i].segment & SEG_RMREG)) {
757             ins.oprs[i].basereg = whichreg((*p)->opd[i],
758                                            ins.oprs[i].basereg);
759             if ((*p)->opd[i] & TO)
760                 slen += snprintf(output + slen, outbufsize - slen, "to ");
761             slen += snprintf(output + slen, outbufsize - slen, "%s",
762                              reg_names[ins.oprs[i].basereg -
763                                        EXPR_REG_START]);
764         } else if (!(UNITY & ~(*p)->opd[i])) {
765             output[slen++] = '1';
766         } else if ((*p)->opd[i] & IMMEDIATE) {
767             if ((*p)->opd[i] & BITS8) {
768                 slen +=
769                     snprintf(output + slen, outbufsize - slen, "byte ");
770                 if (ins.oprs[i].segment & SEG_SIGNED) {
771                     if (ins.oprs[i].offset < 0) {
772                         ins.oprs[i].offset *= -1;
773                         output[slen++] = '-';
774                     } else
775                         output[slen++] = '+';
776                 }
777             } else if ((*p)->opd[i] & BITS16) {
778                 slen +=
779                     snprintf(output + slen, outbufsize - slen, "word ");
780             } else if ((*p)->opd[i] & BITS32) {
781                 slen +=
782                     snprintf(output + slen, outbufsize - slen, "dword ");
783             } else if ((*p)->opd[i] & NEAR) {
784                 slen +=
785                     snprintf(output + slen, outbufsize - slen, "near ");
786             } else if ((*p)->opd[i] & SHORT) {
787                 slen +=
788                     snprintf(output + slen, outbufsize - slen, "short ");
789             }
790             slen +=
791                 snprintf(output + slen, outbufsize - slen, "0x%lx",
792                          ins.oprs[i].offset);
793         } else if (!(MEM_OFFS & ~(*p)->opd[i])) {
794             slen +=
795                 snprintf(output + slen, outbufsize - slen, "[%s%s%s0x%lx]",
796                          (segover ? segover : ""), (segover ? ":" : ""),
797                          (ins.oprs[i].addr_size ==
798                           32 ? "dword " : ins.oprs[i].addr_size ==
799                           16 ? "word " : ""), ins.oprs[i].offset);
800             segover = NULL;
801         } else if (!(REGMEM & ~(*p)->opd[i])) {
802             int started = FALSE;
803             if ((*p)->opd[i] & BITS8)
804                 slen +=
805                     snprintf(output + slen, outbufsize - slen, "byte ");
806             if ((*p)->opd[i] & BITS16)
807                 slen +=
808                     snprintf(output + slen, outbufsize - slen, "word ");
809             if ((*p)->opd[i] & BITS32)
810                 slen +=
811                     snprintf(output + slen, outbufsize - slen, "dword ");
812             if ((*p)->opd[i] & BITS64)
813                 slen +=
814                     snprintf(output + slen, outbufsize - slen, "qword ");
815             if ((*p)->opd[i] & BITS80)
816                 slen +=
817                     snprintf(output + slen, outbufsize - slen, "tword ");
818             if ((*p)->opd[i] & FAR)
819                 slen += snprintf(output + slen, outbufsize - slen, "far ");
820             if ((*p)->opd[i] & NEAR)
821                 slen +=
822                     snprintf(output + slen, outbufsize - slen, "near ");
823             output[slen++] = '[';
824             if (ins.oprs[i].addr_size)
825                 slen += snprintf(output + slen, outbufsize - slen, "%s",
826                                  (ins.oprs[i].addr_size == 32 ? "dword " :
827                                   ins.oprs[i].addr_size ==
828                                   16 ? "word " : ""));
829             if (segover) {
830                 slen +=
831                     snprintf(output + slen, outbufsize - slen, "%s:",
832                              segover);
833                 segover = NULL;
834             }
835             if (ins.oprs[i].basereg != -1) {
836                 slen += snprintf(output + slen, outbufsize - slen, "%s",
837                                  reg_names[(ins.oprs[i].basereg -
838                                             EXPR_REG_START)]);
839                 started = TRUE;
840             }
841             if (ins.oprs[i].indexreg != -1) {
842                 if (started)
843                     output[slen++] = '+';
844                 slen += snprintf(output + slen, outbufsize - slen, "%s",
845                                  reg_names[(ins.oprs[i].indexreg -
846                                             EXPR_REG_START)]);
847                 if (ins.oprs[i].scale > 1)
848                     slen +=
849                         snprintf(output + slen, outbufsize - slen, "*%d",
850                                  ins.oprs[i].scale);
851                 started = TRUE;
852             }
853             if (ins.oprs[i].segment & SEG_DISP8) {
854                 int sign = '+';
855                 if (ins.oprs[i].offset & 0x80) {
856                     ins.oprs[i].offset = -(signed char)ins.oprs[i].offset;
857                     sign = '-';
858                 }
859                 slen +=
860                     snprintf(output + slen, outbufsize - slen, "%c0x%lx",
861                              sign, ins.oprs[i].offset);
862             } else if (ins.oprs[i].segment & SEG_DISP16) {
863                 if (started)
864                     output[slen++] = '+';
865                 slen +=
866                     snprintf(output + slen, outbufsize - slen, "0x%lx",
867                              ins.oprs[i].offset);
868             } else if (ins.oprs[i].segment & SEG_DISP32) {
869                 if (started)
870                     output[slen++] = '+';
871                 slen +=
872                     snprintf(output + slen, outbufsize - slen, "0x%lx",
873                              ins.oprs[i].offset);
874             }
875             output[slen++] = ']';
876         } else {
877             slen +=
878                 snprintf(output + slen, outbufsize - slen, "<operand%d>",
879                          i);
880         }
881     }
882     output[slen] = '\0';
883     if (segover) {              /* unused segment override */
884         char *p = output;
885         int count = slen + 1;
886         while (count--)
887             p[count + 3] = p[count];
888         strncpy(output, segover, 2);
889         output[2] = ' ';
890     }
891     return length;
892 }
893
894 long eatbyte(unsigned char *data, char *output, int outbufsize)
895 {
896     snprintf(output, outbufsize, "db 0x%02X", *data);
897     return 1;
898 }