Generate _jit_[reg,mem] calls for custom modrm instructions

This allows for a cleaner separation for custom modrm instructions
This commit is contained in:
Amaan Cheval 2018-02-26 11:17:40 +05:30 committed by Fabian
parent a09ace9c95
commit 21909fd5fd
4 changed files with 71 additions and 65 deletions

View file

@ -86,37 +86,39 @@ function gen_codegen_call(name, args)
return gen_call(`gen_fn${args_count}`, args);
}
function gen_codegen_call_modrm(name, args, is_cb)
function gen_codegen_call_modrm(name, args)
{
args = (args || []).slice();
const args_count = args.length - 1; // minus 1 for the modrm_byte
let is_cb = false;
if(args[args.length-1].endsWith("()"))
{
is_cb = true;
args = args.slice();
args[args.length-1] = args[args.length-1].replace("()", "");
}
args = [].concat([`"${name}"`, name.length], args);
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, postfixes={})
function gen_modrm_mem_reg_split(name, gen_call_fns, mem_prefix_call, mem_args, reg_args, postfixes={})
{
let cb = false;
const { mem_call_fn, reg_call_fn } = gen_call_fns;
const { mem_postfix=[], reg_postfix=[] } = postfixes;
if(mem_args[mem_args.length-1].endsWith("()"))
{
cb = true;
mem_args = mem_args.slice();
mem_args[mem_args.length-1] = mem_args[mem_args.length-1].replace("()", "");
}
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)])
.concat([mem_call_fn(`${name}_mem`, mem_args)])
.concat(mem_postfix),
}],
else_block: {
body: [
gen_codegen_call(`${name}_reg`, reg_args)
reg_call_fn(`${name}_reg`, reg_args)
].concat(reg_postfix),
},
};
@ -185,6 +187,12 @@ function gen_instruction_body(encodings, size)
const instruction_postfix = encoding.jump ? ["instr_flags |= JIT_INSTR_JUMP_FLAG;"] : [];
// May be overridden for custom encodings
const gen_call_fns = {
mem_call_fn: gen_codegen_call_modrm,
reg_call_fn: gen_codegen_call,
};
if(encoding.fixed_g !== undefined)
{
// instruction with modrm byte where the middle 3 bits encode the instruction
@ -204,26 +212,8 @@ function gen_instruction_body(encodings, size)
condition: "modrm_byte >> 3 & 7",
cases: cases.map(case_ => {
const fixed_g = case_.fixed_g;
let instruction_name = make_instruction_name(case_, size, undefined);
const instruction_postfix = case_.jump ? ["instr_flags |= JIT_INSTR_JUMP_FLAG;"] : [];
if(case_.custom)
{
console.assert(!case_.nonfaulting, "Unsupported: custom fixed_g instruction as nonfaulting");
const instruction_name = make_instruction_name(case_, size) + "_jit";
const imm_read = gen_read_imm_call(case_, size);
const args = ["modrm_byte"];
if(imm_read)
{
args.push(imm_read);
}
return {
conditions: [fixed_g],
body: [gen_call(instruction_name, args)].concat(instruction_postfix),
};
}
const instruction_name = make_instruction_name(case_, size, undefined);
let modrm_resolve_prefix = undefined;
@ -242,28 +232,45 @@ function gen_instruction_body(encodings, size)
reg_args.push(imm_read);
}
if(case_.custom)
{
console.assert(!case_.nonfaulting, "Unsupported: custom fixed_g instruction as nonfaulting");
instruction_name += "_jit";
gen_call_fns.mem_call_fn = gen_call;
gen_call_fns.reg_call_fn = gen_call;
}
if(has_66 || has_F2 || has_F3)
{
const if_blocks = [];
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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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,
gen_call_fns,
modrm_resolve_prefix,
mem_args,
reg_args,
{}
)
],
};
return {
@ -283,6 +290,7 @@ function gen_instruction_body(encodings, size)
const body = [
gen_modrm_mem_reg_split(
instruction_name,
gen_call_fns,
modrm_resolve_prefix,
mem_args,
reg_args,
@ -330,22 +338,31 @@ 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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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, gen_call_fns, modrm_resolve_prefix, mem_args, reg_args, {})];
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),
gen_call_fns,
modrm_resolve_prefix,
mem_args,
reg_args,
{}
)
],
};
return [
@ -407,6 +424,7 @@ function gen_instruction_body(encodings, size)
"int32_t modrm_byte = read_imm8();",
gen_modrm_mem_reg_split(
instruction_name,
gen_call_fns,
modrm_resolve_prefix,
mem_args,
reg_args,

View file

@ -1449,7 +1449,8 @@ void instr16_FF_5_mem(int32_t addr)
diverged();
}
DEFINE_MODRM_INSTR1_READ16(instr16_FF_6, push16(___))
void instr16_FF_6_jit(int32_t modrm_byte) { push16_modrm_jit(modrm_byte); }
void instr16_FF_6_jit_reg(int32_t reg) { push16_reg_jit(reg); }
void instr16_FF_6_jit_mem(int32_t modrm_byte) { push16_mem_jit(modrm_byte); }
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_0, inc32(___))
DEFINE_MODRM_INSTR1_READ_WRITE_32(instr32_FF_1, dec32(___))
@ -1520,7 +1521,8 @@ void instr32_FF_5_mem(int32_t addr)
diverged();
}
DEFINE_MODRM_INSTR1_READ32(instr32_FF_6, push32(___))
void instr32_FF_6_jit(int32_t modrm_byte) { push32_modrm_jit(modrm_byte); }
void instr32_FF_6_jit_reg(int32_t reg) { push32_reg_jit(reg); }
void instr32_FF_6_jit_mem(int32_t modrm_byte) { push32_mem_jit(modrm_byte); }
void run_instruction(int32_t opcode)
{

View file

@ -301,22 +301,15 @@ void push16_imm_jit(int32_t imm)
}
}
void push16_modrm_jit(int32_t modrm_byte)
void push16_mem_jit(int32_t modrm_byte)
{
if(modrm_byte < 0xC0)
if(*stack_size_32)
{
if(*stack_size_32)
{
gen_modrm_fn0("push16_ss32_mem", 15, modrm_byte);
}
else
{
gen_modrm_fn0("push16_ss16_mem", 15, modrm_byte);
}
gen_modrm_fn0("push16_ss32_mem", 15, modrm_byte);
}
else
{
push16_reg_jit(modrm_byte & 7);
gen_modrm_fn0("push16_ss16_mem", 15, modrm_byte);
}
}
@ -376,22 +369,15 @@ void push32_imm_jit(int32_t imm)
}
}
void push32_modrm_jit(int32_t modrm_byte)
void push32_mem_jit(int32_t modrm_byte)
{
if(modrm_byte < 0xC0)
if(*stack_size_32)
{
if(*stack_size_32)
{
gen_modrm_fn0("push32_ss32_mem", 15, modrm_byte);
}
else
{
gen_modrm_fn0("push32_ss16_mem", 15, modrm_byte);
}
gen_modrm_fn0("push32_ss32_mem", 15, modrm_byte);
}
else
{
push32_reg_jit(modrm_byte & 7);
gen_modrm_fn0("push32_ss16_mem", 15, modrm_byte);
}
}

View file

@ -48,7 +48,7 @@ void push16_ss32_mem(int32_t imm16);
void push16(int32_t imm16);
void push16_reg_jit(int32_t reg);
void push16_imm_jit(int32_t imm);
void push16_modrm_jit(int32_t modrm_byte);
void push16_mem_jit(int32_t modrm_byte);
void push32_ss16(int32_t imm32);
void push32_ss32(int32_t imm32);
void push32_ss16_mem(int32_t imm32);
@ -56,7 +56,7 @@ void push32_ss32_mem(int32_t imm32);
void push32(int32_t imm32);
void push32_reg_jit(int32_t reg);
void push32_imm_jit(int32_t imm);
void push32_modrm_jit(int32_t modrm_byte);
void push32_mem_jit(int32_t modrm_byte);
int32_t pop16(void);
void pop16_reg_jit(int32_t reg);
int32_t pop32_ss16(void);