#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 * core,
- const qx86_insn * qx86_inst, struct x86_instr * instr)
-{
- int status = 0;
- PrintDebug(info->vm_info, info, "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 = core->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(info->vm_info, info, "Could not get destination memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- instr->dst_operand.type = MEM_OPERAND;
- instr->dst_operand.size = qx86_inst->operands[0].size;
-
-
- if((status = qx86_calculate_linear_address(qx86_inst, 1,
- (qx86_uint64*)&instr->src_operand.operand)) != QX86_SUCCESS) {
- PrintError(info->vm_info, info, "Could not get source memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- instr->src_operand.type = MEM_OPERAND;
- instr->src_operand.size = qx86_inst->operands[1].size;
-
- 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(info->vm_info, info, "Could not get destination memory operand: "
- "qx86_calculate_linear_address: %d\n", status);
- return -1;
- }
-
- instr->dst_operand.type = MEM_OPERAND;
- instr->dst_operand.size = qx86_inst->operands[0].size;
-
- // STOS reads from rax
- qx86_register_to_v3_reg(core,
- 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(info->vm_info, info, "Unhandled String OP\n");
- return -1;
- }
-
-
-#ifdef V3_CONFIG_DEBUG_DECODER
- V3_Print(info->vm_info, info, "Decoding Instr at %p\n", (void *)core->rip);
- v3_print_instr(instr);
- V3_Print(info->vm_info, info, "CS DB FLag=%x\n", core->segments.cs.db);
-#endif
-
-
- return 0;
-}
-
static int callback(void *data, int rindex, int subreg, unsigned char *value) {
void* reg_addr = 0;
uint_t reg_size;
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;
if (v3_reg_type == -1) {
PrintError(info->vm_info, info, "Operand %d is an Unhandled Operand: %s\n", op_num,
- qx86_rtab[qx86_op->u.r.rindex].name);
+ qx86_rinfo(qx86_op->u.r.rindex)->name);
v3_op->type = INVALID_OPERAND;
return -1;
} else if (v3_reg_type == SEGMENT_REGISTER) {
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));
instr->instr_length = qx86_inst.rawSize;
- if ((instr->op_type = get_opcode(&qx86_inst)) == V3_INVALID_OP) {
+ // 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_mtab[qx86_inst.mnemonic].name);
+ 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;
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(info->vm_info, info, "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(info->vm_info, info, "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;