2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_decoder.h>
23 /* .... Giant fucking switch tables */
27 #define MODRM_MOD(x) (((x) >> 6) & 0x3)
28 #define MODRM_REG(x) (((x) >> 3) & 0x7)
29 #define MODRM_RM(x) ((x) & 0x7)
35 } __attribute__((packed));
38 #define SIB_BASE(x) (((x) >> 6) & 0x3)
39 #define SIB_INDEX(x) (((x) >> 3) & 0x7)
40 #define SIB_SCALE(x) ((x) & 0x7)
46 } __attribute__((packed));
162 static op_form_t op_code_to_form(uint8_t * instr);
166 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
167 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
172 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
177 reg_addr = (addr_t)&(gprs->rax);
180 reg_addr = (addr_t)&(gprs->rcx);
183 reg_addr = (addr_t)&(gprs->rdx);
186 reg_addr = (addr_t)&(gprs->rbx);
189 if (reg_size == REG8) {
190 reg_addr = (addr_t)&(gprs->rax) + 1;
192 reg_addr = (addr_t)&(gprs->rsp);
196 if (reg_size == REG8) {
197 reg_addr = (addr_t)&(gprs->rcx) + 1;
199 reg_addr = (addr_t)&(gprs->rbp);
203 if (reg_size == REG8) {
204 reg_addr = (addr_t)&(gprs->rdx) + 1;
206 reg_addr = (addr_t)&(gprs->rsi);
210 if (reg_size == REG8) {
211 reg_addr = (addr_t)&(gprs->rbx) + 1;
213 reg_addr = (addr_t)&(gprs->rdi);
226 static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
227 char * modrm_instr, // input
228 int * offset, // output
229 addr_t * first_operand, // output
230 addr_t * second_operand, // output
231 reg_size_t reg_size) { // input
233 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
234 addr_t base_addr = 0;
235 modrm_mode_t mod_mode = 0;
236 v3_operand_type_t addr_type = INVALID_OPERAND;
237 char * instr_cursor = modrm_instr;
239 // PrintDebug("ModRM mod=%d\n", modrm->mod);
243 if (modrm->mod == 3) {
245 addr_type = REG_OPERAND;
246 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
248 *first_operand = decode_register(gprs, modrm->rm, reg_size);
252 addr_type = MEM_OPERAND;
254 if (modrm->mod == 0) {
256 } else if (modrm->mod == 1) {
258 } else if (modrm->mod == 2) {
264 base_addr = gprs->rbx + gprs->rsi;
267 base_addr = gprs->rbx + gprs->rdi;
270 base_addr = gprs->rbp + gprs->rsi;
273 base_addr = gprs->rbp + gprs->rdi;
276 base_addr = gprs->rsi;
279 base_addr = gprs->rdi;
282 if (modrm->mod == 0) {
286 base_addr = gprs->rbp;
290 base_addr = gprs->rbx;
296 if (mod_mode == DISP8) {
297 base_addr += (uchar_t)*(instr_cursor);
299 } else if (mod_mode == DISP16) {
300 base_addr += (ushort_t)*(instr_cursor);
304 *first_operand = base_addr;
307 *offset += (instr_cursor - modrm_instr);
308 *second_operand = decode_register(gprs, modrm->reg, reg_size);
315 static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
316 uchar_t * modrm_instr, // input
317 int * offset, // output
318 addr_t * first_operand, // output
319 addr_t * second_operand, // output
320 reg_size_t reg_size) { // input
322 uchar_t * instr_cursor = modrm_instr;
323 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
324 addr_t base_addr = 0;
325 modrm_mode_t mod_mode = 0;
326 uint_t has_sib_byte = 0;
327 v3_operand_type_t addr_type = INVALID_OPERAND;
333 if (modrm->mod == 3) {
335 addr_type = REG_OPERAND;
337 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
339 *first_operand = decode_register(gprs, modrm->rm, reg_size);
343 addr_type = MEM_OPERAND;
345 if (modrm->mod == 0) {
347 } else if (modrm->mod == 1) {
349 } else if (modrm->mod == 2) {
355 base_addr = gprs->rax;
358 base_addr = gprs->rcx;
361 base_addr = gprs->rdx;
364 base_addr = gprs->rbx;
370 if (modrm->mod == 0) {
374 base_addr = gprs->rbp;
378 base_addr = gprs->rsi;
381 base_addr = gprs->rdi;
387 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
393 if (sib->scale == 1) {
395 } else if (sib->scale == 2) {
397 } else if (sib->scale == 3) {
402 switch (sib->index) {
404 base_addr = gprs->rax;
407 base_addr = gprs->rcx;
410 base_addr = gprs->rdx;
413 base_addr = gprs->rbx;
419 base_addr = gprs->rbp;
422 base_addr = gprs->rsi;
425 base_addr = gprs->rdi;
434 base_addr += gprs->rax;
437 base_addr += gprs->rcx;
440 base_addr += gprs->rdx;
443 base_addr += gprs->rbx;
446 base_addr += gprs->rsp;
449 if (modrm->mod != 0) {
450 base_addr += gprs->rbp;
454 base_addr += gprs->rsi;
457 base_addr += gprs->rdi;
464 if (mod_mode == DISP8) {
465 base_addr += (uchar_t)*(instr_cursor);
467 } else if (mod_mode == DISP32) {
468 base_addr += (uint_t)*(instr_cursor);
473 *first_operand = base_addr;
476 *offset += (instr_cursor - modrm_instr);
478 *second_operand = decode_register(gprs, modrm->reg, reg_size);
485 static inline op_form_t op_code_to_form_0f(uint8_t * instr) {
488 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
490 switch (modrm->reg) {
498 return INVALID_INSTR;
559 return INVALID_INSTR;
564 static op_form_t op_code_to_form(uint8_t * instr) {
586 return op_code_to_form_0f(instr);
626 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
628 switch (modrm->reg) {
642 return INVALID_INSTR;
646 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
648 switch (modrm->reg) {
662 return INVALID_INSTR;
666 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
668 switch (modrm->reg) {
682 return INVALID_INSTR;
739 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
741 switch (modrm->reg) {
747 return INVALID_INSTR;
751 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
753 switch (modrm->reg) {
759 return INVALID_INSTR;
765 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
767 switch (modrm->reg) {
773 return INVALID_INSTR;
778 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
780 switch (modrm->reg) {
786 return INVALID_INSTR;
791 return INVALID_INSTR;
795 int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
801 int v3_init_decoder(struct guest_info * core) {
806 int v3_deinit_decoder(struct guest_info * core) {
811 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
815 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
816 op_code_to_form((void *)instr_ptr);