* and the University of New Mexico. You can find out more at
* http://www.v3vee.org
*
- * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * Copyright (c) 2012, Alexander Kudryavtsev <alexk@ispras.ru>
+ * Copyright (c) 2012, The V3VEE Project <http://www.v3vee.org>
* All rights reserved.
*
* Author: Alexander Kudryavtsev <alexk@ispras.ru>
#include <quix86/quix86.h>
+#ifdef V3_CONFIG_TM_FUNC
+#include <extensions/trans_mem.h>
+#endif
+
#ifndef V3_CONFIG_DEBUG_DECODER
#undef PrintDebug
#define PrintDebug(fmt, args...)
return 0;
}
-static int get_opcode(qx86_insn *inst);
+static int get_opcode(qx86_insn *inst, struct guest_info *core);
static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg,
addr_t * v3_reg, uint_t * reg_len);
-static int decode_string_op(struct guest_info * info,
- const qx86_insn * qx86_inst, struct x86_instr * instr)
-{
- int status = 0;
- PrintDebug("String operation\n");
-
- if (instr->prefixes.rep == 1) {
- uint64_t a_mask = ~(~0ULL <<
- (QX86_SIZE_OCTETS(qx86_inst->attributes.addressSize) * 8));
-
- instr->str_op_length = info->vm_regs.rcx & a_mask;
- } else {
- instr->str_op_length = 1;
- }
-
-
- if (instr->op_type == V3_OP_MOVS) {
- instr->num_operands = 2;
-
- if((status = qx86_calculate_linear_address(qx86_inst, 0,
- (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) {
- PrintError("Could not get destination memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- if((status = qx86_calculate_linear_address(qx86_inst, 1,
- (qx86_uint64*)&instr->src_operand.operand)) != QX86_SUCCESS) {
- PrintError("Could not get source memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- instr->dst_operand.write = 1;
- instr->src_operand.read = 1;
-
- } else if (instr->op_type == V3_OP_STOS) {
- instr->num_operands = 2;
-
- if((status = qx86_calculate_linear_address(qx86_inst, 0,
- (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) {
- PrintError("Could not get destination memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- // STOS reads from rax
- qx86_register_to_v3_reg(info,
- qx86_inst->operands[1].u.r.rindex,
- &(instr->src_operand.operand), &(instr->src_operand.size));
- instr->src_operand.type = REG_OPERAND;
-
- instr->src_operand.read = 1;
- instr->dst_operand.write = 1;
-
- } else {
- PrintError("Unhandled String OP\n");
- return -1;
- }
-
- return 0;
-}
-
static int callback(void *data, int rindex, int subreg, unsigned char *value) {
void* reg_addr = 0;
uint_t reg_size;
(addr_t*)®_addr, ®_size);
if(v3_reg_type == -1) {
- PrintError("Callback failed to get register index %d\n", rindex);
+ PrintError(info->vm_info, info, "Callback failed to get register index %d\n", rindex);
return 0;
}
*(uint32_t*)value = ((struct v3_segment*)reg_addr)->limit;
break;
case QX86_SUBREG_FLAGS:
- PrintError("Callback doesn't know how to give flags.\n");
+ PrintError(info->vm_info, info, "Callback doesn't know how to give flags.\n");
return 0;
case QX86_SUBREG_NONE: {
- switch(qx86_rtab[rindex].size) {
+ switch(qx86_rinfo(rindex)->size) {
case 1: *(uint8_t* )value = *(uint8_t* )reg_addr; break;
case 2: *(uint16_t*)value = *(uint16_t*)reg_addr; break;
case 4: *(uint32_t*)value = *(uint32_t*)reg_addr; break;
&(v3_op->operand), &(v3_op->size));
if (v3_reg_type == -1) {
- PrintError("Operand %d is an Unhandled Operand: %s\n", op_num,
- qx86_rtab[qx86_op->u.r.rindex].name);
+ PrintError(info->vm_info, info, "Operand %d is an Unhandled Operand: %s\n", op_num,
+ qx86_rinfo(qx86_op->u.r.rindex)->name);
v3_op->type = INVALID_OPERAND;
return -1;
} else if (v3_reg_type == SEGMENT_REGISTER) {
v3_op->type = REG_OPERAND;
} else if(qx86_op->ot == QX86_OPERAND_TYPE_MEMORY) {
- PrintDebug("Memory operand (%d)\n", op_num);
+ PrintDebug(info->vm_info, info, "Memory operand (%d)\n", op_num);
if((status = qx86_calculate_linear_address(qx86_insn, op_num,
(qx86_uint64*)&v3_op->operand)) != QX86_SUCCESS) {
- PrintError("Could not get memory operand %d: "
+ PrintError(info->vm_info, info, "Could not get memory operand %d: "
"qx86_calculate_linear_address() returns %d\n", op_num, status);
return -1;
}
v3_op->size = qx86_op->u.i.valueSize;
if (v3_op->size > 4) {
- PrintError("Unhandled 64 bit immediates\n");
+ PrintError(info->vm_info, info, "Unhandled 64 bit immediates\n");
return -1;
}
v3_op->operand = (addr_t)*(uint64_t*)qx86_op->u.i.value;
v3_op->type = IMM_OPERAND;
} else {
- PrintError("Unhandled Operand %d Type %d\n", op_num, qx86_op->ot);
+ PrintError(info->vm_info, info, "Unhandled Operand %d Type %d\n", op_num, qx86_op->ot);
return -1;
}
qx86_insn qx86_inst;
uint8_t inst_buf[QX86_INSN_SIZE_MAX];
+ /* 441-tm: add 'escape' trap for Haswell instructions, dont want to stumble
+ * on them!
+ */
+#ifdef V3_CONFIG_TM_FUNC
+ {
+ struct v3_trans_mem * tm = (struct v3_trans_mem *)v3_get_ext_core_state(info, "trans_mem");
+ if (tm->TM_MODE == TM_ON) {
+ int byte1 = *(uint8_t *)(instr_ptr);
+ int byte2 = *(uint8_t *)(instr_ptr + 1);
+ int byte3 = *(uint8_t *)(instr_ptr + 2);
+ if (byte1 == 0xc7 && byte2 == 0xf8) { /* third byte is an immediate */
+ //V3_Print("Decoding %x %x %d\n", byte1, byte2, byte3);
+ instr->instr_length = 6;
+ return 0;
+ } else if (byte1 == 0xc6 && byte2 == 0xf8) { /* third byte is an immediate */
+ //V3_Print("Decoding XABORT %x %x %d\n", byte1, byte2, byte3);
+ instr->instr_length = 3;
+ return 0;
+ } else if (byte1 == 0x0f && byte2 == 0x01 && byte3 == 0xd5) {
+ //V3_Print("Decoding XEND %x %x %x\n", byte1, byte2, byte3);
+ instr->instr_length = 3;
+ return 0;
+ }
+ }
+ }
+#endif
+
memset(instr, 0, sizeof(struct x86_instr));
memset(&qx86_inst, 0, sizeof(qx86_inst));
case LONG:
proc_mode = QX86_SIZE_64; break;
default:
- PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
+ PrintError(info->vm_info, info, "Unsupported CPU mode: %d\n", info->cpu_mode);
return -1;
}
(info->rip & ~0xfffULL) + 0x1000, &(info->segments.cs)), &instr_ptr2);
}
if (status == -1) {
- PrintError("Could not translate Instruction Address at second stage "
+ PrintError(info->vm_info, info, "Could not translate Instruction Address at second stage "
"translation (%p)\n", (void *)(addr_t)info->rip);
return -1;
}
if(((instr_ptr & ~0xfffUL) + 0x1000) != instr_ptr2) {
- PrintError("Note: physical page non-contiguous\n");
+ PrintError(info->vm_info, info, "Note: physical page non-contiguous\n");
memcpy(inst_buf, (const void*)instr_ptr, left_in_page);
memcpy(inst_buf + left_in_page, (const void*)instr_ptr2,
QX86_INSN_SIZE_MAX - left_in_page);
int status = qx86_decode(&qx86_inst, proc_mode,
(const void*)instr_ptr, QX86_INSN_SIZE_MAX);
if(status != QX86_SUCCESS) {
- PrintError("qx86_decode() returned %d\n", status);
+ PrintError(info->vm_info, info, "qx86_decode() returned %d\n", status);
return -1;
}
instr->instr_length = qx86_inst.rawSize;
- if ((instr->op_type = get_opcode(&qx86_inst)) == V3_INVALID_OP) {
- PrintError("Could not get opcode. (mnemonic=%s)\n",
- qx86_mtab[qx86_inst.mnemonic].name);
+ // 441 - dump memory for quix86 debugging
+ if ((instr->op_type = get_opcode(&qx86_inst,info)) == V3_INVALID_OP) {
+ PrintError(info->vm_info, info, "++==++ QX86 DECODE ++==++\n");
+ v3_dump_mem((void *)instr_ptr, 15);
+ PrintError(info->vm_info, info, "Could not get opcode. (mnemonic=%s)\n",
+ qx86_minfo(qx86_inst.mnemonic)->name);
+ return -1;
+ }
+ if ((instr->op_type = get_opcode(&qx86_inst, info)) == V3_INVALID_OP) {
+ PrintError(info->vm_info, info, "Could not get opcode. (mnemonic=%s)\n",
+ qx86_minfo(qx86_inst.mnemonic)->name);
return -1;
}
if(instr->op_type == V3_OP_MOVS || instr->op_type == V3_OP_STOS) {
instr->is_str_op = 1;
- return decode_string_op(info, &qx86_inst, instr);
+ if (instr->prefixes.rep == 1) {
+ uint64_t a_mask = (~0ULL >>
+ (64 - QX86_SIZE_OCTETS(qx86_inst.attributes.addressSize) * 8));
+
+ instr->str_op_length = info->vm_regs.rcx & a_mask;
+ } else {
+ instr->str_op_length = 1;
+ }
} else {
instr->is_str_op = 0;
instr->str_op_length = 0;
char buf[128];
int buf_sz = 128;
if(qx86_print_intel(&qx86_inst, &opt, buf, &buf_sz) != QX86_SUCCESS) {
- PrintDebug("Print failed!\n");
+ PrintDebug(info->vm_info, info, "Print failed!\n");
} else {
- PrintDebug("Instruction (%p): %s\n", (void*)info->rip, buf);
+ PrintDebug(info->vm_info, info, "Instruction (%p): %s\n", (void*)info->rip, buf);
}
- PrintDebug("Operands: dst %p src %p 3rd %p\n", (void*)instr->dst_operand.operand,
+ PrintDebug(info->vm_info, info, "Operands: dst %p src %p 3rd %p\n", (void*)instr->dst_operand.operand,
(void*)instr->src_operand.operand, (void*)instr->third_operand.operand);
#endif
return 0;
}
-static int get_opcode(qx86_insn *inst) {
+static int get_opcode(qx86_insn *inst, struct guest_info *core) {
switch (inst->mnemonic) {
#define IS_CR(op) inst->operands[op].ot == QX86_OPERAND_TYPE_REGISTER && \
- qx86_rtab[inst->operands[op].u.r.rindex].rclass == QX86_RCLASS_CREG
+ qx86_rinfo(inst->operands[op].u.r.rindex)->rclass == QX86_RCLASS_CREG
/* MOV cases */
case QX86_MNEMONIC_MOV: {
return V3_OP_MOV2CR;
if(IS_CR(1))
return V3_OP_MOVCR2;
+ // 441 - mov reg reg is also ok
+ if(inst->operands[0].ot == QX86_OPERAND_TYPE_REGISTER
+ || inst->operands[1].ot == QX86_OPERAND_TYPE_REGISTER)
+ return V3_OP_MOV;
- PrintError("Bad operand types for MOV: %d %d\n", inst->operands[0].ot,
+ PrintError(core->vm_info, core, "Bad operand types for MOV: %d %d\n", inst->operands[0].ot,
inst->operands[1].ot);
return V3_INVALID_OP;
}
case QX86_MNEMONIC_STOSQ:
return V3_OP_STOS;
+ /* 441-tm: add in CMP, POP, JLE, CALL cases */
+ case QX86_MNEMONIC_CMP:
+ return V3_OP_CMP;
+
+ case QX86_MNEMONIC_POP:
+ return V3_OP_POP;
+
+ case QX86_MNEMONIC_JLE:
+ return V3_OP_JLE;
+
+ case QX86_MNEMONIC_CALL:
+ return V3_OP_CALL;
+
+ case QX86_MNEMONIC_TEST:
+ return V3_OP_TEST;
+
+ case QX86_MNEMONIC_PUSH:
+ return V3_OP_PUSH;
+
+ case QX86_MNEMONIC_JAE:
+ return V3_OP_JAE;
+
+ case QX86_MNEMONIC_JMP:
+ return V3_OP_JMP;
+
+ case QX86_MNEMONIC_JNZ:
+ return V3_OP_JNZ;
+
+ case QX86_MNEMONIC_JZ:
+ return V3_OP_JZ;
+
+ case QX86_MNEMONIC_RET:
+ return V3_OP_RET;
+
+ case QX86_MNEMONIC_IMUL:
+ return V3_OP_IMUL;
+
+ case QX86_MNEMONIC_LEA:
+ return V3_OP_LEA;
+
+ case QX86_MNEMONIC_JL:
+ return V3_OP_JL;
+
+ case QX86_MNEMONIC_CMOVZ:
+ return V3_OP_CMOVZ;
+
+ case QX86_MNEMONIC_MOVSXD:
+ return V3_OP_MOVSXD;
+
+ case QX86_MNEMONIC_JNS:
+ return V3_OP_JNS;
+
+ case QX86_MNEMONIC_CMOVS:
+ return V3_OP_CMOVS;
+
+ case QX86_MNEMONIC_SHL:
+ return V3_OP_SHL;
+
+ case QX86_MNEMONIC_INT:
+ return V3_OP_INT;
default:
return V3_INVALID_OP;
static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg,
addr_t * v3_reg, uint_t * reg_len) {
- PrintDebug("qx86 Register: %s\n", qx86_rtab[qx86_reg].name);
+ PrintDebug(info->vm_info, info, "qx86 Register: %s\n", qx86_rinfo(qx86_reg)->name);
switch (qx86_reg) {
case QX86_REGISTER_INVALID:
*reg_len = 4;
return CTRL_REGISTER;
case QX86_REGISTER_CR8:
- *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
+ *v3_reg = (addr_t)&(info->ctrl_regs.apic_tpr);
*reg_len = 4;
return CTRL_REGISTER;