Cleanup of codegen api

This commit is contained in:
Fabian 2018-08-21 21:06:52 -05:00
parent ca36680d52
commit 1d24c5952d
6 changed files with 260 additions and 278 deletions

View file

@ -15,42 +15,42 @@ extern "C" {
pub fn gen_set_previous_eip_offset_from_eip(builder: &mut WasmBuilder, n: u32) {
let cs = &mut builder.code_section;
cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip
cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip
cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip
if n != 0 {
cs.push_i32(n as i32);
cs.const_i32(n as i32);
cs.add_i32(); // add constant to ip value
}
cs.store_aligned_i32(); // store it as previous ip
cs.store_aligned_i32(0); // store it as previous ip
}
pub fn gen_increment_instruction_pointer(builder: &mut WasmBuilder, n: u32) {
let cs = &mut builder.code_section;
cs.push_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip
cs.const_i32(global_pointers::INSTRUCTION_POINTER as i32); // store address of ip
cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip
cs.push_i32(n as i32);
cs.const_i32(n as i32);
cs.add_i32();
cs.store_aligned_i32(); // store it back in
cs.store_aligned_i32(0); // store it back in
}
pub fn gen_set_previous_eip(builder: &mut WasmBuilder) {
let cs = &mut builder.code_section;
cs.push_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip
cs.const_i32(global_pointers::PREVIOUS_IP as i32); // store address of previous ip
cs.load_aligned_i32(global_pointers::INSTRUCTION_POINTER); // load ip
cs.store_aligned_i32(); // store it as previous ip
cs.store_aligned_i32(0); // store it as previous ip
}
pub fn gen_relative_jump(builder: &mut WasmBuilder, n: i32) {
// add n to instruction_pointer (without setting the offset as above)
let instruction_body = &mut builder.instruction_body;
instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
instruction_body.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
instruction_body.push_i32(n);
instruction_body.const_i32(n);
instruction_body.add_i32();
instruction_body.store_aligned_i32();
instruction_body.store_aligned_i32(0);
}
pub fn gen_increment_variable(builder: &mut WasmBuilder, variable_address: u32, n: i32) {
@ -65,12 +65,33 @@ pub fn gen_increment_mem32(builder: &mut WasmBuilder, addr: u32) {
builder.code_section.increment_mem32(addr)
}
pub fn gen_get_reg8(builder: &mut WasmBuilder, r: u32) {
builder
.instruction_body
.const_i32(global_pointers::get_reg8_offset(r) as i32);
builder.instruction_body.load_u8_from_stack(0);
}
pub fn gen_get_reg16(builder: &mut WasmBuilder, r: u32) {
builder
.instruction_body
.const_i32(global_pointers::get_reg16_offset(r) as i32);
builder.instruction_body.load_aligned_u16_from_stack(0);
}
pub fn gen_get_reg32(builder: &mut WasmBuilder, r: u32) {
builder
.instruction_body
.const_i32(global_pointers::get_reg32_offset(r) as i32);
builder.instruction_body.load_aligned_i32_from_stack(0);
}
/// sign-extend a byte value on the stack and leave it on the stack
pub fn sign_extend_i8(builder: &mut WasmBuilder) {
builder.instruction_body.push_i32(24);
builder.instruction_body.const_i32(24);
builder.instruction_body.shl_i32();
builder.instruction_body.push_i32(24);
builder.instruction_body.shr_i32();
builder.instruction_body.const_i32(24);
builder.instruction_body.shr_s_i32();
}
pub fn gen_fn0_const(ctx: &mut JitContext, name: &str) {
@ -87,7 +108,7 @@ pub fn gen_fn0_const_ret(builder: &mut WasmBuilder, name: &str) {
pub fn gen_fn1_const(ctx: &mut JitContext, name: &str, arg0: u32) {
let builder = &mut ctx.builder;
let fn_idx = builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX);
builder.instruction_body.push_i32(arg0 as i32);
builder.instruction_body.const_i32(arg0 as i32);
builder.instruction_body.call_fn(fn_idx);
}
@ -100,8 +121,8 @@ pub fn gen_call_fn1_ret(builder: &mut WasmBuilder, name: &str) {
pub fn gen_fn2_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) {
let builder = &mut ctx.builder;
let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX);
builder.instruction_body.push_i32(arg0 as i32);
builder.instruction_body.push_i32(arg1 as i32);
builder.instruction_body.const_i32(arg0 as i32);
builder.instruction_body.const_i32(arg1 as i32);
builder.instruction_body.call_fn(fn_idx);
}
@ -114,9 +135,9 @@ pub fn gen_call_fn2(builder: &mut WasmBuilder, name: &str) {
pub fn gen_fn3_const(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32, arg2: u32) {
let builder = &mut ctx.builder;
let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX);
builder.instruction_body.push_i32(arg0 as i32);
builder.instruction_body.push_i32(arg1 as i32);
builder.instruction_body.push_i32(arg2 as i32);
builder.instruction_body.const_i32(arg0 as i32);
builder.instruction_body.const_i32(arg1 as i32);
builder.instruction_body.const_i32(arg2 as i32);
builder.instruction_body.call_fn(fn_idx);
}
@ -131,7 +152,7 @@ pub fn gen_modrm_fn1(ctx: &mut JitContext, name: &str, arg0: u32) {
// generates: fn( _, arg0 )
let builder = &mut ctx.builder;
let fn_idx = builder.get_fn_idx(name, module_init::FN2_TYPE_INDEX);
builder.instruction_body.push_i32(arg0 as i32);
builder.instruction_body.const_i32(arg0 as i32);
builder.instruction_body.call_fn(fn_idx);
}
@ -139,8 +160,8 @@ pub fn gen_modrm_fn2(ctx: &mut JitContext, name: &str, arg0: u32, arg1: u32) {
// generates: fn( _, arg0, arg1 )
let builder = &mut ctx.builder;
let fn_idx = builder.get_fn_idx(name, module_init::FN3_TYPE_INDEX);
builder.instruction_body.push_i32(arg0 as i32);
builder.instruction_body.push_i32(arg1 as i32);
builder.instruction_body.const_i32(arg0 as i32);
builder.instruction_body.const_i32(arg1 as i32);
builder.instruction_body.call_fn(fn_idx);
}
@ -151,10 +172,8 @@ pub fn gen_set_reg8_r(ctx: &mut JitContext, dest: u32, src: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg8_offset(dest) as i32);
builder
.instruction_body
.load_u8(global_pointers::get_reg8_offset(src));
.const_i32(global_pointers::get_reg8_offset(dest) as i32);
gen_get_reg8(builder, src);
builder.instruction_body.store_u8(0);
}
pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) {
@ -162,22 +181,18 @@ pub fn gen_set_reg16_r(ctx: &mut JitContext, dest: u32, src: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(dest) as i32);
builder
.instruction_body
.load_aligned_u16(global_pointers::get_reg16_offset(src));
builder.instruction_body.store_aligned_u16();
.const_i32(global_pointers::get_reg16_offset(dest) as i32);
gen_get_reg16(builder, src);
builder.instruction_body.store_aligned_u16(0);
}
pub fn gen_set_reg32_r(ctx: &mut JitContext, dest: u32, src: u32) {
// generates: reg32s[r_dest] = reg32s[r_src]
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(dest) as i32);
builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg32_offset(src));
builder.instruction_body.store_aligned_i32();
.const_i32(global_pointers::get_reg32_offset(dest) as i32);
gen_get_reg32(builder, src);
builder.instruction_body.store_aligned_i32(0);
}
pub fn gen_safe_read8(ctx: &mut JitContext) { gen_safe_read(ctx, BitSize::BYTE) }
@ -202,11 +217,11 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
let address_local = builder.tee_new_local();
// Pseudo: base_on_stack = (uint32_t)address >> 12;
builder.instruction_body.push_i32(12);
builder.instruction_body.shr_u32();
builder.instruction_body.const_i32(12);
builder.instruction_body.shr_u_i32();
// scale index
builder.instruction_body.push_i32(2);
builder.instruction_body.const_i32(2);
builder.instruction_body.shl_i32();
// Pseudo: entry = tlb_data[base_on_stack];
@ -217,22 +232,22 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
// Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID &&
// (bitsize == 8 ? true : (address & 0xFFF) <= (0x1000 - (bitsize / 8)));
builder.instruction_body.push_i32(
builder.instruction_body.const_i32(
(0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER }))
as i32,
);
builder.instruction_body.and_i32();
builder.instruction_body.push_i32(TLB_VALID as i32);
builder.instruction_body.const_i32(TLB_VALID as i32);
builder.instruction_body.eq_i32();
if bits != BitSize::BYTE {
builder.instruction_body.get_local(&address_local);
builder.instruction_body.push_i32(0xFFF);
builder.instruction_body.const_i32(0xFFF);
builder.instruction_body.and_i32();
builder
.instruction_body
.push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
.const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
builder.instruction_body.le_i32();
builder.instruction_body.and_i32();
@ -242,7 +257,7 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
// if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]);
builder.instruction_body.if_i32();
builder.instruction_body.get_local(&entry_local);
builder.instruction_body.push_i32(!0xFFF);
builder.instruction_body.const_i32(!0xFFF);
builder.instruction_body.and_i32();
builder.instruction_body.get_local(&address_local);
builder.instruction_body.xor_i32();
@ -275,19 +290,19 @@ fn gen_safe_read(ctx: &mut JitContext, bits: BitSize) {
builder
.instruction_body
.push_i32(global_pointers::PREVIOUS_IP as i32);
.const_i32(global_pointers::PREVIOUS_IP as i32);
builder
.instruction_body
.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
builder.instruction_body.push_i32(!0xFFF);
builder.instruction_body.const_i32(!0xFFF);
builder.instruction_body.and_i32();
builder
.instruction_body
.push_i32(ctx.start_of_current_instruction as i32 & 0xFFF);
.const_i32(ctx.start_of_current_instruction as i32 & 0xFFF);
builder.instruction_body.or_i32();
builder.instruction_body.store_aligned_i32();
builder.instruction_body.store_aligned_i32(0);
builder.instruction_body.get_local(&address_local);
match bits {
@ -329,11 +344,11 @@ fn gen_safe_write(
builder.instruction_body.get_local(&address_local);
// Pseudo: base_on_stack = (uint32_t)address >> 12;
builder.instruction_body.push_i32(12);
builder.instruction_body.shr_u32();
builder.instruction_body.const_i32(12);
builder.instruction_body.shr_u_i32();
// scale index
builder.instruction_body.push_i32(2);
builder.instruction_body.const_i32(2);
builder.instruction_body.shl_i32();
// Pseudo: entry = tlb_data[base_on_stack];
@ -346,19 +361,19 @@ fn gen_safe_write(
// (address & 0xFFF) <= (0x1000 - bitsize / 8));
builder
.instruction_body
.push_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32);
.const_i32((0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32);
builder.instruction_body.and_i32();
builder.instruction_body.push_i32(TLB_VALID as i32);
builder.instruction_body.const_i32(TLB_VALID as i32);
builder.instruction_body.eq_i32();
if bits != BitSize::BYTE {
builder.instruction_body.get_local(&address_local);
builder.instruction_body.push_i32(0xFFF);
builder.instruction_body.const_i32(0xFFF);
builder.instruction_body.and_i32();
builder
.instruction_body
.push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
.const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
builder.instruction_body.le_i32();
builder.instruction_body.and_i32();
@ -371,7 +386,7 @@ fn gen_safe_write(
builder.instruction_body.if_void();
builder.instruction_body.get_local(&entry_local);
builder.instruction_body.push_i32(!0xFFF);
builder.instruction_body.const_i32(!0xFFF);
builder.instruction_body.and_i32();
builder.instruction_body.get_local(&address_local);
builder.instruction_body.xor_i32();
@ -409,19 +424,19 @@ fn gen_safe_write(
builder
.instruction_body
.push_i32(global_pointers::PREVIOUS_IP as i32);
.const_i32(global_pointers::PREVIOUS_IP as i32);
builder
.instruction_body
.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
builder.instruction_body.push_i32(!0xFFF);
builder.instruction_body.const_i32(!0xFFF);
builder.instruction_body.and_i32();
builder
.instruction_body
.push_i32(ctx.start_of_current_instruction as i32 & 0xFFF);
.const_i32(ctx.start_of_current_instruction as i32 & 0xFFF);
builder.instruction_body.or_i32();
builder.instruction_body.store_aligned_i32();
builder.instruction_body.store_aligned_i32(0);
builder.instruction_body.get_local(&address_local);
builder.instruction_body.get_local(&value_local);
@ -450,22 +465,22 @@ fn gen_safe_write(
pub fn gen_clear_prefixes(ctx: &mut JitContext) {
let instruction_body = &mut ctx.builder.instruction_body;
instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes
instruction_body.push_i32(0);
instruction_body.store_aligned_i32();
instruction_body.const_i32(global_pointers::PREFIXES as i32); // load address of prefixes
instruction_body.const_i32(0);
instruction_body.store_aligned_i32(0);
}
pub fn gen_add_prefix_bits(ctx: &mut JitContext, mask: u32) {
dbg_assert!(mask < 0x100);
let instruction_body = &mut ctx.builder.instruction_body;
instruction_body.push_i32(global_pointers::PREFIXES as i32); // load address of prefixes
instruction_body.const_i32(global_pointers::PREFIXES as i32); // load address of prefixes
instruction_body.load_aligned_i32(global_pointers::PREFIXES); // load old value
instruction_body.push_i32(mask as i32);
instruction_body.const_i32(mask as i32);
instruction_body.or_i32();
instruction_body.store_aligned_i32();
instruction_body.store_aligned_i32(0);
}
pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) {
@ -480,31 +495,29 @@ pub fn gen_jmp_rel16(ctx: &mut JitContext, rel16: u16) {
{
let instruction_body = &mut ctx.builder.instruction_body;
instruction_body.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
instruction_body.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
instruction_body.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
instruction_body.get_local(&local);
instruction_body.sub_i32();
instruction_body.push_i32(rel16 as i32);
instruction_body.const_i32(rel16 as i32);
instruction_body.add_i32();
instruction_body.push_i32(0xFFFF);
instruction_body.const_i32(0xFFFF);
instruction_body.and_i32();
instruction_body.get_local(&local);
instruction_body.add_i32();
instruction_body.store_aligned_i32();
instruction_body.store_aligned_i32(0);
}
ctx.builder.free_local(local);
}
pub fn gen_pop16_ss16(ctx: &mut JitContext) {
// sp = segment_offsets[SS] + reg16[SP] (or just reg16[SP] if has_flat_segmentation)
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg16_offset(regs::SP));
gen_get_reg16(ctx.builder, regs::SP);
let sp_local = ctx.builder.tee_new_local();
if !ctx.cpu.has_flat_segmentation() {
@ -520,11 +533,11 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) {
// reg16[SP] += 2;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
.const_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
ctx.builder.instruction_body.get_local(&sp_local);
ctx.builder.instruction_body.push_i32(2);
ctx.builder.instruction_body.const_i32(2);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_u16(0);
ctx.builder.free_local(sp_local);
@ -533,9 +546,7 @@ pub fn gen_pop16_ss16(ctx: &mut JitContext) {
pub fn gen_pop16_ss32(ctx: &mut JitContext) {
// esp = segment_offsets[SS] + reg32s[ESP] (or just reg32s[ESP] if has_flat_segmentation)
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP));
gen_get_reg32(ctx.builder, regs::ESP);
let esp_local = ctx.builder.tee_new_local();
if !ctx.cpu.has_flat_segmentation() {
@ -551,11 +562,11 @@ pub fn gen_pop16_ss32(ctx: &mut JitContext) {
// reg32s[ESP] += 2;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
.const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
ctx.builder.instruction_body.get_local(&esp_local);
ctx.builder.instruction_body.push_i32(2);
ctx.builder.instruction_body.const_i32(2);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
ctx.builder.free_local(esp_local);
// return value is already on stack
@ -572,9 +583,7 @@ pub fn gen_pop16(ctx: &mut JitContext) {
pub fn gen_pop32s_ss16(ctx: &mut JitContext) {
// sp = reg16[SP]
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg16_offset(regs::SP));
gen_get_reg16(ctx.builder, regs::SP);
let local_sp = ctx.builder.tee_new_local();
// result = safe_read32s(segment_offsets[SS] + sp) (or just sp if has_flat_segmentation)
@ -590,11 +599,11 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) {
// reg16[SP] = sp + 4;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
.const_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
ctx.builder.instruction_body.get_local(&local_sp);
ctx.builder.instruction_body.push_i32(4);
ctx.builder.instruction_body.const_i32(4);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_u16(0);
ctx.builder.free_local(local_sp);
@ -603,9 +612,7 @@ pub fn gen_pop32s_ss16(ctx: &mut JitContext) {
pub fn gen_pop32s_ss32(ctx: &mut JitContext) {
// esp = reg32s[ESP]
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP));
gen_get_reg32(ctx.builder, regs::ESP);
let local_esp = ctx.builder.tee_new_local();
// result = safe_read32s(segment_offsets[SS] + esp) (or just esp if has_flat_segmentation)
@ -620,11 +627,11 @@ pub fn gen_pop32s_ss32(ctx: &mut JitContext) {
// reg32s[ESP] = esp + 4;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
.const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
ctx.builder.instruction_body.get_local(&local_esp);
ctx.builder.instruction_body.push_i32(4);
ctx.builder.instruction_body.const_i32(4);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
ctx.builder.free_local(local_esp);
@ -648,7 +655,7 @@ pub fn gen_task_switch_test(ctx: &mut JitContext) {
ctx.builder.instruction_body.load_aligned_i32(cr0_offset);
ctx.builder
.instruction_body
.push_i32((regs::CR0_EM | regs::CR0_TS) as i32);
.const_i32((regs::CR0_EM | regs::CR0_TS) as i32);
ctx.builder.instruction_body.and_i32();
ctx.builder.instruction_body.if_void();
@ -666,7 +673,7 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) {
ctx.builder.instruction_body.load_aligned_i32(cr0_offset);
ctx.builder
.instruction_body
.push_i32((regs::CR0_EM | regs::CR0_TS) as i32);
.const_i32((regs::CR0_EM | regs::CR0_TS) as i32);
ctx.builder.instruction_body.and_i32();
ctx.builder.instruction_body.if_void();
@ -679,18 +686,19 @@ pub fn gen_task_switch_test_mmx(ctx: &mut JitContext) {
pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) {
let sp_reg = if ctx.cpu.ssize_32() {
gen_get_reg32(ctx.builder, regs::ESP);
global_pointers::get_reg32_offset(regs::ESP)
}
else {
gen_get_reg16(ctx.builder, regs::SP);
global_pointers::get_reg16_offset(regs::SP)
};
ctx.builder.instruction_body.load_aligned_i32(sp_reg);
ctx.builder.instruction_body.push_i32(2);
ctx.builder.instruction_body.const_i32(2);
ctx.builder.instruction_body.sub_i32();
let reg_updated_local = ctx.builder.tee_new_local();
if !ctx.cpu.ssize_32() {
ctx.builder.instruction_body.push_i32(0xFFFF);
ctx.builder.instruction_body.const_i32(0xFFFF);
ctx.builder.instruction_body.and_i32();
}
@ -704,30 +712,31 @@ pub fn gen_push16(ctx: &mut JitContext, value_local: &WasmLocal) {
let sp_local = ctx.builder.set_new_local();
gen_safe_write16(ctx, &sp_local, &value_local);
ctx.builder.free_local(sp_local);
ctx.builder.instruction_body.push_i32(sp_reg as i32);
ctx.builder.instruction_body.const_i32(sp_reg as i32);
ctx.builder.instruction_body.get_local(&reg_updated_local);
if ctx.cpu.ssize_32() {
ctx.builder.instruction_body.store_aligned_i32()
ctx.builder.instruction_body.store_aligned_i32(0)
}
else {
ctx.builder.instruction_body.store_aligned_u16()
ctx.builder.instruction_body.store_aligned_u16(0)
};
ctx.builder.free_local(reg_updated_local);
}
pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) {
let sp_reg = if ctx.cpu.ssize_32() {
gen_get_reg32(ctx.builder, regs::ESP);
global_pointers::get_reg32_offset(regs::ESP)
}
else {
gen_get_reg16(ctx.builder, regs::SP);
global_pointers::get_reg16_offset(regs::SP)
};
ctx.builder.instruction_body.load_aligned_i32(sp_reg);
ctx.builder.instruction_body.push_i32(4);
ctx.builder.instruction_body.const_i32(4);
ctx.builder.instruction_body.sub_i32();
if !ctx.cpu.ssize_32() {
ctx.builder.instruction_body.push_i32(0xFFFF);
ctx.builder.instruction_body.const_i32(0xFFFF);
ctx.builder.instruction_body.and_i32();
}
let new_sp_local = ctx.builder.tee_new_local();
@ -744,13 +753,13 @@ pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) {
gen_safe_write32(ctx, &sp_local, &value_local);
ctx.builder.free_local(sp_local);
ctx.builder.instruction_body.push_i32(sp_reg as i32);
ctx.builder.instruction_body.const_i32(sp_reg as i32);
ctx.builder.instruction_body.get_local(&new_sp_local);
if ctx.cpu.ssize_32() {
ctx.builder.instruction_body.store_aligned_i32()
ctx.builder.instruction_body.store_aligned_i32(0)
}
else {
ctx.builder.instruction_body.store_aligned_u16()
ctx.builder.instruction_body.store_aligned_u16(0)
};
ctx.builder.free_local(new_sp_local);
}
@ -773,11 +782,11 @@ fn gen_safe_read_write(
builder.instruction_body.get_local(address_local);
// Pseudo: base_on_stack = (uint32_t)address >> 12;
builder.instruction_body.push_i32(12);
builder.instruction_body.shr_u32();
builder.instruction_body.const_i32(12);
builder.instruction_body.shr_u_i32();
// scale index
builder.instruction_body.push_i32(2);
builder.instruction_body.const_i32(2);
builder.instruction_body.shl_i32();
// Pseudo: entry = tlb_data[base_on_stack];
@ -788,21 +797,21 @@ fn gen_safe_read_write(
// Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_READONLY & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID &&
// (address & 0xFFF) <= (0x1000 - (bitsize / 8));
builder.instruction_body.push_i32(
builder.instruction_body.const_i32(
(0xFFF & !TLB_READONLY & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER }))
as i32,
);
builder.instruction_body.and_i32();
builder.instruction_body.push_i32(TLB_VALID as i32);
builder.instruction_body.const_i32(TLB_VALID as i32);
builder.instruction_body.eq_i32();
builder.instruction_body.get_local(&address_local);
builder.instruction_body.push_i32(0xFFF);
builder.instruction_body.const_i32(0xFFF);
builder.instruction_body.and_i32();
builder
.instruction_body
.push_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
.const_i32(0x1000 - if bits == BitSize::WORD { 2 } else { 4 });
builder.instruction_body.le_i32();
builder.instruction_body.and_i32();
@ -811,7 +820,7 @@ fn gen_safe_read_write(
// if(can_use_fast_path) leave_on_stack(mem8[entry & ~0xFFF ^ address]);
builder.instruction_body.if_i32();
builder.instruction_body.get_local(&entry_local);
builder.instruction_body.push_i32(!0xFFF);
builder.instruction_body.const_i32(!0xFFF);
builder.instruction_body.and_i32();
builder.instruction_body.get_local(&address_local);
builder.instruction_body.xor_i32();

View file

@ -925,7 +925,7 @@ fn jit_generate_module(
let gen_local_iteration_counter = if JIT_ALWAYS_USE_LOOP_SAFETY || requires_loop_limit {
builder
.instruction_body
.push_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32);
.const_i32(JIT_MAX_ITERATIONS_PER_FUNCTION as i32);
Some(builder.set_new_local())
}
else {
@ -942,7 +942,7 @@ fn jit_generate_module(
builder
.instruction_body
.get_local(gen_local_iteration_counter);
builder.instruction_body.push_i32(-1);
builder.instruction_body.const_i32(-1);
builder.instruction_body.add_i32();
builder
.instruction_body
@ -1006,7 +1006,7 @@ fn jit_generate_module(
.expect("basic_block_indices.get (Normal)");
// set state variable to next basic block
builder.instruction_body.push_i32(next_bb_index as i32);
builder.instruction_body.const_i32(next_bb_index as i32);
builder.instruction_body.set_local(&gen_local_state);
builder
@ -1055,7 +1055,7 @@ fn jit_generate_module(
builder
.instruction_body
.push_i32(next_basic_block_branch_taken_index as i32);
.const_i32(next_basic_block_branch_taken_index as i32);
builder.instruction_body.set_local(&gen_local_state);
}
else {
@ -1074,7 +1074,7 @@ fn jit_generate_module(
builder
.instruction_body
.push_i32(next_basic_block_index as i32);
.const_i32(next_basic_block_index as i32);
builder.instruction_body.set_local(&gen_local_state);
}
else {

View file

@ -102,9 +102,7 @@ pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
}
fn push16_reg_jit(ctx: &mut JitContext, r: u32) {
ctx.builder
.instruction_body
.load_aligned_u16(global_pointers::get_reg16_offset(r));
codegen::gen_get_reg16(ctx.builder, r);
let value_local = ctx.builder.set_new_local();
codegen::gen_push16(ctx, &value_local);
ctx.builder.free_local(value_local);
@ -118,13 +116,13 @@ fn push32_reg_jit(ctx: &mut JitContext, r: u32) {
ctx.builder.free_local(value_local);
}
fn push16_imm_jit(ctx: &mut JitContext, imm: u32) {
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
let value_local = ctx.builder.set_new_local();
codegen::gen_push16(ctx, &value_local);
ctx.builder.free_local(value_local);
}
fn push32_imm_jit(ctx: &mut JitContext, imm: u32) {
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
let value_local = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &value_local);
ctx.builder.free_local(value_local);
@ -147,17 +145,17 @@ fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(reg) as i32);
.const_i32(global_pointers::get_reg16_offset(reg) as i32);
codegen::gen_pop16(ctx);
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
}
fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(reg) as i32);
.const_i32(global_pointers::get_reg32_offset(reg) as i32);
codegen::gen_pop32s(ctx);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); }
@ -239,7 +237,7 @@ pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg8_offset(r) as i32);
.const_i32(global_pointers::get_reg8_offset(r) as i32);
ctx.builder.instruction_body.load_u8_from_stack(0);
let value_local = ctx.builder.set_new_local();
@ -256,10 +254,7 @@ pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
let address_local = ctx.builder.set_new_local();
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r) as i32);
ctx.builder.instruction_body.load_aligned_u16_from_stack(0);
codegen::gen_get_reg16(ctx.builder, r);
let value_local = ctx.builder.set_new_local();
codegen::gen_safe_write16(ctx, &address_local, &value_local);
@ -276,7 +271,7 @@ pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r) as i32);
.const_i32(global_pointers::get_reg32_offset(r) as i32);
ctx.builder.instruction_body.load_aligned_i32_from_stack(0);
let value_local = ctx.builder.set_new_local();
@ -292,7 +287,7 @@ pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
// Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte));
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg8_offset(r) as i32);
.const_i32(global_pointers::get_reg8_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read8(ctx);
@ -307,12 +302,11 @@ pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
// Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte));
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r) as i32);
.const_i32(global_pointers::get_reg16_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read16(ctx);
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
}
pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
codegen::gen_set_reg16_r(ctx, r2, r1);
@ -321,30 +315,32 @@ pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
// Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte));
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r) as i32);
.const_i32(global_pointers::get_reg32_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read32(ctx);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
codegen::gen_set_reg32_r(ctx, r2, r1);
}
pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) {
let loc = global_pointers::get_reg16_offset(reg);
ctx.builder.instruction_body.push_i32(loc as i32);
ctx.builder
.instruction_body
.const_i32(global_pointers::get_reg16_offset(reg) as i32);
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
codegen::gen_modrm_resolve(ctx, modrm_byte);
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
}
pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) {
let loc = global_pointers::get_reg32_offset(reg);
ctx.builder.instruction_body.push_i32(loc as i32);
ctx.builder
.instruction_body
.const_i32(global_pointers::get_reg32_offset(reg) as i32);
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
codegen::gen_modrm_resolve(ctx, modrm_byte);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
@ -358,13 +354,11 @@ pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
ctx.builder
.instruction_body
.load_aligned_u16(global_pointers::get_reg16_offset(regs::SP));
ctx.builder.instruction_body.push_i32(2);
.const_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
codegen::gen_get_reg16(ctx.builder, regs::SP);
ctx.builder.instruction_body.const_i32(2);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit");
@ -375,13 +369,11 @@ pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) {
pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP));
ctx.builder.instruction_body.push_i32(4);
.const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
codegen::gen_get_reg32(ctx.builder, regs::ESP);
ctx.builder.instruction_body.const_i32(4);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit");
@ -404,13 +396,13 @@ pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) {
ctx.builder.free_local(value_local);
ctx.builder
.instruction_body
.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
ctx.builder
.instruction_body
.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); }
@ -423,19 +415,19 @@ pub fn instr16_C3_jit(ctx: &mut JitContext) {
ctx.builder
.instruction_body
.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
ctx.builder.instruction_body.load_aligned_i32(cs_addr);
codegen::gen_pop16(ctx);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr32_C3_jit(ctx: &mut JitContext) {
ctx.builder
.instruction_body
.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
// cs = segment_offsets[CS]
ctx.builder
@ -450,7 +442,7 @@ pub fn instr32_C3_jit(ctx: &mut JitContext) {
// dbg_assert(is_asize_32() || ip < 0x10000);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) {
@ -535,96 +527,88 @@ pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r2) as i32);
builder
.instruction_body
.load_u8(global_pointers::get_reg8_offset(r1));
builder.instruction_body.store_aligned_u16();
.const_i32(global_pointers::get_reg16_offset(r2) as i32);
codegen::gen_get_reg8(builder, r1);
builder.instruction_body.store_aligned_u16(0);
}
pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r) as i32);
.const_i32(global_pointers::get_reg16_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read8(ctx);
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
}
pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r2) as i32);
builder
.instruction_body
.load_u8(global_pointers::get_reg8_offset(r1));
builder.instruction_body.store_aligned_i32();
.const_i32(global_pointers::get_reg32_offset(r2) as i32);
codegen::gen_get_reg8(builder, r1);
builder.instruction_body.store_aligned_i32(0);
}
pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r) as i32);
.const_i32(global_pointers::get_reg32_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read8(ctx);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r2) as i32);
builder
.instruction_body
.load_u8(global_pointers::get_reg8_offset(r1));
.const_i32(global_pointers::get_reg16_offset(r2) as i32);
codegen::gen_get_reg8(builder, r1);
codegen::sign_extend_i8(builder);
builder.instruction_body.store_aligned_u16();
builder.instruction_body.store_aligned_u16(0);
}
pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r) as i32);
.const_i32(global_pointers::get_reg16_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read8(ctx);
codegen::sign_extend_i8(ctx.builder);
ctx.builder.instruction_body.store_aligned_u16();
ctx.builder.instruction_body.store_aligned_u16(0);
}
pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
let builder = &mut ctx.builder;
builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r2) as i32);
builder
.instruction_body
.load_u8(global_pointers::get_reg8_offset(r1));
.const_i32(global_pointers::get_reg32_offset(r2) as i32);
codegen::gen_get_reg8(builder, r1);
codegen::sign_extend_i8(builder);
builder.instruction_body.store_aligned_i32();
builder.instruction_body.store_aligned_i32(0);
}
pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r) as i32);
.const_i32(global_pointers::get_reg32_offset(r) as i32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read8(ctx);
codegen::sign_extend_i8(ctx.builder);
ctx.builder.instruction_body.store_aligned_i32();
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
// reg16[r] = imm;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg16_offset(r) as i32);
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.store_aligned_u16();
.const_i32(global_pointers::get_reg16_offset(r) as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
ctx.builder.instruction_body.store_aligned_u16(0);
}
pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
codegen::gen_modrm_resolve(ctx, modrm_byte);
let address_local = ctx.builder.set_new_local();
let imm = ctx.cpu.read_imm16();
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
let value_local = ctx.builder.set_new_local();
codegen::gen_safe_write16(ctx, &address_local, &value_local);
ctx.builder.free_local(address_local);
@ -635,16 +619,16 @@ pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
// reg32s[r] = imm;
ctx.builder
.instruction_body
.push_i32(global_pointers::get_reg32_offset(r) as i32);
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.store_aligned_i32();
.const_i32(global_pointers::get_reg32_offset(r) as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
ctx.builder.instruction_body.store_aligned_i32(0);
}
pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
codegen::gen_modrm_resolve(ctx, modrm_byte);
let address_local = ctx.builder.set_new_local();
let imm = ctx.cpu.read_imm32();
ctx.builder.instruction_body.push_i32(imm as i32);
ctx.builder.instruction_body.const_i32(imm as i32);
let value_local = ctx.builder.set_new_local();
codegen::gen_safe_write32(ctx, &address_local, &value_local);
ctx.builder.free_local(address_local);

View file

@ -1,3 +1,4 @@
use codegen;
use cpu_context::CpuContext;
use jit::JitContext;
use prefix::{PREFIX_MASK_SEGMENT, SEG_PREFIX_ZERO};
@ -105,36 +106,30 @@ fn gen16_case(ctx: &mut JitContext, seg: u32, offset: Offset16, imm: Imm16) {
Offset16::Zero => {
ctx.builder
.instruction_body
.push_i32(immediate_value & 0xFFFF);
.const_i32(immediate_value & 0xFFFF);
},
Offset16::One(r) => {
ctx.builder
.instruction_body
.load_aligned_u16(::global_pointers::get_reg16_offset(r));
codegen::gen_get_reg16(ctx.builder, r);
if immediate_value != 0 {
ctx.builder.instruction_body.push_i32(immediate_value);
ctx.builder.instruction_body.const_i32(immediate_value);
ctx.builder.instruction_body.add_i32();
ctx.builder.instruction_body.push_i32(0xFFFF);
ctx.builder.instruction_body.const_i32(0xFFFF);
ctx.builder.instruction_body.and_i32();
}
},
Offset16::Two(r1, r2) => {
ctx.builder
.instruction_body
.load_aligned_u16(::global_pointers::get_reg16_offset(r1));
ctx.builder
.instruction_body
.load_aligned_u16(::global_pointers::get_reg16_offset(r2));
codegen::gen_get_reg16(ctx.builder, r1);
codegen::gen_get_reg16(ctx.builder, r2);
ctx.builder.instruction_body.add_i32();
if immediate_value != 0 {
ctx.builder.instruction_body.push_i32(immediate_value);
ctx.builder.instruction_body.const_i32(immediate_value);
ctx.builder.instruction_body.add_i32();
}
ctx.builder.instruction_body.push_i32(0xFFFF);
ctx.builder.instruction_body.const_i32(0xFFFF);
ctx.builder.instruction_body.and_i32();
},
}
@ -200,7 +195,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) {
};
if immediate_value != 0 {
ctx.builder.instruction_body.push_i32(immediate_value);
ctx.builder.instruction_body.const_i32(immediate_value);
ctx.builder.instruction_body.add_i32();
}
},
@ -210,11 +205,9 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) {
Imm32::Imm8 => ctx.cpu.read_imm8s() as i32,
Imm32::Imm32 => ctx.cpu.read_imm32() as i32,
};
ctx.builder
.instruction_body
.load_aligned_i32(::global_pointers::get_reg32_offset(r));
codegen::gen_get_reg32(ctx.builder, r);
if immediate_value != 0 {
ctx.builder.instruction_body.push_i32(immediate_value);
ctx.builder.instruction_body.const_i32(immediate_value);
ctx.builder.instruction_body.add_i32();
}
jit_add_seg_offset(ctx, seg);
@ -225,7 +218,7 @@ fn gen32_case(ctx: &mut JitContext, seg: u32, offset: Offset, imm: Imm32) {
Imm32::Imm8 => ctx.cpu.read_imm8s() as i32,
Imm32::Imm32 => ctx.cpu.read_imm32() as i32,
};
ctx.builder.instruction_body.push_i32(immediate_value);
ctx.builder.instruction_body.const_i32(immediate_value);
jit_add_seg_offset(ctx, seg);
},
}
@ -276,25 +269,22 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) {
if r == 4 {
seg = SS;
let base_addr = ::global_pointers::get_reg32_offset(ESP);
ctx.builder.instruction_body.load_aligned_i32(base_addr);
codegen::gen_get_reg32(ctx.builder, ESP);
}
else if r == 5 {
if mod_is_nonzero {
seg = SS;
let base_addr = ::global_pointers::get_reg32_offset(EBP);
ctx.builder.instruction_body.load_aligned_i32(base_addr);
codegen::gen_get_reg32(ctx.builder, EBP);
}
else {
seg = DS;
let base = ctx.cpu.read_imm32();
ctx.builder.instruction_body.push_i32(base as i32);
ctx.builder.instruction_body.const_i32(base as i32);
}
}
else {
seg = DS;
let base_addr = ::global_pointers::get_reg32_offset(r as u32);
ctx.builder.instruction_body.load_aligned_i32(base_addr);
codegen::gen_get_reg32(ctx.builder, r as u32);
}
jit_add_seg_offset(ctx, seg);
@ -310,10 +300,8 @@ fn gen_sib(ctx: &mut JitContext, mod_is_nonzero: bool) {
let s = sib_byte >> 6 & 3;
ctx.builder
.instruction_body
.load_aligned_i32(::global_pointers::get_reg32_offset(m as u32));
ctx.builder.instruction_body.push_i32(s as i32);
codegen::gen_get_reg32(ctx.builder, m as u32);
ctx.builder.instruction_body.const_i32(s as i32);
ctx.builder.instruction_body.shl_i32();
ctx.builder.instruction_body.add_i32();
@ -336,7 +324,7 @@ fn jit_add_seg_offset(ctx: &mut JitContext, default_segment: u32) {
return;
}
ctx.builder.instruction_body.push_i32(seg as i32);
ctx.builder.instruction_body.const_i32(seg as i32);
ctx.builder.instruction_body.call_fn(::jit::FN_GET_SEG_IDX);
ctx.builder.instruction_body.add_i32();
}

View file

@ -395,18 +395,18 @@ mod tests {
m.finish();
m.reset();
m.code_section.push_i32(2);
m.code_section.const_i32(2);
let baz_index = m.get_fn_idx("baz", FN1_RET_TYPE_INDEX);
m.instruction_body.call_fn(baz_index);
foo_index = m.get_fn_idx("foo", FN1_TYPE_INDEX);
m.instruction_body.call_fn(foo_index);
m.code_section.push_i32(10);
m.code_section.const_i32(10);
let local1 = m.alloc_local();
m.code_section.tee_local(&local1); // local1 = 10
m.code_section.push_i32(20);
m.code_section.const_i32(20);
m.code_section.add_i32();
let local2 = m.alloc_local();
m.code_section.tee_local(&local2); // local2 = 30
@ -419,7 +419,7 @@ mod tests {
m.free_local(local2);
m.free_local(local3);
m.code_section.push_i32(30);
m.code_section.const_i32(30);
m.code_section.ne_i32();
m.code_section.if_void();
m.code_section.unreachable();

View file

@ -7,11 +7,7 @@ pub trait WasmBuf {
fn write_leb_u32(&mut self, v: u32);
fn write_fixed_leb16_at_idx(&mut self, idx: usize, x: u16);
fn write_fixed_leb32_at_idx(&mut self, idx: usize, x: u32);
fn push_i32(&mut self, v: i32);
fn load_aligned_u16(&mut self, addr: u32);
fn load_aligned_i32(&mut self, addr: u32);
fn store_aligned_u16(&mut self);
fn store_aligned_i32(&mut self);
fn const_i32(&mut self, v: i32);
fn add_i32(&mut self);
fn sub_i32(&mut self);
fn and_i32(&mut self);
@ -27,16 +23,24 @@ pub trait WasmBuf {
fn if_i32(&mut self);
fn block_i32(&mut self);
fn xor_i32(&mut self);
fn load_u8(&mut self, addr: u32);
fn load_u8_from_stack(&mut self, byte_offset: u32);
fn load_aligned_u16(&mut self, addr: u32);
fn load_aligned_i32(&mut self, addr: u32);
fn load_unaligned_i32_from_stack(&mut self, byte_offset: u32);
fn load_unaligned_u16_from_stack(&mut self, byte_offset: u32);
fn load_aligned_i32_from_stack(&mut self, byte_offset: u32);
fn load_u8(&mut self, addr: u32);
fn load_u8_from_stack(&mut self, byte_offset: u32);
fn store_unaligned_i32(&mut self, byte_offset: u32);
fn store_unaligned_u16(&mut self, byte_offset: u32);
fn load_aligned_u16_from_stack(&mut self, byte_offset: u32);
fn store_u8(&mut self, byte_offset: u32);
fn shr_u32(&mut self);
fn shr_i32(&mut self);
fn store_aligned_u16(&mut self, byte_offset: u32);
fn store_aligned_i32(&mut self, byte_offset: u32);
fn store_unaligned_u16(&mut self, byte_offset: u32);
fn store_unaligned_i32(&mut self, byte_offset: u32);
fn shr_u_i32(&mut self);
fn shr_s_i32(&mut self);
fn eqz_i32(&mut self);
fn if_void(&mut self);
fn else_(&mut self);
@ -53,7 +57,6 @@ pub trait WasmBuf {
fn unreachable(&mut self);
fn increment_mem32(&mut self, addr: u32);
fn increment_variable(&mut self, addr: u32, n: i32);
fn load_aligned_u16_from_stack(&mut self, byte_offset: u32);
}
impl WasmBuf for Vec<u8> {
@ -69,7 +72,7 @@ impl WasmBuf for Vec<u8> {
write_fixed_leb32_at_idx(self, idx, x)
}
fn push_i32(&mut self, v: i32) {
fn const_i32(&mut self, v: i32) {
self.push(op::OP_I32CONST);
self.write_leb_i32(v);
}
@ -89,7 +92,7 @@ impl WasmBuf for Vec<u8> {
// doesn't cause a failure in the generated code, but it will be much slower
dbg_assert!((addr & 3) == 0);
self.push_i32(addr as i32);
self.const_i32(addr as i32);
self.load_aligned_i32_from_stack(0);
}
@ -100,22 +103,10 @@ impl WasmBuf for Vec<u8> {
}
fn load_u8(&mut self, addr: u32) {
self.push_i32(addr as i32);
self.const_i32(addr as i32);
self.load_u8_from_stack(0);
}
fn store_aligned_u16(&mut self) {
self.push(op::OP_I32STORE16);
self.push(op::MEM_ALIGN16);
self.push(0); // immediate offset
}
fn store_aligned_i32(&mut self) {
self.push(op::OP_I32STORE);
self.push(op::MEM_ALIGN32);
self.push(0); // immediate offset
}
fn add_i32(&mut self) { self.push(op::OP_I32ADD); }
fn sub_i32(&mut self) { self.push(op::OP_I32SUB); }
@ -175,29 +166,39 @@ impl WasmBuf for Vec<u8> {
self.write_leb_u32(byte_offset);
}
// XXX: Function naming should be consistent regarding both alignment and accepting an
// offset. Leaving as-is for the Rust port to cleanup
fn store_unaligned_i32(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE);
fn store_u8(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE8);
self.push(op::MEM_NO_ALIGN);
self.write_leb_u32(byte_offset);
}
fn store_aligned_u16(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE16);
self.push(op::MEM_ALIGN16);
self.write_leb_u32(byte_offset);
}
fn store_aligned_i32(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE);
self.push(op::MEM_ALIGN32);
self.write_leb_u32(byte_offset);
}
fn store_unaligned_u16(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE16);
self.push(op::MEM_NO_ALIGN);
self.write_leb_u32(byte_offset);
}
fn store_u8(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE8);
fn store_unaligned_i32(&mut self, byte_offset: u32) {
self.push(op::OP_I32STORE);
self.push(op::MEM_NO_ALIGN);
self.write_leb_u32(byte_offset);
}
fn shr_u32(&mut self) { self.push(op::OP_I32SHRU); }
fn shr_u_i32(&mut self) { self.push(op::OP_I32SHRU); }
fn shr_i32(&mut self) { self.push(op::OP_I32SHRS); }
fn shr_s_i32(&mut self) { self.push(op::OP_I32SHRS); }
fn eqz_i32(&mut self) { self.push(op::OP_I32EQZ); }
@ -260,11 +261,11 @@ impl WasmBuf for Vec<u8> {
fn increment_mem32(&mut self, addr: u32) { self.increment_variable(addr, 1) }
fn increment_variable(&mut self, addr: u32, n: i32) {
self.push_i32(addr as i32);
self.const_i32(addr as i32);
self.load_aligned_i32(addr);
self.push_i32(n);
self.const_i32(n);
self.add_i32();
self.store_aligned_i32();
self.store_aligned_i32(0);
}
fn load_aligned_u16_from_stack(&mut self, byte_offset: u32) {