1 /////////////////////////////////////////////////////////////////////////
2 // $Id: resolve.cc,v 1.18 2008/04/11 17:54:21 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
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
;
19 return; /* mod, reg, reg */
24 if ((insn
->rm
& 7) != 4) { /* rm != 100b, no s-i-b byte */
28 resolve_modrm
= &disassembler::resolve64_mod0
;
29 if ((insn
->rm
& 7) == 5) /* no reg, 32-bit displacement */
30 insn
->displacement
.displ32
= fetch_dword();
33 /* reg, 8-bit displacement, sign extend */
34 resolve_modrm
= &disassembler::resolve64_mod1or2
;
35 insn
->displacement
.displ32
= (Bit8s
) fetch_byte();
38 /* reg, 32-bit displacement */
39 resolve_modrm
= &disassembler::resolve64_mod1or2
;
40 insn
->displacement
.displ32
= fetch_dword();
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
;
52 resolve_modrm
= &disassembler::resolve64_mod0_rm4
;
53 if ((insn
->base
& 7) == 5)
54 insn
->displacement
.displ32
= fetch_dword();
57 resolve_modrm
= &disassembler::resolve64_mod1or2_rm4
;
58 insn
->displacement
.displ32
= (Bit8s
) fetch_byte();
61 resolve_modrm
= &disassembler::resolve64_mod1or2_rm4
;
62 insn
->displacement
.displ32
= fetch_dword();
65 } /* s-i-b byte follows */
71 if ((insn
->rm
& 7) != 4) { /* rm != 100b, no s-i-b byte */
75 resolve_modrm
= &disassembler::resolve32_mod0
;
76 if ((insn
->rm
& 7) == 5) /* no reg, 32-bit displacement */
77 insn
->displacement
.displ32
= fetch_dword();
80 /* reg, 8-bit displacement, sign extend */
81 resolve_modrm
= &disassembler::resolve32_mod1or2
;
82 insn
->displacement
.displ32
= (Bit8s
) fetch_byte();
85 /* reg, 32-bit displacement */
86 resolve_modrm
= &disassembler::resolve32_mod1or2
;
87 insn
->displacement
.displ32
= fetch_dword();
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
;
99 resolve_modrm
= &disassembler::resolve32_mod0_rm4
;
100 if ((insn
->base
& 7) == 5)
101 insn
->displacement
.displ32
= fetch_dword();
104 resolve_modrm
= &disassembler::resolve32_mod1or2_rm4
;
105 insn
->displacement
.displ32
= (Bit8s
) fetch_byte();
108 resolve_modrm
= &disassembler::resolve32_mod1or2_rm4
;
109 insn
->displacement
.displ32
= fetch_dword();
112 } /* s-i-b byte follows */
115 assert(insn
->rex_b
== 0);
116 assert(insn
->rex_x
== 0);
117 assert(insn
->rex_r
== 0);
118 /* 16 bit addressing modes. */
121 resolve_modrm
= &disassembler::resolve16_mod0
;
123 insn
->displacement
.displ16
= fetch_word();
126 /* reg, 8-bit displacement, sign extend */
127 resolve_modrm
= &disassembler::resolve16_mod1or2
;
128 insn
->displacement
.displ16
= (Bit8s
) fetch_byte();
131 resolve_modrm
= &disassembler::resolve16_mod1or2
;
132 insn
->displacement
.displ16
= fetch_word();
134 } /* switch (mod) ... */
139 void disassembler::resolve16_mod0(const x86_insn
*insn
, unsigned mode
)
143 if (insn
->is_seg_override())
144 seg
= segment_name
[insn
->seg_override
];
146 seg
= sreg_mod00_rm16
[insn
->rm
];
149 print_memory_access16(mode
, seg
, NULL
, insn
->displacement
.displ16
);
151 print_memory_access16(mode
, seg
, index16
[insn
->rm
], 0);
154 void disassembler::resolve16_mod1or2(const x86_insn
*insn
, unsigned mode
)
158 if (insn
->is_seg_override())
159 seg
= segment_name
[insn
->seg_override
];
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
];
173 seg
= segment_name
[DS_REG
];
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
);
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
)
190 if (insn
->is_seg_override())
191 seg
= segment_name
[insn
->seg_override
];
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
;
204 if (insn
->is_seg_override())
205 seg
= segment_name
[insn
->seg_override
];
207 seg
= sreg_mod00_base32
[insn
->base
];
209 if ((insn
->base
& 7) != 5)
210 base
= general_32bit_regname
[insn
->base
];
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
];
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
];
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);
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
)
258 if (insn
->is_seg_override())
259 seg
= segment_name
[insn
->seg_override
];
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
;
272 if (insn
->is_seg_override())
273 seg
= segment_name
[insn
->seg_override
];
275 seg
= sreg_mod00_base32
[insn
->base
];
277 if ((insn
->base
& 7) != 5)
278 base
= general_64bit_regname
[insn
->base
];
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
];
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;
311 dis_sprintf("byte ptr ");
314 dis_sprintf("word ptr ");
317 dis_sprintf("dword ptr ");
320 dis_sprintf("qword ptr ");
323 dis_sprintf("dqword ptr ");
326 dis_sprintf("tbyte ptr ");
335 void disassembler::print_memory_access16(int datasize
,
336 const char *seg
, const char *index
, Bit16u disp
)
338 print_datasize(datasize
);
344 dis_sprintf("%s:0x%x", seg
, (unsigned) disp
);
349 dis_sprintf("%s:[%s+0x%x]", seg
, index
, (unsigned) disp
);
351 dis_sprintf("%s:[%s]", seg
, index
);
358 dis_sprintf("%s:0x%x", seg
, (unsigned) disp
);
363 dis_sprintf("%s:0x%x(%s,1)", seg
, (unsigned) disp
, index
);
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
);
384 dis_sprintf("%s:0x%08x%08x", seg
, GET32H(disp
), GET32L(disp
));
386 dis_sprintf("%s:0x%x", seg
, (unsigned) disp
);
395 dis_sprintf("%s:[%s*%d+0x%08x%08x]", seg
, index
, scale
,
396 GET32H(disp
), GET32L(disp
));
399 dis_sprintf("%s:[%s*%d+0x%x]", seg
, index
, scale
, (unsigned) disp
);
403 dis_sprintf("%s:[%s*%d]", seg
, index
, scale
);
409 dis_sprintf("%s:[%s+0x%08x%08x]", seg
, index
, GET32H(disp
), GET32L(disp
));
412 dis_sprintf("%s:[%s+0x%x]", seg
, index
, (unsigned) disp
);
416 dis_sprintf("%s:[%s]", seg
, index
);
427 dis_sprintf("%s:[%s+0x%08x%08x]", seg
, base
, GET32H(disp
), GET32L(disp
));
430 dis_sprintf("%s:[%s+0x%x]", seg
, base
, (unsigned) disp
);
434 dis_sprintf("%s:[%s]", seg
, base
);
443 dis_sprintf("%s:[%s+%s*%d+0x%08x%08x]", seg
, base
, index
, scale
,
444 GET32H(disp
), GET32L(disp
));
447 dis_sprintf("%s:[%s+%s*%d+0x%x]", seg
, base
, index
, scale
, (unsigned) disp
);
451 dis_sprintf("%s:[%s+%s*%d]", seg
, base
, index
, scale
);
458 dis_sprintf("%s:[%s+%s+0x%08x%08x]", seg
, base
, index
, GET32H(disp
), GET32L(disp
));
461 dis_sprintf("%s:[%s+%s+0x%x]", seg
, base
, index
, (unsigned) disp
);
465 dis_sprintf("%s:[%s+%s]", seg
, base
, index
);
477 dis_sprintf("%s:0x%08x%08x", seg
, GET32H(disp
), GET32L(disp
));
479 dis_sprintf("%s:0x%x", seg
, (unsigned) disp
);
486 dis_sprintf("%s:0x%08x%08x(,%s,%d)", seg
, GET32H(disp
), GET32L(disp
), index
, scale
);
488 dis_sprintf("%s:0x%x(,%s,%d)", seg
, (unsigned) disp
, index
, scale
);
492 dis_sprintf("%s:(,%s,%d)", seg
, index
, scale
);
501 dis_sprintf("%s:0x%08x%08x(%s)", seg
, GET32H(disp
), GET32L(disp
), base
);
504 dis_sprintf("%s:0x%x(%s)", seg
, (unsigned) disp
, base
);
508 dis_sprintf("%s:(%s)", seg
, base
);
514 dis_sprintf("%s:0x%08x%08x(%s,%s,%d)", seg
, GET32H(disp
), GET32L(disp
), base
, index
, scale
);
517 dis_sprintf("%s:0x%x(%s,%s,%d)", seg
, (unsigned) disp
, base
, index
, scale
);
521 dis_sprintf("%s:(%s,%s,%d)", seg
, base
, index
, scale
);