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:
parent
89e3105bde
commit
43288ecdbd
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue