1G pages support for CPU
[bochs-mirror.git] / disasm / resolve.cc
blob16c737b5ac295c3c7b0956e3b9b76e8950469f0e
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: resolve.cc,v 1.18 2008/04/11 17:54:21 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 #include <stdio.h>
6 #include <assert.h>
7 #include "disasm.h"
9 void disassembler::decode_modrm(x86_insn *insn)
11 insn->modrm = fetch_byte();
12 BX_DECODE_MODRM(insn->modrm, insn->mod, insn->nnn, insn->rm);
13 // MOVs with CRx and DRx always use register ops and ignore the mod field.
14 if ((insn->b1 & ~3) == 0x120) insn->mod = 3;
15 insn->nnn |= insn->rex_r;
16 insn->rm |= insn->rex_b;
18 if (insn->mod == 3) {
19 return; /* mod, reg, reg */
22 if (insn->as_64)
24 if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
25 // one byte modrm
26 switch (insn->mod) {
27 case 0:
28 resolve_modrm = &disassembler::resolve64_mod0;
29 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
30 insn->displacement.displ32 = fetch_dword();
31 break;
32 case 1:
33 /* reg, 8-bit displacement, sign extend */
34 resolve_modrm = &disassembler::resolve64_mod1or2;
35 insn->displacement.displ32 = (Bit8s) fetch_byte();
36 break;
37 case 2:
38 /* reg, 32-bit displacement */
39 resolve_modrm = &disassembler::resolve64_mod1or2;
40 insn->displacement.displ32 = fetch_dword();
41 break;
42 } /* switch (mod) */
43 } /* if (rm != 4) */
44 else { /* rm == 4, s-i-b byte follows */
45 insn->sib = fetch_byte();
46 BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
47 insn->base |= insn->rex_b;
48 insn->index |= insn->rex_x;
50 switch (insn->mod) {
51 case 0:
52 resolve_modrm = &disassembler::resolve64_mod0_rm4;
53 if ((insn->base & 7) == 5)
54 insn->displacement.displ32 = fetch_dword();
55 break;
56 case 1:
57 resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
58 insn->displacement.displ32 = (Bit8s) fetch_byte();
59 break;
60 case 2:
61 resolve_modrm = &disassembler::resolve64_mod1or2_rm4;
62 insn->displacement.displ32 = fetch_dword();
63 break;
65 } /* s-i-b byte follows */
67 else
69 if (insn->as_32)
71 if ((insn->rm & 7) != 4) { /* rm != 100b, no s-i-b byte */
72 // one byte modrm
73 switch (insn->mod) {
74 case 0:
75 resolve_modrm = &disassembler::resolve32_mod0;
76 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
77 insn->displacement.displ32 = fetch_dword();
78 break;
79 case 1:
80 /* reg, 8-bit displacement, sign extend */
81 resolve_modrm = &disassembler::resolve32_mod1or2;
82 insn->displacement.displ32 = (Bit8s) fetch_byte();
83 break;
84 case 2:
85 /* reg, 32-bit displacement */
86 resolve_modrm = &disassembler::resolve32_mod1or2;
87 insn->displacement.displ32 = fetch_dword();
88 break;
89 } /* switch (mod) */
90 } /* if (rm != 4) */
91 else { /* rm == 4, s-i-b byte follows */
92 insn->sib = fetch_byte();
93 BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
94 insn->base |= insn->rex_b;
95 insn->index |= insn->rex_x;
97 switch (insn->mod) {
98 case 0:
99 resolve_modrm = &disassembler::resolve32_mod0_rm4;
100 if ((insn->base & 7) == 5)
101 insn->displacement.displ32 = fetch_dword();
102 break;
103 case 1:
104 resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
105 insn->displacement.displ32 = (Bit8s) fetch_byte();
106 break;
107 case 2:
108 resolve_modrm = &disassembler::resolve32_mod1or2_rm4;
109 insn->displacement.displ32 = fetch_dword();
110 break;
112 } /* s-i-b byte follows */
114 else {
115 assert(insn->rex_b == 0);
116 assert(insn->rex_x == 0);
117 assert(insn->rex_r == 0);
118 /* 16 bit addressing modes. */
119 switch (insn->mod) {
120 case 0:
121 resolve_modrm = &disassembler::resolve16_mod0;
122 if(insn->rm == 6)
123 insn->displacement.displ16 = fetch_word();
124 break;
125 case 1:
126 /* reg, 8-bit displacement, sign extend */
127 resolve_modrm = &disassembler::resolve16_mod1or2;
128 insn->displacement.displ16 = (Bit8s) fetch_byte();
129 break;
130 case 2:
131 resolve_modrm = &disassembler::resolve16_mod1or2;
132 insn->displacement.displ16 = fetch_word();
133 break;
134 } /* switch (mod) ... */
139 void disassembler::resolve16_mod0(const x86_insn *insn, unsigned mode)
141 const char *seg;
143 if (insn->is_seg_override())
144 seg = segment_name[insn->seg_override];
145 else
146 seg = sreg_mod00_rm16[insn->rm];
148 if(insn->rm == 6)
149 print_memory_access16(mode, seg, NULL, insn->displacement.displ16);
150 else
151 print_memory_access16(mode, seg, index16[insn->rm], 0);
154 void disassembler::resolve16_mod1or2(const x86_insn *insn, unsigned mode)
156 const char *seg;
158 if (insn->is_seg_override())
159 seg = segment_name[insn->seg_override];
160 else
161 seg = sreg_mod01or10_rm16[insn->rm];
163 print_memory_access16(mode, seg, index16[insn->rm], insn->displacement.displ16);
166 void disassembler::resolve32_mod0(const x86_insn *insn, unsigned mode)
168 const char *seg, *eip_regname = NULL;
170 if (insn->is_seg_override())
171 seg = segment_name[insn->seg_override];
172 else
173 seg = segment_name[DS_REG];
175 if (insn->is_64) {
176 if (intel_mode) eip_regname = "eip";
177 else eip_regname = "%eip";
180 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
181 print_memory_access(mode, seg, eip_regname, NULL, 0, insn->displacement.displ32);
182 else
183 print_memory_access(mode, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
186 void disassembler::resolve32_mod1or2(const x86_insn *insn, unsigned mode)
188 const char *seg;
190 if (insn->is_seg_override())
191 seg = segment_name[insn->seg_override];
192 else
193 seg = sreg_mod01or10_rm32[insn->rm];
195 print_memory_access(mode, seg,
196 general_32bit_regname[insn->rm], NULL, 0, insn->displacement.displ32);
199 void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned mode)
201 const char *seg, *base = NULL, *index = NULL;
202 Bit32u disp32 = 0;
204 if (insn->is_seg_override())
205 seg = segment_name[insn->seg_override];
206 else
207 seg = sreg_mod00_base32[insn->base];
209 if ((insn->base & 7) != 5)
210 base = general_32bit_regname[insn->base];
211 else
212 disp32 = insn->displacement.displ32;
214 if (insn->index != 4)
215 index = general_32bit_regname[insn->index];
217 print_memory_access(mode, seg, base, index, insn->scale, disp32);
220 void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode)
222 const char *seg, *index = NULL;
224 if (insn->is_seg_override())
225 seg = segment_name[insn->seg_override];
226 else
227 seg = sreg_mod01or10_base32[insn->base];
229 if (insn->index != 4)
230 index = general_32bit_regname[insn->index];
232 print_memory_access(mode, seg,
233 general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
236 void disassembler::resolve64_mod0(const x86_insn *insn, unsigned mode)
238 const char *seg, *rip_regname;
240 if (insn->is_seg_override())
241 seg = segment_name[insn->seg_override];
242 else
243 seg = segment_name[DS_REG];
245 if (intel_mode) rip_regname = "rip";
246 else rip_regname = "%rip";
248 if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
249 print_memory_access(mode, seg, rip_regname, NULL, 0, (Bit32s) insn->displacement.displ32, 1);
250 else
251 print_memory_access(mode, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
254 void disassembler::resolve64_mod1or2(const x86_insn *insn, unsigned mode)
256 const char *seg;
258 if (insn->is_seg_override())
259 seg = segment_name[insn->seg_override];
260 else
261 seg = sreg_mod01or10_rm32[insn->rm];
263 print_memory_access(mode, seg,
264 general_64bit_regname[insn->rm], NULL, 0, (Bit32s) insn->displacement.displ32, 1);
267 void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned mode)
269 const char *seg, *base = NULL, *index = NULL;
270 Bit32s disp32 = 0;
272 if (insn->is_seg_override())
273 seg = segment_name[insn->seg_override];
274 else
275 seg = sreg_mod00_base32[insn->base];
277 if ((insn->base & 7) != 5)
278 base = general_64bit_regname[insn->base];
279 else
280 disp32 = (Bit32s) insn->displacement.displ32;
282 if (insn->index != 4)
283 index = general_64bit_regname[insn->index];
285 print_memory_access(mode, seg, base, index, insn->scale, disp32, 1);
288 void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode)
290 const char *seg, *index = NULL;
292 if (insn->is_seg_override())
293 seg = segment_name[insn->seg_override];
294 else
295 seg = sreg_mod01or10_base32[insn->base];
297 if (insn->index != 4)
298 index = general_64bit_regname[insn->index];
300 print_memory_access(mode, seg,
301 general_64bit_regname[insn->base], index, insn->scale, (Bit32s) insn->displacement.displ32, 1);
304 void disassembler::print_datasize(unsigned size)
306 if (!intel_mode) return;
308 switch(size)
310 case B_SIZE:
311 dis_sprintf("byte ptr ");
312 break;
313 case W_SIZE:
314 dis_sprintf("word ptr ");
315 break;
316 case D_SIZE:
317 dis_sprintf("dword ptr ");
318 break;
319 case Q_SIZE:
320 dis_sprintf("qword ptr ");
321 break;
322 case O_SIZE:
323 dis_sprintf("dqword ptr ");
324 break;
325 case T_SIZE:
326 dis_sprintf("tbyte ptr ");
327 break;
328 case P_SIZE:
329 break;
330 case X_SIZE:
331 break;
335 void disassembler::print_memory_access16(int datasize,
336 const char *seg, const char *index, Bit16u disp)
338 print_datasize(datasize);
340 if (intel_mode)
342 if (index == NULL)
344 dis_sprintf("%s:0x%x", seg, (unsigned) disp);
346 else
348 if (disp != 0)
349 dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
350 else
351 dis_sprintf("%s:[%s]", seg, index);
354 else
356 if (index == NULL)
358 dis_sprintf("%s:0x%x", seg, (unsigned) disp);
360 else
362 if (disp != 0)
363 dis_sprintf("%s:0x%x(%s,1)", seg, (unsigned) disp, index);
364 else
365 dis_sprintf("%s:(%s,1)", seg, index);
370 void disassembler::print_memory_access(int datasize,
371 const char *seg, const char *base, const char *index, int scale, Bit32s disp, bx_bool disp64)
373 print_datasize(datasize);
375 scale = 1 << scale;
377 if (intel_mode)
379 if (base == NULL)
381 if (index == NULL)
383 if (disp64) {
384 dis_sprintf("%s:0x%08x%08x", seg, GET32H(disp), GET32L(disp));
385 } else {
386 dis_sprintf("%s:0x%x", seg, (unsigned) disp);
389 else
391 if (scale != 1)
393 if (disp != 0) {
394 if (disp64) {
395 dis_sprintf("%s:[%s*%d+0x%08x%08x]", seg, index, scale,
396 GET32H(disp), GET32L(disp));
398 else {
399 dis_sprintf("%s:[%s*%d+0x%x]", seg, index, scale, (unsigned) disp);
402 else
403 dis_sprintf("%s:[%s*%d]", seg, index, scale);
405 else
407 if (disp != 0) {
408 if (disp64) {
409 dis_sprintf("%s:[%s+0x%08x%08x]", seg, index, GET32H(disp), GET32L(disp));
411 else {
412 dis_sprintf("%s:[%s+0x%x]", seg, index, (unsigned) disp);
415 else {
416 dis_sprintf("%s:[%s]", seg, index);
421 else
423 if (index == NULL)
425 if (disp != 0) {
426 if (disp64) {
427 dis_sprintf("%s:[%s+0x%08x%08x]", seg, base, GET32H(disp), GET32L(disp));
429 else {
430 dis_sprintf("%s:[%s+0x%x]", seg, base, (unsigned) disp);
433 else {
434 dis_sprintf("%s:[%s]", seg, base);
437 else
439 if (scale != 1)
441 if (disp != 0) {
442 if (disp64) {
443 dis_sprintf("%s:[%s+%s*%d+0x%08x%08x]", seg, base, index, scale,
444 GET32H(disp), GET32L(disp));
446 else {
447 dis_sprintf("%s:[%s+%s*%d+0x%x]", seg, base, index, scale, (unsigned) disp);
450 else {
451 dis_sprintf("%s:[%s+%s*%d]", seg, base, index, scale);
454 else
456 if (disp != 0) {
457 if (disp64) {
458 dis_sprintf("%s:[%s+%s+0x%08x%08x]", seg, base, index, GET32H(disp), GET32L(disp));
460 else {
461 dis_sprintf("%s:[%s+%s+0x%x]", seg, base, index, (unsigned) disp);
464 else
465 dis_sprintf("%s:[%s+%s]", seg, base, index);
470 else
472 if (base == NULL)
474 if (index == NULL)
476 if (disp64) {
477 dis_sprintf("%s:0x%08x%08x", seg, GET32H(disp), GET32L(disp));
478 } else {
479 dis_sprintf("%s:0x%x", seg, (unsigned) disp);
482 else
484 if (disp != 0) {
485 if (disp64) {
486 dis_sprintf("%s:0x%08x%08x(,%s,%d)", seg, GET32H(disp), GET32L(disp), index, scale);
487 } else {
488 dis_sprintf("%s:0x%x(,%s,%d)", seg, (unsigned) disp, index, scale);
491 else
492 dis_sprintf("%s:(,%s,%d)", seg, index, scale);
495 else
497 if (index == NULL)
499 if (disp != 0) {
500 if (disp64) {
501 dis_sprintf("%s:0x%08x%08x(%s)", seg, GET32H(disp), GET32L(disp), base);
503 else {
504 dis_sprintf("%s:0x%x(%s)", seg, (unsigned) disp, base);
507 else
508 dis_sprintf("%s:(%s)", seg, base);
510 else
512 if (disp != 0) {
513 if (disp64) {
514 dis_sprintf("%s:0x%08x%08x(%s,%s,%d)", seg, GET32H(disp), GET32L(disp), base, index, scale);
516 else {
517 dis_sprintf("%s:0x%x(%s,%s,%d)", seg, (unsigned) disp, base, index, scale);
520 else
521 dis_sprintf("%s:(%s,%s,%d)", seg, base, index, scale);