static void x86_uinst_parse_odep(struct x86_uinst_t *uinst, int index, struct x86_ctx_t *ctx) { struct x86_uinst_t *new_uinst; enum x86_dep_t mem_regular_dep; int mem_dep_size; int dep; /* Get dependence */ assert(index >= X86_UINST_MAX_IDEPS && index < X86_UINST_MAX_DEPS); dep = uinst->dep[index]; if (!dep) return; /* Memory dependence */ mem_dep_size = x86_uinst_mem_dep_size(uinst, index, ctx, &mem_regular_dep); if (mem_dep_size) { /* If uinst is 'move', just convert it into a 'store' */ if (uinst->opcode == x86_uinst_move) { /* Try to add 'ea' as input dependence */ if (x86_uinst_add_idep(uinst, x86_dep_ea)) { uinst->opcode = x86_uinst_store; uinst->dep[index] = x86_dep_none; uinst->address = x86_isa_effective_address(ctx); uinst->size = mem_dep_size; return; } } /* Store */ new_uinst = x86_uinst_create(); new_uinst->opcode = x86_uinst_store; new_uinst->idep[0] = x86_dep_ea; new_uinst->idep[1] = mem_regular_dep; new_uinst->address = x86_isa_effective_address(ctx); new_uinst->size = mem_dep_size; list_add(x86_uinst_list, new_uinst); /* Output dependence of instruction is x86_dep_data */ uinst->dep[index] = mem_regular_dep; return; } /* Regular dependence */ x86_uinst_parse_dep(uinst, index, ctx); }
static void x86_uinst_parse_idep(struct x86_uinst_t *uinst, int index, struct x86_ctx_t *ctx) { struct x86_uinst_t *new_uinst; enum x86_dep_t mem_regular_dep; int mem_dep_size; int dep; /* Get dependence */ assert(index >= 0 && index < X86_UINST_MAX_IDEPS); dep = uinst->dep[index]; if (!dep) return; /* Memory dependence */ mem_dep_size = x86_uinst_mem_dep_size(uinst, index, ctx, &mem_regular_dep); if (mem_dep_size) { /* If uinst is 'move', just convert it into a 'load' */ /* Replace 'rmXXX' by 'ea' dependence */ if (uinst->opcode == x86_uinst_move) { uinst->opcode = x86_uinst_load; uinst->dep[index] = x86_dep_ea; uinst->address = x86_isa_effective_address(ctx); uinst->size = mem_dep_size; return; } /* Load */ new_uinst = x86_uinst_create(); new_uinst->opcode = x86_uinst_load; new_uinst->idep[0] = x86_dep_ea; new_uinst->odep[0] = mem_regular_dep; new_uinst->address = x86_isa_effective_address(ctx); new_uinst->size = mem_dep_size; list_add(x86_uinst_list, new_uinst); /* Input dependence of instruction is converted into 'x86_dep_data' */ uinst->dep[index] = mem_regular_dep; return; } /* Regular dependence */ x86_uinst_parse_dep(uinst, index, ctx); }
static void x86_uinst_emit_effaddr(struct x86_uinst_t *uinst, int index, struct x86_ctx_t *ctx) { struct x86_uinst_t *new_uinst; /* Check if it is a memory dependence */ if (!x86_uinst_mem_dep_size(uinst, index, ctx, NULL)) return; /* Record occurrence */ x86_uinst_effaddr_emitted = 1; /* Emit 'effaddr' */ new_uinst = x86_uinst_create(); new_uinst->opcode = x86_uinst_effaddr; new_uinst->idep[0] = ctx->inst.segment ? ctx->inst.segment - x86_reg_es + x86_dep_es : x86_dep_none; new_uinst->idep[1] = ctx->inst.ea_base ? ctx->inst.ea_base - x86_reg_eax + x86_dep_eax : x86_dep_none; new_uinst->idep[2] = ctx->inst.ea_index ? ctx->inst.ea_index - x86_reg_eax + x86_dep_eax : x86_dep_none; new_uinst->odep[0] = x86_dep_ea; list_add(x86_uinst_list, new_uinst); }
void __x86_uinst_new_mem(struct x86_ctx_t *ctx, enum x86_uinst_opcode_t opcode, uint32_t address, int size, enum x86_dep_t idep0, enum x86_dep_t idep1, enum x86_dep_t idep2, enum x86_dep_t odep0, enum x86_dep_t odep1, enum x86_dep_t odep2, enum x86_dep_t odep3) { struct x86_uinst_t *uinst; int i; /* Do nothing for functional simulation */ if (x86_emu_kind == x86_emu_kind_functional) return; /* Create uinst */ uinst = x86_uinst_create(); uinst->opcode = opcode; uinst->idep[0] = idep0; uinst->idep[1] = idep1; uinst->idep[2] = idep2; uinst->odep[0] = odep0; uinst->odep[1] = odep1; uinst->odep[2] = odep2; uinst->odep[3] = odep3; uinst->address = address; uinst->size = size; /* Emit effective address computation if needed. */ for (i = 0; !x86_uinst_effaddr_emitted && i < X86_UINST_MAX_DEPS; i++) x86_uinst_emit_effaddr(uinst, i, ctx); /* Parse input dependences */ for (i = 0; i < X86_UINST_MAX_IDEPS; i++) x86_uinst_parse_idep(uinst, i, ctx); /* Add micro-instruction */ list_add(x86_uinst_list, uinst); /* Parse output dependences */ for (i = 0; i < X86_UINST_MAX_ODEPS; i++) x86_uinst_parse_odep(uinst, i + X86_UINST_MAX_IDEPS, ctx); }
void __x86_uinst_new_mem(X86Context *ctx, enum x86_uinst_opcode_t opcode, unsigned int address, int size, enum x86_dep_t idep0, enum x86_dep_t idep1, enum x86_dep_t idep2, enum x86_dep_t odep0, enum x86_dep_t odep1, enum x86_dep_t odep2, enum x86_dep_t odep3) { struct x86_uinst_t *uinst; int i; /* Create micro-instruction */ assert(arch_x86->sim_kind == arch_sim_kind_detailed); uinst = x86_uinst_create(); uinst->opcode = opcode; uinst->idep[0] = idep0; uinst->idep[1] = idep1; uinst->idep[2] = idep2; uinst->odep[0] = odep0; uinst->odep[1] = odep1; uinst->odep[2] = odep2; uinst->odep[3] = odep3; uinst->address = address; uinst->size = size; /* Emit effective address computation if needed. */ for (i = 0; !x86_uinst_effaddr_emitted && i < X86_UINST_MAX_DEPS; i++) x86_uinst_emit_effaddr(uinst, i, ctx); /* Parse input dependences */ for (i = 0; i < X86_UINST_MAX_IDEPS; i++) x86_uinst_parse_idep(uinst, i, ctx); /* Add micro-instruction */ list_add(x86_uinst_list, uinst); /* Parse output dependences */ for (i = 0; i < X86_UINST_MAX_ODEPS; i++) x86_uinst_parse_odep(uinst, i + X86_UINST_MAX_IDEPS, ctx); }