Make loop, loopz, loopnz and jcxz custom generated
This commit is contained in:
parent
ea0cd01207
commit
a73988a817
|
@ -284,9 +284,13 @@ function gen_instruction_body_after_fixed_g(encoding, size)
|
|||
|
||||
if(encoding.conditional_jump)
|
||||
{
|
||||
console.assert((encoding.opcode & ~0xF) === 0x70 || (encoding.opcode & ~0xF) === 0x0F80);
|
||||
const condition_index = encoding.opcode & 0xF;
|
||||
body.push(`analysis.ty = ::analysis::AnalysisType::Jump { offset: jump_offset as i32, condition: Some(${condition_index}), is_32: cpu.osize_32() };`);
|
||||
console.assert(
|
||||
(encoding.opcode & ~0xF) === 0x70 ||
|
||||
(encoding.opcode & ~0xF) === 0x0F80 ||
|
||||
(encoding.opcode & ~0x3) === 0xE0
|
||||
);
|
||||
const condition_index = encoding.opcode & 0xFF;
|
||||
body.push(`analysis.ty = ::analysis::AnalysisType::Jump { offset: jump_offset as i32, condition: Some(0x${hex(condition_index, 2)}), is_32: cpu.osize_32() };`);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -345,12 +345,10 @@ const encodings = [
|
|||
{ opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
// loop, jcxz, etc.
|
||||
// Conditional jumps, but condition code not supported by code generator
|
||||
// (these are never generated by modern compilers)
|
||||
{ opcode: 0xE0, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
|
||||
{ opcode: 0xE1, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
|
||||
{ opcode: 0xE2, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
|
||||
{ opcode: 0xE3, os: 1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
|
||||
{ opcode: 0xE0, os: 1, imm8s: 1, no_block_boundary_in_interpreted: 1, skip: 1, block_boundary: 1, jump_offset_imm: 1, custom: 1, conditional_jump: 1, },
|
||||
{ opcode: 0xE1, os: 1, imm8s: 1, no_block_boundary_in_interpreted: 1, skip: 1, block_boundary: 1, jump_offset_imm: 1, custom: 1, conditional_jump: 1, },
|
||||
{ opcode: 0xE2, os: 1, imm8s: 1, no_block_boundary_in_interpreted: 1, skip: 1, block_boundary: 1, jump_offset_imm: 1, custom: 1, conditional_jump: 1, },
|
||||
{ opcode: 0xE3, os: 1, imm8s: 1, no_block_boundary_in_interpreted: 1, skip: 1, block_boundary: 1, jump_offset_imm: 1, custom: 1, conditional_jump: 1, },
|
||||
|
||||
// port functions aren't jumps, but they may modify eip due to how they are implemented
|
||||
{ opcode: 0xE4, block_boundary: 1, imm8: 1, skip: 1, }, // in
|
||||
|
|
|
@ -1601,6 +1601,49 @@ pub fn gen_test_be(builder: &mut WasmBuilder) {
|
|||
builder.instruction_body.or_i32();
|
||||
}
|
||||
|
||||
pub fn gen_test_loopnz(ctx: &mut JitContext, is_asize_32: bool) {
|
||||
gen_test_loop(ctx, is_asize_32);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
gen_getzf(&mut ctx.builder);
|
||||
ctx.builder.instruction_body.or_i32();
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
pub fn gen_test_loopz(ctx: &mut JitContext, is_asize_32: bool) {
|
||||
gen_test_loop(ctx, is_asize_32);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
gen_getzf(&mut ctx.builder);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
ctx.builder.instruction_body.or_i32();
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
pub fn gen_test_loop(ctx: &mut JitContext, is_asize_32: bool) {
|
||||
if is_asize_32 {
|
||||
gen_get_reg32(ctx, regs::ECX);
|
||||
}
|
||||
else {
|
||||
gen_get_reg16(ctx, regs::CX);
|
||||
}
|
||||
ctx.builder.instruction_body.const_i32(1);
|
||||
ctx.builder.instruction_body.sub_i32();
|
||||
if is_asize_32 {
|
||||
gen_set_reg32(ctx, regs::ECX);
|
||||
gen_get_reg32(ctx, regs::ECX);
|
||||
}
|
||||
else {
|
||||
gen_set_reg16(ctx, regs::ECX);
|
||||
gen_get_reg16(ctx, regs::CX);
|
||||
}
|
||||
}
|
||||
pub fn gen_test_jcxz(ctx: &mut JitContext, is_asize_32: bool) {
|
||||
if is_asize_32 {
|
||||
gen_get_reg32(ctx, regs::ECX);
|
||||
}
|
||||
else {
|
||||
gen_get_reg16(ctx, regs::CX);
|
||||
}
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
|
||||
pub fn gen_fpu_get_sti(ctx: &mut JitContext, i: u32) {
|
||||
ctx.builder.instruction_body.const_i32(i as i32);
|
||||
gen_call_fn1_ret_f64(ctx.builder, "fpu_get_sti");
|
||||
|
@ -1641,32 +1684,50 @@ pub fn gen_trigger_gp(ctx: &mut JitContext, error_code: u32) {
|
|||
ctx.builder.instruction_body.return_();
|
||||
}
|
||||
|
||||
pub fn gen_condition_fn(builder: &mut WasmBuilder, condition: u8) {
|
||||
dbg_assert!(condition < 16);
|
||||
if condition == 2 {
|
||||
gen_getcf(builder);
|
||||
}
|
||||
else if condition == 3 {
|
||||
gen_getcf(builder);
|
||||
builder.instruction_body.eqz_i32();
|
||||
}
|
||||
else if condition == 4 {
|
||||
gen_getzf(builder);
|
||||
}
|
||||
else if condition == 5 {
|
||||
gen_getzf(builder);
|
||||
builder.instruction_body.eqz_i32();
|
||||
}
|
||||
else if condition == 6 {
|
||||
gen_test_be(builder);
|
||||
}
|
||||
else if condition == 7 {
|
||||
gen_test_be(builder);
|
||||
builder.instruction_body.eqz_i32();
|
||||
pub fn gen_condition_fn(ctx: &mut JitContext, mut condition: u8) {
|
||||
if condition & 0xF0 == 0x00 || condition & 0xF0 == 0x70 || condition & 0xF0 == 0x80 {
|
||||
condition &= 0xF;
|
||||
if condition == 2 {
|
||||
gen_getcf(ctx.builder);
|
||||
}
|
||||
else if condition == 3 {
|
||||
gen_getcf(ctx.builder);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
else if condition == 4 {
|
||||
gen_getzf(ctx.builder);
|
||||
}
|
||||
else if condition == 5 {
|
||||
gen_getzf(ctx.builder);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
else if condition == 6 {
|
||||
gen_test_be(ctx.builder);
|
||||
}
|
||||
else if condition == 7 {
|
||||
gen_test_be(ctx.builder);
|
||||
ctx.builder.instruction_body.eqz_i32();
|
||||
}
|
||||
else {
|
||||
let condition_name = CONDITION_FUNCTIONS[condition as usize];
|
||||
gen_fn0_const_ret(ctx.builder, condition_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let condition_name = CONDITION_FUNCTIONS[condition as usize];
|
||||
gen_fn0_const_ret(builder, condition_name);
|
||||
// loop, loopnz, loopz, jcxz
|
||||
dbg_assert!(condition & !0x3 == 0xE0);
|
||||
if condition == 0xE0 {
|
||||
gen_test_loopnz(ctx, ctx.cpu.asize_32());
|
||||
}
|
||||
else if condition == 0xE1 {
|
||||
gen_test_loopz(ctx, ctx.cpu.asize_32());
|
||||
}
|
||||
else if condition == 0xE2 {
|
||||
gen_test_loop(ctx, ctx.cpu.asize_32());
|
||||
}
|
||||
else if condition == 0xE3 {
|
||||
gen_test_jcxz(ctx, ctx.cpu.asize_32());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1106,9 +1106,9 @@ fn jit_generate_module(
|
|||
jump_offset_is_32,
|
||||
} => {
|
||||
// Conditional jump to next basic block
|
||||
// - jnz, jc, etc.
|
||||
// - jnz, jc, loop, jcxz, etc.
|
||||
|
||||
codegen::gen_condition_fn(ctx.builder, condition);
|
||||
codegen::gen_condition_fn(ctx, condition);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
|
||||
// Branch taken
|
||||
|
|
|
@ -1526,6 +1526,15 @@ pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|||
pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
|
||||
pub fn instr16_E0_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr32_E0_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr16_E1_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr32_E1_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr16_E2_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr32_E2_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr16_E3_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
pub fn instr32_E3_jit(_ctx: &mut JitContext, _imm: u32) {}
|
||||
|
||||
define_instruction_read_write_mem8!("add8", instr_80_0_mem_jit, instr_80_0_reg_jit, imm8);
|
||||
define_instruction_read_write_mem8!("or8", instr_80_1_mem_jit, instr_80_1_reg_jit, imm8);
|
||||
define_instruction_read_write_mem8!("adc8", instr_80_2_mem_jit, instr_80_2_reg_jit, imm8);
|
||||
|
@ -3567,7 +3576,7 @@ macro_rules! define_cmovcc16(
|
|||
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
||||
codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte);
|
||||
let value = ctx.builder.set_new_local();
|
||||
codegen::gen_condition_fn(ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
ctx.builder.instruction_body.get_local(&value);
|
||||
codegen::gen_set_reg16(ctx, r);
|
||||
|
@ -3576,7 +3585,7 @@ macro_rules! define_cmovcc16(
|
|||
}
|
||||
|
||||
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
codegen::gen_condition_fn(ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
codegen::gen_get_reg16(ctx, r1);
|
||||
codegen::gen_set_reg16(ctx, r2);
|
||||
|
@ -3590,7 +3599,7 @@ macro_rules! define_cmovcc32(
|
|||
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
||||
codegen::gen_modrm_resolve_safe_read32(ctx, modrm_byte);
|
||||
let value = ctx.builder.set_new_local();
|
||||
codegen::gen_condition_fn(ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
ctx.builder.instruction_body.get_local(&value);
|
||||
codegen::gen_set_reg32(ctx, r);
|
||||
|
@ -3599,7 +3608,7 @@ macro_rules! define_cmovcc32(
|
|||
}
|
||||
|
||||
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
codegen::gen_condition_fn(ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.if_void();
|
||||
codegen::gen_get_reg32(ctx, r1);
|
||||
codegen::gen_set_reg32(ctx, r2);
|
||||
|
@ -3649,7 +3658,7 @@ macro_rules! define_setcc(
|
|||
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, _r: u32) {
|
||||
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
||||
let address_local = ctx.builder.set_new_local();
|
||||
codegen::gen_condition_fn(&mut ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.const_i32(0);
|
||||
ctx.builder.instruction_body.ne_i32();
|
||||
let value_local = ctx.builder.set_new_local();
|
||||
|
@ -3659,7 +3668,7 @@ macro_rules! define_setcc(
|
|||
}
|
||||
|
||||
pub fn $name_reg(ctx: &mut JitContext, r1: u32, _r2: u32) {
|
||||
codegen::gen_condition_fn(&mut ctx.builder, $cond);
|
||||
codegen::gen_condition_fn(ctx, $cond);
|
||||
ctx.builder.instruction_body.const_i32(0);
|
||||
ctx.builder.instruction_body.ne_i32();
|
||||
codegen::gen_set_reg8(ctx, r1);
|
||||
|
|
25
tests/nasm/jcxz.asm
Normal file
25
tests/nasm/jcxz.asm
Normal file
|
@ -0,0 +1,25 @@
|
|||
global _start
|
||||
|
||||
%include "header.inc"
|
||||
|
||||
mov ecx, 0x10000
|
||||
jecxz cont1
|
||||
or eax, 1
|
||||
cont1:
|
||||
|
||||
mov ecx, 0
|
||||
jecxz cont2
|
||||
or eax, 2
|
||||
cont2:
|
||||
|
||||
mov ecx, 0x1
|
||||
jcxz cont3
|
||||
or eax, 4
|
||||
cont3:
|
||||
|
||||
mov ecx, 0x10000
|
||||
jcxz cont4
|
||||
or eax, 8
|
||||
cont4:
|
||||
|
||||
%include "footer.inc"
|
18
tests/nasm/loop.asm
Normal file
18
tests/nasm/loop.asm
Normal file
|
@ -0,0 +1,18 @@
|
|||
global _start
|
||||
|
||||
%include "header.inc"
|
||||
|
||||
mov ecx, 0x10042
|
||||
mov eax, 0
|
||||
start1:
|
||||
inc eax
|
||||
loop start1
|
||||
|
||||
mov ecx, 0x10005
|
||||
mov ebx, 0
|
||||
start2:
|
||||
inc ebx
|
||||
db 67h
|
||||
loop start2
|
||||
|
||||
%include "footer.inc"
|
24
tests/nasm/loopnz.asm
Normal file
24
tests/nasm/loopnz.asm
Normal file
|
@ -0,0 +1,24 @@
|
|||
global _start
|
||||
|
||||
%include "header.inc"
|
||||
|
||||
mov ecx, 0x10042
|
||||
mov eax, 42
|
||||
start1:
|
||||
dec eax
|
||||
loopz start1
|
||||
|
||||
mov ecx, 0x10005
|
||||
mov ebx, 51
|
||||
start2:
|
||||
dec ebx
|
||||
db 67h
|
||||
loopz start2
|
||||
|
||||
mov ecx, 0x10005
|
||||
start3:
|
||||
or edx, 1
|
||||
db 67h
|
||||
loopz start3
|
||||
|
||||
%include "footer.inc"
|
24
tests/nasm/loopz.asm
Normal file
24
tests/nasm/loopz.asm
Normal file
|
@ -0,0 +1,24 @@
|
|||
global _start
|
||||
|
||||
%include "header.inc"
|
||||
|
||||
mov ecx, 0x10042
|
||||
mov eax, -1
|
||||
start1:
|
||||
inc eax
|
||||
loopz start1
|
||||
|
||||
mov ecx, 0x10005
|
||||
mov ebx, -1
|
||||
start2:
|
||||
inc ebx
|
||||
db 67h
|
||||
loopz start2
|
||||
|
||||
mov ecx, 0x10005
|
||||
start3:
|
||||
xor edx, edx
|
||||
db 67h
|
||||
loopz start3
|
||||
|
||||
%include "footer.inc"
|
Loading…
Reference in a new issue