1 /////////////////////////////////////////////////////////////////////////
2 // $Id: resolve.cc 11863 2013-10-07 19:23:19Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2005-2013 Stanislav Shwartsman
6 // Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23
24 #include <stdio.h>
25 #include <assert.h>
26 #include "disasm.h"
27
decode_modrm(x86_insn * insn)28 void disassembler::decode_modrm(x86_insn *insn)
29 {
30 insn->modrm = fetch_byte();
31 BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
32 // MOVs with CRx and DRx always use register ops and ignore the mod field.
33 if ((insn->b1 & ~3) == 0x120) insn->mod = 3;
34 insn->nnn |= insn->rex_r;
35 insn->rm |= insn->rex_b;
36
37 if (insn->mod == 3) {
38 return; /* mod, reg, reg */
39 }
40
41 if (insn->as_64)
42 {
43 if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
44 // one byte modrm
45 switch (insn->mod) {
46 case 0:
47 resolve_modrm = &disassembler::resolve64_mod0;
48 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
49 insn->displacement.displ32 = fetch_dword();
50 break;
51 case 1:
52 /* reg, 8-bit displacement, sign extend */
53 resolve_modrm = &disassembler::resolve64_mod1or2;
54 insn->displacement.displ32 = (Bit8s) fetch_byte();
55 break;
56 case 2:
57 /* reg, 32-bit displacement */
58 resolve_modrm = &disassembler::resolve64_mod1or2;
59 insn->displacement.displ32 = fetch_dword();
60 break;
61 } /* switch (mod) */
62 } /* if (rm != 4) */
63 else { /* rm == 4, s-i-b byte follows */
64 insn->sib = fetch_byte();
65 BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
66 insn->base |= insn->rex_b;
67 insn->index |= insn->rex_x;
68
69 switch (insn->mod) {
70 case 0:
71 resolve_modrm = &disassembler::resolve64_mod0_rm4;
72 if ((insn->base & 7) == 5)
73 insn->displacement.displ32 = fetch_dword();
74 break;
75 case 1:
76 resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
77 insn->displacement.displ32 = (Bit8s) fetch_byte();
78 break;
79 case 2:
80 resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
81 insn->displacement.displ32 = fetch_dword();
82 break;
83 }
84 } /* s-i-b byte follows */
85 }
86 else
87 {
88 if (insn->as_32)
89 {
90 if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
91 // one byte modrm
92 switch (insn->mod) {
93 case 0:
94 resolve_modrm = &disassembler::resolve32_mod0;
95 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
96 insn->displacement.displ32 = fetch_dword();
97 break;
98 case 1:
99 /* reg, 8-bit displacement, sign extend */
100 resolve_modrm = &disassembler::resolve32_mod1or2;
101 insn->displacement.displ32 = (Bit8s) fetch_byte();
102 break;
103 case 2:
104 /* reg, 32-bit displacement */
105 resolve_modrm = &disassembler::resolve32_mod1or2;
106 insn->displacement.displ32 = fetch_dword();
107 break;
108 } /* switch (mod) */
109 } /* if (rm != 4) */
110 else { /* rm == 4, s-i-b byte follows */
111 insn->sib = fetch_byte();
112 BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
113 insn->base |= insn->rex_b;
114 insn->index |= insn->rex_x;
115
116 switch (insn->mod) {
117 case 0:
118 resolve_modrm = &disassembler::resolve32_mod0_rm4;
119 if ((insn->base & 7) == 5)
120 insn->displacement.displ32 = fetch_dword();
121 break;
122 case 1:
123 resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
124 insn->displacement.displ32 = (Bit8s) fetch_byte();
125 break;
126 case 2:
127 resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
128 insn->displacement.displ32 = fetch_dword();
129 break;
130 }
131 } /* s-i-b byte follows */
132 }
133 else {
134 assert(insn->rex_b == 0);
135 assert(insn->rex_x == 0);
136 assert(insn->rex_r == 0);
137 /* 16 bit addressing modes. */
138 switch (insn->mod) {
139 case 0:
140 resolve_modrm = &disassembler::resolve16_mod0;
141 if(insn->rm == 6)
142 insn->displacement.displ16 = fetch_word();
143 break;
144 case 1:
145 /* reg, 8-bit displacement, sign extend */
146 resolve_modrm = &disassembler::resolve16_mod1or2;
147 insn->displacement.displ16 = (Bit8s) fetch_byte();
148 break;
149 case 2:
150 resolve_modrm = &disassembler::resolve16_mod1or2;
151 insn->displacement.displ16 = fetch_word();
152 break;
153 } /* switch (mod) ... */
154 }
155 }
156 }
157
resolve16_mod0(const x86_insn * insn,unsigned datasize)158 void disassembler::resolve16_mod0(const x86_insn *insn, unsigned datasize)
159 {
160 const char *seg;
161
162 if (insn->is_seg_override())
163 seg = segment_name[insn->seg_override];
164 else
165 seg = sreg_mod00_rm16[insn->rm];
166
167 if(insn->rm == 6)
168 print_memory_access16(datasize, seg, NULL, insn->displacement.displ16);
169 else
170 print_memory_access16(datasize, seg, index16[insn->rm], 0);
171 }
172
resolve16_mod1or2(const x86_insn * insn,unsigned datasize)173 void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned datasize)
174 {
175 const char *seg;
176
177 if (insn->is_seg_override())
178 seg = segment_name[insn->seg_override];
179 else
180 seg = sreg_mod01or10_rm16[insn->rm];
181
182 print_memory_access16(datasize, seg, index16[insn->rm], insn->displacement.displ16);
183 }
184
resolve32_mod0(const x86_insn * insn,unsigned datasize)185 void disassembler::resolve32_mod0(const x86_insn *insn, unsigned datasize)
186 {
187 const char *seg, *eip_regname = NULL;
188
189 if (insn->is_seg_override())
190 seg = segment_name[insn->seg_override];
191 else
192 seg = segment_name[DS_REG];
193
194 if (insn->is_64) {
195 if (intel_mode) eip_regname = "eip";
196 else eip_regname = "%eip";
197 }
198
199 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
200 print_memory_access32(datasize, seg, eip_regname, NULL, 0, insn->displacement.displ32);
201 else
202 print_memory_access32(datasize, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
203 }
204
resolve32_mod1or2(const x86_insn * insn,unsigned datasize)205 void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned datasize)
206 {
207 const char *seg;
208
209 if (insn->is_seg_override())
210 seg = segment_name[insn->seg_override];
211 else
212 seg = sreg_mod01or10_base32[insn->rm];
213
214 print_memory_access32(datasize, seg,
215 general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
216 }
217
resolve32_mod0_rm4(const x86_insn * insn,unsigned datasize)218 void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned datasize)
219 {
220 char vsib_index[8];
221 const char *seg, *base = NULL, *index = NULL;
222 Bit32u disp32 = 0;
223
224 if (insn->is_seg_override())
225 seg = segment_name[insn->seg_override];
226 else
227 seg = sreg_mod00_base32[insn->base];
228
229 if ((insn->base & 7) != 5)
230 base = general_32bit_regname[insn->base];
231 else
232 disp32 = insn->displacement.displ32;
233
234 if (datasize & VSIB_Index) {
235 sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
236 index = vsib_index;
237 }
238 else {
239 if (insn->index != 4)
240 index = general_32bit_regname[insn->index];
241 }
242
243 print_memory_access32(datasize, seg, base, index, insn->scale, disp32);
244 }
245
resolve32_mod1or2_rm4(const x86_insn * insn,unsigned datasize)246 void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned datasize)
247 {
248 char vsib_index[8];
249 const char *seg, *index = NULL;
250
251 if (insn->is_seg_override())
252 seg = segment_name[insn->seg_override];
253 else
254 seg = sreg_mod01or10_base32[insn->base];
255
256 if (datasize & VSIB_Index) {
257 sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
258 index = vsib_index;
259 }
260 else {
261 if (insn->index != 4)
262 index = general_32bit_regname[insn->index];
263 }
264
265 print_memory_access32(datasize, seg,
266 general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
267 }
268
resolve64_mod0(const x86_insn * insn,unsigned datasize)269 void disassembler::resolve64_mod0(const x86_insn *insn, unsigned datasize)
270 {
271 const char *seg, *rip_regname;
272
273 if (insn->is_seg_override())
274 seg = segment_name[insn->seg_override];
275 else
276 seg = segment_name[DS_REG];
277
278 if (intel_mode) rip_regname = "rip";
279 else rip_regname = "%rip";
280
281 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
282 print_memory_access64(datasize, seg, rip_regname, NULL, 0, (Bit32s) insn->displacement.displ32);
283 else
284 print_memory_access64(datasize, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
285 }
286
resolve64_mod1or2(const x86_insn * insn,unsigned datasize)287 void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned datasize)
288 {
289 const char *seg;
290
291 if (insn->is_seg_override())
292 seg = segment_name[insn->seg_override];
293 else
294 seg = sreg_mod01or10_base32[insn->rm];
295
296 print_memory_access64(datasize, seg,
297 general_64bit_regname[insn->rm], NULL, 0, (Bit32s) insn->displacement.displ32);
298 }
299
resolve64_mod0_rm4(const x86_insn * insn,unsigned datasize)300 void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned datasize)
301 {
302 char vsib_index[8];
303 const char *seg, *base = NULL, *index = NULL;
304 Bit32s disp32 = 0;
305
306 if (insn->is_seg_override())
307 seg = segment_name[insn->seg_override];
308 else
309 seg = sreg_mod00_base32[insn->base];
310
311 if ((insn->base & 7) != 5)
312 base = general_64bit_regname[insn->base];
313 else
314 disp32 = (Bit32s) insn->displacement.displ32;
315
316 if (datasize & VSIB_Index) {
317 sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
318 index = vsib_index;
319 }
320 else {
321 if (insn->index != 4)
322 index = general_64bit_regname[insn->index];
323 }
324
325 print_memory_access64(datasize, seg, base, index, insn->scale, disp32);
326 }
327
resolve64_mod1or2_rm4(const x86_insn * insn,unsigned datasize)328 void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned datasize)
329 {
330 char vsib_index[8];
331 const char *seg, *index = NULL;
332
333 if (insn->is_seg_override())
334 seg = segment_name[insn->seg_override];
335 else
336 seg = sreg_mod01or10_base32[insn->base];
337
338 if (datasize & VSIB_Index) {
339 sprintf(vsib_index, "%s%d", vector_reg_name[insn->vex_l], insn->index);
340 index = vsib_index;
341 }
342 else {
343 if (insn->index != 4)
344 index = general_64bit_regname[insn->index];
345 }
346
347 print_memory_access64(datasize, seg,
348 general_64bit_regname[insn->base], index, insn->scale, (Bit32s) insn->displacement.displ32);
349 }
350
print_datasize(unsigned size)351 void disassembler::print_datasize(unsigned size)
352 {
353 if (!intel_mode || !print_mem_datasize) return;
354
355 switch(size & 0xf)
356 {
357 case B_SIZE:
358 dis_sprintf("byte ptr ");
359 break;
360 case W_SIZE:
361 dis_sprintf("word ptr ");
362 break;
363 case D_SIZE:
364 dis_sprintf("dword ptr ");
365 break;
366 case Q_SIZE:
367 dis_sprintf("qword ptr ");
368 break;
369 case T_SIZE:
370 dis_sprintf("tbyte ptr ");
371 break;
372 case XMM_SIZE:
373 dis_sprintf("dqword ptr ");
374 break;
375 case YMM_SIZE:
376 dis_sprintf("qqword ptr ");
377 break;
378 case X_SIZE:
379 break;
380 };
381 }
382
print_memory_access16(int datasize,const char * seg,const char * index,Bit16u disp)383 void disassembler::print_memory_access16(int datasize,
384 const char *seg, const char *index, Bit16u disp)
385 {
386 print_datasize(datasize);
387
388 dis_sprintf("%s:", seg);
389
390 if (intel_mode)
391 {
392 if (index == NULL)
393 {
394 dis_sprintf("0x%04x", (unsigned) disp);
395 }
396 else
397 {
398 if (disp != 0) {
399 if (offset_mode_hex)
400 dis_sprintf("[%s+0x%04x]", index, (unsigned) disp);
401 else
402 dis_sprintf("[%s%+d]", index, (int) (Bit16s) disp);
403 }
404 else
405 dis_sprintf("[%s]", index);
406 }
407 }
408 else
409 {
410 if (index == NULL)
411 {
412 dis_sprintf("0x%04x", (unsigned) disp);
413 }
414 else
415 {
416 if (disp != 0) {
417 if (offset_mode_hex)
418 dis_sprintf("0x%04x(%s,1)", (unsigned) disp, index);
419 else
420 dis_sprintf("%d(%s,1)", (int) (Bit16s) disp, index);
421 }
422 else
423 dis_sprintf("(%s,1)", index);
424 }
425 }
426 }
427
print_memory_access32(int datasize,const char * seg,const char * base,const char * index,int scale,Bit32s disp)428 void disassembler::print_memory_access32(int datasize,
429 const char *seg, const char *base, const char *index, int scale, Bit32s disp)
430 {
431 print_datasize(datasize);
432
433 dis_sprintf("%s:", seg);
434
435 scale = 1 << scale;
436
437 if (intel_mode)
438 {
439 if (base == NULL)
440 {
441 if (index == NULL)
442 {
443 dis_sprintf("0x%08x", (unsigned) disp);
444 }
445 else
446 {
447 if (scale != 1)
448 {
449 if (disp != 0) {
450 if (offset_mode_hex)
451 dis_sprintf("[%s*%d+0x%08x]", index, scale, (unsigned) disp);
452 else
453 dis_sprintf("[%s*%d%+d]", index, scale, (int) disp);
454 }
455 else
456 dis_sprintf("[%s*%d]", index, scale);
457 }
458 else
459 {
460 if (disp != 0) {
461 if (offset_mode_hex)
462 dis_sprintf("[%s+0x%08x]", index, (unsigned) disp);
463 else
464 dis_sprintf("[%s%+d]", index, (int) disp);
465 }
466 else {
467 dis_sprintf("[%s]", index);
468 }
469 }
470 }
471 }
472 else
473 {
474 if (index == NULL)
475 {
476 if (disp != 0) {
477 if (offset_mode_hex)
478 dis_sprintf("[%s+0x%08x]", base, (unsigned) disp);
479 else
480 dis_sprintf("[%s%+d]", base, (int) disp);
481 }
482 else {
483 dis_sprintf("[%s]", base);
484 }
485 }
486 else
487 {
488 if (scale != 1)
489 {
490 if (disp != 0) {
491 if (offset_mode_hex)
492 dis_sprintf("[%s+%s*%d+0x%08x]", base, index, scale, (unsigned) disp);
493 else
494 dis_sprintf("[%s+%s*%d%+d]", base, index, scale, (int) disp);
495 }
496 else {
497 dis_sprintf("[%s+%s*%d]", base, index, scale);
498 }
499 }
500 else
501 {
502 if (disp != 0) {
503 if (offset_mode_hex)
504 dis_sprintf("[%s+%s+0x%08x]", base, index, (unsigned) disp);
505 else
506 dis_sprintf("[%s+%s%+d]", base, index, (int) disp);
507 }
508 else
509 dis_sprintf("[%s+%s]", base, index);
510 }
511 }
512 }
513 }
514 else
515 {
516 if (base == NULL)
517 {
518 if (index == NULL)
519 {
520 dis_sprintf("0x%08x", (unsigned) disp);
521 }
522 else
523 {
524 if (disp != 0) {
525 if (offset_mode_hex)
526 dis_sprintf("0x%08x(,%s,%d)", (unsigned) disp, index, scale);
527 else
528 dis_sprintf("%d(,%s,%d)", (int) disp, index, scale);
529 }
530 else
531 dis_sprintf("(,%s,%d)", index, scale);
532 }
533 }
534 else
535 {
536 if (index == NULL)
537 {
538 if (disp != 0) {
539 if (offset_mode_hex)
540 dis_sprintf("0x%08x(%s)", (unsigned) disp, base);
541 else
542 dis_sprintf("%d(%s)", (int) disp, base);
543 }
544 else
545 dis_sprintf("(%s)", base);
546 }
547 else
548 {
549 if (disp != 0) {
550 if (offset_mode_hex)
551 dis_sprintf("0x%08x(%s,%s,%d)", (unsigned) disp, base, index, scale);
552 else
553 dis_sprintf("%d(%s,%s,%d)", (int) disp, base, index, scale);
554 }
555 else
556 dis_sprintf("(%s,%s,%d)", base, index, scale);
557 }
558 }
559 }
560 }
561
print_memory_access64(int datasize,const char * seg,const char * base,const char * index,int scale,Bit32s disp)562 void disassembler::print_memory_access64(int datasize,
563 const char *seg, const char *base, const char *index, int scale, Bit32s disp)
564 {
565 Bit64u disp64 = (Bit64s) disp;
566
567 print_datasize(datasize);
568
569 dis_sprintf("%s:", seg);
570
571 scale = 1 << scale;
572
573 if (intel_mode)
574 {
575 if (base == NULL)
576 {
577 if (index == NULL)
578 {
579 dis_sprintf("0x%08x%08x", GET32H(disp64), GET32L(disp64));
580 }
581 else
582 {
583 if (scale != 1)
584 {
585 if (disp != 0) {
586 if (offset_mode_hex)
587 dis_sprintf("[%s*%d+0x%08x%08x]", index, scale, GET32H(disp64), GET32L(disp64));
588 else
589 dis_sprintf("[%s*%d%+d]", index, scale, (int) disp);
590 }
591 else
592 dis_sprintf("[%s*%d]", index, scale);
593 }
594 else
595 {
596 if (disp != 0) {
597 if (offset_mode_hex)
598 dis_sprintf("[%s+0x%08x%08x]", index, GET32H(disp64), GET32L(disp64));
599 else
600 dis_sprintf("[%s%+d]", index, (int) disp);
601 }
602 else {
603 dis_sprintf("[%s]", index);
604 }
605 }
606 }
607 }
608 else
609 {
610 if (index == NULL)
611 {
612 if (disp != 0) {
613 if (offset_mode_hex)
614 dis_sprintf("[%s+0x%08x%08x]", base, GET32H(disp64), GET32L(disp64));
615 else
616 dis_sprintf("[%s%+d]", base, (int) disp);
617 }
618 else {
619 dis_sprintf("[%s]", base);
620 }
621 }
622 else
623 {
624 if (scale != 1)
625 {
626 if (disp != 0) {
627 if (offset_mode_hex)
628 dis_sprintf("[%s+%s*%d+0x%08x%08x]", base, index, scale, GET32H(disp64), GET32L(disp64));
629 else
630 dis_sprintf("[%s+%s*%d%+d]", base, index, scale, (int) disp);
631 }
632 else {
633 dis_sprintf("[%s+%s*%d]", base, index, scale);
634 }
635 }
636 else
637 {
638 if (disp != 0) {
639 if (offset_mode_hex)
640 dis_sprintf("[%s+%s+0x%08x%08x]", base, index, GET32H(disp64), GET32L(disp64));
641 else
642 dis_sprintf("[%s+%s%+d]", base, index, (int) disp);
643 }
644 else
645 dis_sprintf("[%s+%s]", base, index);
646 }
647 }
648 }
649 }
650 else
651 {
652 if (base == NULL)
653 {
654 if (index == NULL)
655 {
656 dis_sprintf("0x%08x%08x", GET32H(disp64), GET32L(disp64));
657 }
658 else
659 {
660 if (disp != 0) {
661 if (offset_mode_hex)
662 dis_sprintf("0x%08x%08x(,%s,%d)", GET32H(disp64), GET32L(disp64), index, scale);
663 else
664 dis_sprintf("%d(,%s,%d)", (int) disp, index, scale);
665 }
666 else
667 dis_sprintf("(,%s,%d)", index, scale);
668 }
669 }
670 else
671 {
672 if (index == NULL)
673 {
674 if (disp != 0) {
675 if (offset_mode_hex)
676 dis_sprintf("0x%08x%08x(%s)", GET32H(disp64), GET32L(disp64), base);
677 else
678 dis_sprintf("%d(%s)", (int) disp, base);
679 }
680 else
681 dis_sprintf("(%s)", base);
682 }
683 else
684 {
685 if (disp != 0) {
686 if (offset_mode_hex)
687 dis_sprintf("0x%08x%08x(%s,%s,%d)", GET32H(disp64), GET32L(disp64), base, index, scale);
688 else
689 dis_sprintf("%d(%s,%s,%d)", (int) disp, base, index, scale);
690 }
691 else
692 dis_sprintf("(%s,%s,%d)", base, index, scale);
693 }
694 }
695 }
696 }
697