Simplify modrm code generation

Previously a callback was used to insert the read_imm call after
modrm_resolve. The new api uses two calls, allowing the removal of some
edge cases and deletion of extraneous functions
This commit is contained in:
Fabian 2018-03-08 14:21:14 -05:00
parent 89e3105bde
commit 43288ecdbd
5 changed files with 40 additions and 114 deletions

View file

@ -89,18 +89,14 @@ function gen_codegen_call(name, args)
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("()", "");
}
const args_count = args.length;
args = [].concat([`"${name}"`, name.length], args);
return gen_call(`gen_modrm${is_cb ? "_cb" : ""}_fn${args_count}`, args);
return [
gen_call(`gen_modrm_resolve`, ["modrm_byte"]),
gen_call(`gen_modrm_fn${args_count}`, args),
].join(" ");
}
function gen_modrm_mem_reg_split(name, gen_call_fns, mem_prefix_call, mem_args, reg_args, postfixes={})
@ -222,7 +218,7 @@ function gen_instruction_body(encodings, size)
modrm_resolve_prefix = gen_codegen_call(instruction_name + "_mem_pre");
}
const mem_args = ["modrm_byte"];
const mem_args = [];
const reg_args = ["modrm_byte & 7"];
const imm_read = gen_read_imm_call(case_, size);
@ -236,6 +232,7 @@ function gen_instruction_body(encodings, size)
{
console.assert(!case_.nonfaulting, "Unsupported: custom fixed_g instruction as nonfaulting");
instruction_name += "_jit";
mem_args.push("modrm_byte");
gen_call_fns.mem_call_fn = gen_call;
gen_call_fns.reg_call_fn = gen_call;
}
@ -325,7 +322,7 @@ function gen_instruction_body(encodings, size)
const imm_read = gen_read_imm_call(encoding, size);
const modrm_resolve_prefix = undefined;
const mem_args = ["modrm_byte", "modrm_byte >> 3 & 7"];
const mem_args = ["modrm_byte >> 3 & 7"];
const reg_args = ["modrm_byte & 7", "modrm_byte >> 3 & 7"];
if(imm_read)
@ -411,7 +408,7 @@ function gen_instruction_body(encodings, size)
modrm_resolve_prefix = gen_codegen_call(instruction_name + "_mem_pre");
}
const mem_args = ["modrm_byte", "modrm_byte >> 3 & 7"];
const mem_args = ["modrm_byte >> 3 & 7"];
const reg_args = ["modrm_byte & 7", "modrm_byte >> 3 & 7"];
if(imm_read)

View file

@ -53,23 +53,15 @@ Codegen.prototype.fn2 = function(fn, arg0, arg1)
Codegen.prototype.modrm_fn1 = function(fn, modrm_byte, arg)
{
this.str_input(fn);
this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length, modrm_byte, arg);
this.wm.exports["_gen_modrm_resolve"](modrm_byte);
this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length, arg);
};
Codegen.prototype.modrm_fn0 = function(fn, modrm_byte)
{
this.str_input(fn);
this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length, modrm_byte);
};
Codegen.prototype.resolve_modrm16 = function(modrm_byte)
{
this.wm.exports["_gen_resolve_modrm16"](modrm_byte);
};
Codegen.prototype.resolve_modrm32 = function(modrm_byte)
{
this.wm.exports["_gen_resolve_modrm32"](modrm_byte);
this.wm.exports["_gen_modrm_resolve"](modrm_byte);
this.wm.exports["_gen_modrm_fn1"](Codegen.STR_INPUT_OFFSET, fn.length);
};
Codegen.prototype.increment_instruction_pointer = function(n)

View file

@ -19,9 +19,6 @@ static Buffer instruction_body = {
.len = 0x1000,
};
// location in memory where we store the result of the computation for testing
#define RESULT_LOC 1600
extern bool is_asize_32(void);
extern int32_t read_imm8();
extern int32_t read_imm8s();
@ -357,13 +354,6 @@ static void jit_resolve_modrm16_(int32_t modrm_byte)
}
}
void gen_resolve_modrm16(int32_t modrm_byte)
{
push_u32(&instruction_body, RESULT_LOC);
jit_resolve_modrm16_(modrm_byte);
store_aligned_i32(&instruction_body);
}
#define MODRM_ENTRY32_0(row, seg, reg)\
MODRM_ENTRY(0x00 | (row), gen_modrm32_entry(seg, reg, 0))\
MODRM_ENTRY(0x40 | (row), gen_modrm32_entry(seg, reg, read_imm8s()))\
@ -498,18 +488,12 @@ static void jit_resolve_modrm32_(int32_t modrm_byte)
}
}
void gen_resolve_modrm32(int32_t modrm_byte)
{
push_i32(&instruction_body, RESULT_LOC);
jit_resolve_modrm32_(modrm_byte);
store_aligned_i32(&instruction_body);
}
#undef MODRM_ENTRY
void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0, int32_t arg1)
// This function leaves a value on the wasm stack, to be consumed by one of the
// gen_modrm_fn* functions below
void gen_modrm_resolve(int32_t modrm_byte)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0, arg1 )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
@ -518,6 +502,11 @@ void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t a
{
jit_resolve_modrm16_(modrm_byte);
}
}
void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1)
{
// generates: fn( _, arg0, arg1 )
push_i32(&instruction_body, arg0);
push_i32(&instruction_body, arg1);
@ -526,36 +515,9 @@ void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t a
call_fn(&instruction_body, fn_idx);
}
void gen_modrm_cb_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0, int32_t (*arg1_cb) (void))
void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0, arg1_cb() )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
push_i32(&instruction_body, arg0);
push_i32(&instruction_body, arg1_cb());
int32_t fn_idx = get_fn_index(fn, fn_len, FN3_TYPE_INDEX);
call_fn(&instruction_body, fn_idx);
}
void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0 )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
// generates: fn( _, arg0 )
push_i32(&instruction_body, arg0);
@ -563,35 +525,9 @@ void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t a
call_fn(&instruction_body, fn_idx);
}
void gen_modrm_cb_fn1(char const* fn, uint8_t fn_len, int32_t modrm_byte, int (*arg0_cb) (void))
void gen_modrm_fn0(char const* fn, uint8_t fn_len)
{
// generates: fn( modrm_resolve( modrm_byte ), arg0_cb() )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
push_i32(&instruction_body, arg0_cb());
int32_t fn_idx = get_fn_index(fn, fn_len, FN2_TYPE_INDEX);
call_fn(&instruction_body, fn_idx);
}
void gen_modrm_fn0(char const* fn, uint8_t fn_len, int32_t modrm_byte)
{
// generates: fn( modrm_resolve( modrm_byte ) )
if(is_asize_32())
{
jit_resolve_modrm32_(modrm_byte);
}
else
{
jit_resolve_modrm16_(modrm_byte);
}
// generates: fn( _ )
int32_t fn_idx = get_fn_index(fn, fn_len, FN1_TYPE_INDEX);
call_fn(&instruction_body, fn_idx);

View file

@ -31,6 +31,7 @@ void gen_fn1(char const* fn, uint8_t fn_len, int32_t arg0);
void gen_fn1_reg16(char const* fn, uint8_t fn_len, int32_t reg);
void gen_fn1_reg32s(char const* fn, uint8_t fn_len, int32_t reg);
void gen_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1);
void gen_fn3(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1, int32_t arg2);
void gen_fn0_ret(char const* fn, uint8_t fn_len);
@ -38,16 +39,12 @@ void gen_if_void();
void gen_else();
void gen_block_end();
void gen_modrm_fn0(char const* fn, uint8_t fn_len, int32_t modrm_byte);
void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0);
void gen_resolve_modrm16(int32_t modrm_byte);
void gen_resolve_modrm32(int32_t modrm_byte);
void gen_relative_jump(int32_t n);
void gen_fn3(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1, int32_t arg2);
void gen_modrm_resolve(int32_t modrm_byte);
void gen_modrm_fn0(char const* fn, uint8_t fn_len);
void gen_modrm_fn1(char const* fn, uint8_t fn_len, int32_t arg0);
void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t arg0, int32_t arg1);
void gen_modrm_cb_fn1(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t (*) (void));
void gen_modrm_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t arg0, int32_t arg1);
void gen_modrm_cb_fn2(char const* fn, uint8_t fn_len, int32_t modrm_byte, int32_t, int32_t (*) (void));
void gen_relative_jump(int32_t n);
void gen_set_previous_eip_offset_from_eip(int32_t n);
void gen_set_previous_eip(void);

View file

@ -304,11 +304,13 @@ void push16_mem_jit(int32_t modrm_byte)
{
if(*stack_size_32)
{
gen_modrm_fn0("push16_ss32_mem", 15, modrm_byte);
gen_modrm_resolve(modrm_byte);
gen_modrm_fn0("push16_ss32_mem", 15);
}
else
{
gen_modrm_fn0("push16_ss16_mem", 15, modrm_byte);
gen_modrm_resolve(modrm_byte);
gen_modrm_fn0("push16_ss16_mem", 15);
}
}
@ -372,11 +374,13 @@ void push32_mem_jit(int32_t modrm_byte)
{
if(*stack_size_32)
{
gen_modrm_fn0("push32_ss32_mem", 15, modrm_byte);
gen_modrm_resolve(modrm_byte);
gen_modrm_fn0("push32_ss32_mem", 15);
}
else
{
gen_modrm_fn0("push32_ss16_mem", 15, modrm_byte);
gen_modrm_resolve(modrm_byte);
gen_modrm_fn0("push32_ss16_mem", 15);
}
}