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 */
138 static int get_addr_width(struct guest_info * info, struct x86_instr * instr,
141 switch (v3_get_vm_cpu_mode(info)) {
143 return (instr->prefixes.addr_size) ? 4 : 2;
146 return (instr->prefixes.addr_size) ? 2 : 4;
150 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
155 static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
255 switch (v3_get_vm_cpu_mode(info)) {
257 return (instr->prefixes.op_size) ? 4 : 2;
260 return (instr->prefixes.op_size) ? 2 : 4;
264 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
269 switch (v3_get_vm_cpu_mode(info)) {
271 PrintError("Invalid instruction given operating mode (%d)\n", form);
279 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
285 switch (v3_get_vm_cpu_mode(info)) {
294 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
302 switch (v3_get_vm_cpu_mode(info)) {
310 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
317 PrintError("Unsupported instruction form %d\n", form);
326 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
327 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
334 } __attribute__((packed));
341 } __attribute__((packed));
348 static inline int decode_gpr(struct v3_gprs * gprs,
350 struct x86_operand * reg) {
354 reg->operand = (addr_t)&(gprs->rax);
357 reg->operand = (addr_t)&(gprs->rcx);
360 reg->operand = (addr_t)&(gprs->rdx);
363 reg->operand = (addr_t)&(gprs->rbx);
366 if (reg->size == 1) {
367 reg->operand = (addr_t)&(gprs->rax) + 1;
369 reg->operand = (addr_t)&(gprs->rsp);
373 if (reg->size == 1) {
374 reg->operand = (addr_t)&(gprs->rcx) + 1;
376 reg->operand = (addr_t)&(gprs->rbp);
380 if (reg->size == 1) {
381 reg->operand = (addr_t)&(gprs->rdx) + 1;
383 reg->operand = (addr_t)&(gprs->rsi);
387 if (reg->size == 1) {
388 reg->operand = (addr_t)&(gprs->rbx) + 1;
390 reg->operand = (addr_t)&(gprs->rdi);
402 // This converts the displacement into the appropriate masked value
404 QUESTION: Are the register Values signed ?????
406 #define MASK_DISPLACEMENT(reg, mode) ({ \
408 if (mode == DISP8) { \
409 val = (sint8_t)(reg & 0xff); \
410 } else if (mode == DISP16) { \
411 val = (sint16_t)(reg & 0xffff); \
412 } else if (mode == DISP32) { \
413 val = (sint32_t)(reg & 0xffffffff); \
415 PrintError("Error invalid displacement size (%d)\n", mode); \
421 static int decode_rm_operand16(struct v3_gprs * gprs,
423 struct x86_operand * operand,
424 uint8_t * reg_code) {
427 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
428 addr_t base_addr = 0;
429 modrm_mode_t mod_mode = 0;
430 char * instr_cursor = modrm_instr;
432 // PrintDebug("ModRM mod=%d\n", modrm->mod);
434 *reg_code = modrm->reg;
438 if (modrm->mod == 3) {
439 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
440 operand->type = REG_OPERAND;
442 decode_gpr(gprs, modrm->rm, operand);
446 operand->type = MEM_OPERAND;
448 if (modrm->mod == 0) {
450 } else if (modrm->mod == 1) {
452 } else if (modrm->mod == 2) {
458 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
461 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
464 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
467 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
470 base_addr = gprs->rsi;
473 base_addr = gprs->rdi;
476 if (modrm->mod == 0) {
480 base_addr = gprs->rbp;
484 base_addr = gprs->rbx;
490 if (mod_mode == DISP8) {
491 base_addr += *(sint8_t *)instr_cursor;
493 } else if (mod_mode == DISP16) {
494 base_addr += *(sint16_t *)instr_cursor;
498 operand->operand = base_addr;
502 return (instr_cursor - modrm_instr);
506 // returns num_bytes parsed
507 static int decode_rm_operand32(struct v3_gprs * gprs, // input/output
508 uint8_t * modrm_instr, // input
509 struct x86_operand * operand,
510 uint8_t * reg_code) {
512 uchar_t * instr_cursor = modrm_instr;
513 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
514 addr_t base_addr = 0;
515 modrm_mode_t mod_mode = 0;
516 uint_t has_sib_byte = 0;
519 *reg_code = modrm->reg;
523 if (modrm->mod == 3) {
524 operand->type = REG_OPERAND;
525 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
527 decode_gpr(gprs, modrm->rm, operand);
531 operand->type = MEM_OPERAND;
533 if (modrm->mod == 0) {
535 } else if (modrm->mod == 1) {
537 } else if (modrm->mod == 2) {
543 base_addr = gprs->rax;
546 base_addr = gprs->rcx;
549 base_addr = gprs->rdx;
552 base_addr = gprs->rbx;
558 if (modrm->mod == 0) {
562 base_addr = gprs->rbp;
566 base_addr = gprs->rsi;
569 base_addr = gprs->rdi;
575 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
576 int scale = 0x1 << sib->scale;
580 switch (sib->index) {
582 base_addr = gprs->rax;
585 base_addr = gprs->rcx;
588 base_addr = gprs->rdx;
591 base_addr = gprs->rbx;
597 base_addr = gprs->rbp;
600 base_addr = gprs->rsi;
603 base_addr = gprs->rdi;
612 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
615 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
618 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
621 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
624 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
627 if (modrm->mod != 0) {
628 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
632 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
635 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
642 if (mod_mode == DISP8) {
643 base_addr += *(sint8_t *)instr_cursor;
645 } else if (mod_mode == DISP32) {
646 base_addr += *(sint32_t *)instr_cursor;
651 operand->operand = base_addr;
655 return (instr_cursor - modrm_instr);
662 static int decode_rm_operand(struct guest_info * core,
663 uint8_t * instr_ptr, // input
664 struct x86_operand * operand,
665 uint8_t * reg_code) {
667 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
670 return decode_rm_operand16(&(core->vm_regs), instr_ptr, operand, reg_code);
671 } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) {
672 return decode_rm_operand32(&(core->vm_regs), instr_ptr, operand, reg_code);
674 PrintError("Invalid CPU_MODE (%d)\n", mode);
681 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
686 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
688 switch (modrm->reg) {
696 return INVALID_INSTR;
757 return INVALID_INSTR;
762 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
786 return op_code_to_form_0f(instr, length);
826 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
828 switch (modrm->reg) {
842 return INVALID_INSTR;
846 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
848 switch (modrm->reg) {
862 return INVALID_INSTR;
866 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
868 switch (modrm->reg) {
882 return INVALID_INSTR;
939 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
941 switch (modrm->reg) {
947 return INVALID_INSTR;
951 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
953 switch (modrm->reg) {
959 return INVALID_INSTR;
965 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
967 switch (modrm->reg) {
973 return INVALID_INSTR;
978 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
980 switch (modrm->reg) {
986 return INVALID_INSTR;
991 return INVALID_INSTR;