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_types.h>
23 /* .... Giant fucking switch tables */
145 static int get_operand_width(struct guest_info * info, struct x86_instr * instr, op_form_t form) {
246 switch (v3_get_vm_cpu_mode(info)) {
248 return (instr->prefixes.op_size) ? 4 : 2;
251 return (instr->prefixes.op_size) ? 2 : 4;
255 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
261 switch (v3_get_vm_cpu_mode(info)) {
263 PrintError("Invalid instruction given operating mode (%d)\n", form);
271 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
278 switch (v3_get_vm_cpu_mode(info)) {
287 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
295 switch (v3_get_vm_cpu_mode(info)) {
303 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
311 PrintError("Unsupported instruction form %d\n", form);
320 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
321 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
328 } __attribute__((packed));
335 } __attribute__((packed));
342 static inline int decode_gpr(struct v3_gprs * gprs,
344 struct x86_operand * reg) {
348 reg->operand = (addr_t)&(gprs->rax);
351 reg->operand = (addr_t)&(gprs->rcx);
354 reg->operand = (addr_t)&(gprs->rdx);
357 reg->operand = (addr_t)&(gprs->rbx);
360 if (reg->size == 1) {
361 reg->operand = (addr_t)&(gprs->rax) + 1;
363 reg->operand = (addr_t)&(gprs->rsp);
367 if (reg->size == 1) {
368 reg->operand = (addr_t)&(gprs->rcx) + 1;
370 reg->operand = (addr_t)&(gprs->rbp);
374 if (reg->size == 1) {
375 reg->operand = (addr_t)&(gprs->rdx) + 1;
377 reg->operand = (addr_t)&(gprs->rsi);
381 if (reg->size == 1) {
382 reg->operand = (addr_t)&(gprs->rbx) + 1;
384 reg->operand = (addr_t)&(gprs->rdi);
396 // This converts the displacement into the appropriate masked value
398 QUESTION: Are the register Values signed ?????
400 #define MASK_DISPLACEMENT(reg, mode) ({ \
402 if (mode == DISP8) { \
403 val = (sint8_t)(reg & 0xff); \
404 } else if (mode == DISP16) { \
405 val = (sint16_t)(reg & 0xffff); \
406 } else if (mode == DISP32) { \
407 val = (sint32_t)(reg & 0xffffffff); \
409 PrintError("Error invalid displacement size (%d)\n", mode); \
415 static int decode_rm_operand16(struct v3_gprs * gprs,
417 struct x86_operand * operand,
418 uint8_t * reg_code) {
421 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
422 addr_t base_addr = 0;
423 modrm_mode_t mod_mode = 0;
424 char * instr_cursor = modrm_instr;
426 // PrintDebug("ModRM mod=%d\n", modrm->mod);
428 *reg_code = modrm->reg;
432 if (modrm->mod == 3) {
433 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
434 operand->type = REG_OPERAND;
436 decode_gpr(gprs, modrm->rm, operand);
440 operand->type = MEM_OPERAND;
442 if (modrm->mod == 0) {
444 } else if (modrm->mod == 1) {
446 } else if (modrm->mod == 2) {
452 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
455 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
458 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
461 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
464 base_addr = gprs->rsi;
467 base_addr = gprs->rdi;
470 if (modrm->mod == 0) {
474 base_addr = gprs->rbp;
478 base_addr = gprs->rbx;
484 if (mod_mode == DISP8) {
485 base_addr += *(sint8_t *)instr_cursor;
487 } else if (mod_mode == DISP16) {
488 base_addr += *(sint16_t *)instr_cursor;
492 operand->operand = base_addr;
496 return (instr_cursor - modrm_instr);
500 // returns num_bytes parsed
501 static int decode_rm_operand32(struct v3_gprs * gprs, // input/output
502 uint8_t * modrm_instr, // input
503 struct x86_operand * operand,
504 uint8_t * reg_code) {
506 uchar_t * instr_cursor = modrm_instr;
507 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
508 addr_t base_addr = 0;
509 modrm_mode_t mod_mode = 0;
510 uint_t has_sib_byte = 0;
513 *reg_code = modrm->reg;
517 if (modrm->mod == 3) {
518 operand->type = REG_OPERAND;
519 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
521 decode_gpr(gprs, modrm->rm, operand);
525 operand->type = MEM_OPERAND;
527 if (modrm->mod == 0) {
529 } else if (modrm->mod == 1) {
531 } else if (modrm->mod == 2) {
537 base_addr = gprs->rax;
540 base_addr = gprs->rcx;
543 base_addr = gprs->rdx;
546 base_addr = gprs->rbx;
552 if (modrm->mod == 0) {
556 base_addr = gprs->rbp;
560 base_addr = gprs->rsi;
563 base_addr = gprs->rdi;
569 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
570 int scale = 0x1 << sib->scale;
574 switch (sib->index) {
576 base_addr = gprs->rax;
579 base_addr = gprs->rcx;
582 base_addr = gprs->rdx;
585 base_addr = gprs->rbx;
591 base_addr = gprs->rbp;
594 base_addr = gprs->rsi;
597 base_addr = gprs->rdi;
606 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
609 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
612 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
615 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
618 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
621 if (modrm->mod != 0) {
622 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
626 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
629 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
636 if (mod_mode == DISP8) {
637 base_addr += *(sint8_t *)instr_cursor;
639 } else if (mod_mode == DISP32) {
640 base_addr += *(sint32_t *)instr_cursor;
645 operand->operand = base_addr;
649 return (instr_cursor - modrm_instr);
656 static int decode_rm_operand(struct guest_info * core,
657 uint8_t * instr_ptr, // input
658 struct x86_operand * operand,
659 uint8_t * reg_code) {
661 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
664 return decode_rm_operand16(&(core->vm_regs), instr_ptr, operand, reg_code);
665 } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) {
666 return decode_rm_operand32(&(core->vm_regs), instr_ptr, operand, reg_code);
668 PrintError("Invalid CPU_MODE (%d)\n", mode);
675 static inline op_form_t op_code_to_form_0f(uint8_t * instr) {
678 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
680 switch (modrm->reg) {
688 return INVALID_INSTR;
749 return INVALID_INSTR;
754 static op_form_t op_code_to_form(uint8_t * instr) {
776 return op_code_to_form_0f(instr);
816 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
818 switch (modrm->reg) {
832 return INVALID_INSTR;
836 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
838 switch (modrm->reg) {
852 return INVALID_INSTR;
856 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
858 switch (modrm->reg) {
872 return INVALID_INSTR;
929 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
931 switch (modrm->reg) {
937 return INVALID_INSTR;
941 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
943 switch (modrm->reg) {
949 return INVALID_INSTR;
955 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
957 switch (modrm->reg) {
963 return INVALID_INSTR;
968 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
970 switch (modrm->reg) {
976 return INVALID_INSTR;
981 return INVALID_INSTR;