Skip to content

Commit

Permalink
Update generate_jit and enable JIT's nonfaulting eip optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
AmaanC authored and copy committed Jul 22, 2020
1 parent bc03a26 commit d5212a1
Show file tree
Hide file tree
Showing 4 changed files with 479 additions and 13 deletions.
51 changes: 38 additions & 13 deletions gen/generate_jit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const encodings = require("./x86_table");
const c_ast = require("./c_ast");
const { hex } = require("./util");

const APPEND_NONFAULTING_FLAG = "flags |= JIT_INSTR_NONFAULTING_FLAG;";

gen_table();


Expand Down Expand Up @@ -74,7 +76,7 @@ function gen_codegen_call_modrm(name, args, is_cb)
return gen_call(`gen_modrm${is_cb ? "_cb" : ""}_fn${args_count}`, args);
}

function gen_modrm_mem_reg_split(name, mem_prefix_call, mem_args, reg_args)
function gen_modrm_mem_reg_split(name, mem_prefix_call, mem_args, reg_args, encoding)
{
let cb = false;

Expand All @@ -85,16 +87,22 @@ function gen_modrm_mem_reg_split(name, mem_prefix_call, mem_args, reg_args)
mem_args[mem_args.length-1] = mem_args[mem_args.length-1].replace("()", "");
}

const lea_special_case = encoding.opcode === 0x8D;
const mem_postfix = (encoding.nonfaulting && lea_special_case) ? [APPEND_NONFAULTING_FLAG] : [];
const reg_postfix = (encoding.nonfaulting && !lea_special_case) ? [APPEND_NONFAULTING_FLAG] : [];

return {
type: "if-else",
if_blocks: [{
condition: "modrm_byte < 0xC0",
body: (mem_prefix_call ? [mem_prefix_call] : []).concat([gen_codegen_call_modrm(`${name}_mem`, mem_args, cb)]),
body: (mem_prefix_call ? [mem_prefix_call] : [])
.concat([gen_codegen_call_modrm(`${name}_mem`, mem_args, cb)])
.concat(mem_postfix),
}],
else_block: {
body: [
gen_codegen_call(`${name}_reg`, reg_args)
],
].concat(reg_postfix),
},
};
}
Expand Down Expand Up @@ -133,6 +141,15 @@ function gen_instruction_body(encodings, size)
if(has_66 || has_F2 || has_F3)
{
console.assert((encoding.opcode & 0xFF00) === 0x0F00);
// Leaving unsupported because:
// 1. Instructions that use these prefixes are usually faulting
// 2. It would need a refactor to allow us to pass the correct prefixed encoding object to
// where the nonfaulting flags are set
console.assert(
!encodings.some(e => e.nonfaulting),
"Unsupported: marking instruction with 66/f2/f3 prefix variant as nonfaulting. Opcode: 0x"
+ hex(encoding.opcode)
);
}

const instruction_postfix = encoding.jump ? ["flags |= JIT_INSTR_JUMP_FLAG;"] : [];
Expand Down Expand Up @@ -182,22 +199,22 @@ function gen_instruction_body(encodings, size)

if(has_66) {
const name = make_instruction_name(case_, size, 0x66);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, case_)];
if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, });
}
if(has_F2) {
const name = make_instruction_name(case_, size, 0xF2);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, case_)];
if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, });
}
if(has_F3) {
const name = make_instruction_name(case_, size, 0xF3);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, case_)];
if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, });
}

const else_block = {
body: [gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args)],
body: [gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args, case_)],
};

return {
Expand All @@ -215,7 +232,7 @@ function gen_instruction_body(encodings, size)
else
{
const body = [
gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args)
gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args, case_)
].concat(instruction_postfix);

return {
Expand Down Expand Up @@ -258,22 +275,22 @@ function gen_instruction_body(encodings, size)

if(has_66) {
const name = make_instruction_name(encoding, size, 0x66);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, encoding)];
if_blocks.push({ condition: "prefixes_ & PREFIX_66", body, });
}
if(has_F2) {
const name = make_instruction_name(encoding, size, 0xF2);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, encoding)];
if_blocks.push({ condition: "prefixes_ & PREFIX_F2", body, });
}
if(has_F3) {
const name = make_instruction_name(encoding, size, 0xF3);
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args)];
const body = [gen_modrm_mem_reg_split(name, modrm_resolve_prefix, mem_args, reg_args, encoding)];
if_blocks.push({ condition: "prefixes_ & PREFIX_F3", body, });
}

const else_block = {
body: [gen_modrm_mem_reg_split(make_instruction_name(encoding, size), modrm_resolve_prefix, mem_args, reg_args)],
body: [gen_modrm_mem_reg_split(make_instruction_name(encoding, size), modrm_resolve_prefix, mem_args, reg_args, encoding)],
};

return [
Expand Down Expand Up @@ -306,6 +323,7 @@ function gen_instruction_body(encodings, size)
return [
"int32_t modrm_byte = read_imm8();",
gen_codegen_call(instruction_name, ["modrm_byte & 7", "modrm_byte >> 3 & 7"]),
encoding.nonfaulting ? APPEND_NONFAULTING_FLAG : "",
].concat(instruction_postfix);
}
else
Expand All @@ -328,12 +346,14 @@ function gen_instruction_body(encodings, size)

return [
"int32_t modrm_byte = read_imm8();",
gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args),
gen_modrm_mem_reg_split(instruction_name, modrm_resolve_prefix, mem_args, reg_args, encoding),
].concat(instruction_postfix);
}
}
else if(encoding.prefix || encoding.custom)
{
console.assert(!encoding.nonfaulting, "Prefix/custom instructions cannot be marked as nonfaulting.");

const instruction_name = make_instruction_name(encoding, size) + "_jit";
const imm_read = gen_read_imm_call(encoding, size);
const args = [];
Expand Down Expand Up @@ -372,6 +392,11 @@ function gen_instruction_body(encodings, size)
args.push("read_imm8()");
}

if(encoding.nonfaulting)
{
instruction_postfix.push(APPEND_NONFAULTING_FLAG);
}

return [gen_codegen_call(instruction_name, args)].concat(instruction_postfix);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/native/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ static void jit_generate(int32_t address_hash, uint32_t phys_addr, struct code_c
gen_patch_increment_instruction_pointer(eip_delta);
}
#else
UNUSED(eip_delta);
gen_set_previous_eip();
gen_increment_instruction_pointer(instruction_length);
#endif
Expand Down
Loading

0 comments on commit d5212a1

Please sign in to comment.