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".
21 #include <palacios/vmm_decoder.h>
27 uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes) {
28 uint8_t * instr_cursor = instr;
31 switch (*instr_cursor) {
36 case 0xF2: // REPNE/REPNZ
41 case 0xF3: // REP or REPE/REPZ
47 case 0x2E: // CS override or Branch hint not taken (with Jcc instr_cursors)
48 prefixes->cs_override = 1;
49 prefixes->br_not_taken = 1;
52 case 0x36: // SS override
53 prefixes->ss_override = 1;
56 case 0x3E: // DS override or Branch hint taken (with Jcc instr_cursors)
57 prefixes->ds_override = 1;
58 prefixes->br_taken = 1;
61 case 0x26: // ES override
62 prefixes->es_override = 1;
65 case 0x64: // FS override
66 prefixes->fs_override = 1;
69 case 0x65: // GS override
70 prefixes->gs_override = 1;
73 case 0x66: // operand size override
74 prefixes->op_size = 1;
77 case 0x67: // address size override
78 prefixes->addr_size = 1;
82 return (instr_cursor - instr);
89 void v3_strip_rep_prefix(uchar_t * instr, int length) {
94 while (read_ctr < length) {
96 ( (instr[read_ctr] == 0xF2) ||
97 (instr[read_ctr] == 0xF3))) {
101 instr[write_ctr] = instr[read_ctr];
109 static char * op_type_to_str(v3_op_type_t type) {
111 case V3_OP_MOVCR2: return "V3_OP_MOVCR2";
112 case V3_OP_MOV2CR: return "V3_OP_MOV2CR";
113 case V3_OP_SMSW: return "V3_OP_SMSW";
114 case V3_OP_LMSW: return "V3_OP_LMSW";
115 case V3_OP_CLTS: return "V3_OP_CLTS";
116 case V3_OP_INVLPG: return "V3_OP_INVLPG";
117 case V3_OP_ADC: return "V3_OP_ADC";
118 case V3_OP_ADD: return "V3_OP_ADD";
119 case V3_OP_AND: return "V3_OP_AND";
120 case V3_OP_OR: return "V3_OP_OR";
121 case V3_OP_XOR: return "V3_OP_XOR";
122 case V3_OP_SUB: return "V3_OP_SUB";
123 case V3_OP_INC: return "V3_OP_INC";
124 case V3_OP_DEC: return "V3_OP_DEC";
125 case V3_OP_NEG: return "V3_OP_NEG";
126 case V3_OP_MOV: return "V3_OP_MOV";
127 case V3_OP_NOT: return "V3_OP_NOT";
128 case V3_OP_XCHG: return "V3_OP_XCHG";
129 case V3_OP_SETB: return "V3_OP_SETB";
130 case V3_OP_SETBE: return "V3_OP_SETBE";
131 case V3_OP_SETL: return "V3_OP_SETL";
132 case V3_OP_SETLE: return "V3_OP_SETLE";
133 case V3_OP_SETNB: return "V3_OP_SETNB";
134 case V3_OP_SETNBE: return "V3_OP_SETNBE";
135 case V3_OP_SETNL: return "V3_OP_SETNL";
136 case V3_OP_SETNLE: return "V3_OP_SETNLE";
137 case V3_OP_SETNO: return "V3_OP_SETNO";
138 case V3_OP_SETNP: return "V3_OP_SETNP";
139 case V3_OP_SETNS: return "V3_OP_SETNS";
140 case V3_OP_SETNZ: return "V3_OP_SETNZ";
141 case V3_OP_SETO: return "V3_OP_SETO";
142 case V3_OP_SETP: return "V3_OP_SETP";
143 case V3_OP_SETS: return "V3_OP_SETS";
144 case V3_OP_SETZ: return "V3_OP_SETZ";
145 case V3_OP_MOVS: return "V3_OP_MOVS";
146 case V3_OP_STOS: return "V3_OP_STOS";
147 case V3_OP_MOVZX: return "V3_OP_MOVZX";
148 case V3_OP_MOVSX: return "V3_OP_MOVSX";
149 case V3_OP_INT: return "V3_OP_INT";
152 return "V3_INVALID_OP";
157 static char * operand_type_to_str(v3_operand_type_t op) {
159 case REG_OPERAND: return "REG_OPERAND";
160 case MEM_OPERAND: return "MEM_OPERAND";
161 case IMM_OPERAND: return "IMM_OPERAND";
163 return "INVALID_OPERAND";
168 static const ullong_t mask_1 = 0x00000000000000ffLL;
169 static const ullong_t mask_2 = 0x000000000000ffffLL;
170 static const ullong_t mask_4 = 0x00000000ffffffffLL;
171 static const ullong_t mask_8 = 0xffffffffffffffffLL;
174 #define MASK(val, length) ({ \
175 ullong_t mask = 0x0LL; \
193 void v3_print_instr(struct x86_instr * instr) {
194 V3_Print("Instr: %s (Len: %d)\n", op_type_to_str(instr->op_type), instr->instr_length);
196 V3_Print("Prefixes= %x\n", instr->prefixes.val);
198 if (instr->is_str_op) {
199 V3_Print("String OP (len=%d)\n", (uint32_t)instr->str_op_length);
202 V3_Print("Number of operands: %d\n", instr->num_operands);
204 if (instr->num_operands > 0) {
205 V3_Print("Src Operand (%s)\n", operand_type_to_str(instr->src_operand.type));
206 V3_Print("\tLen=%d (Addr: %p)\n", instr->src_operand.size,
207 (void *)instr->src_operand.operand);
208 if (instr->src_operand.type == REG_OPERAND) {
209 V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->src_operand.operand), instr->src_operand.size));
213 if (instr->num_operands > 1) {
214 V3_Print("Dst Operand (%s)\n", operand_type_to_str(instr->dst_operand.type));
215 V3_Print("\tLen=%d (Addr: %p)\n", instr->dst_operand.size,
216 (void *)instr->dst_operand.operand);
217 if (instr->dst_operand.type == REG_OPERAND) {
218 V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->dst_operand.operand), instr->dst_operand.size));
222 if (instr->num_operands > 2) {
223 V3_Print("Third Operand (%s)\n", operand_type_to_str(instr->third_operand.type));
224 V3_Print("\tLen=%d (Addr: %p)\n", instr->third_operand.size,
225 (void *)instr->third_operand.operand);
226 if (instr->third_operand.type == REG_OPERAND) {
227 V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->third_operand.operand), instr->third_operand.size));