Fix 8-bit jumps in 16-bit mode

This commit is contained in:
Fabian 2018-06-19 09:35:09 -06:00
parent c40a5ccf25
commit 9b2b3250df
4 changed files with 110 additions and 90 deletions

View file

@ -168,10 +168,10 @@ const encodings = [
// loop, jcxz, etc.
// Conditional jumps, but condition code not supported by code generator
// (these are never generated by modern compilers)
{ opcode: 0xE0, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
{ opcode: 0xE1, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
{ opcode: 0xE2, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
{ opcode: 0xE3, imm8s: 1, skip: 1, block_boundary: 1, /* jump_offset_imm: 1, conditional_jump: 1, */ },
{ 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, */ },
// 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
@ -182,7 +182,7 @@ const encodings = [
{ opcode: 0xE8, block_boundary: 1, jump_offset_imm: 1, os: 1, imm1632: 1, custom: 1, skip: 1, }, // call
{ opcode: 0xE9, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm1632: 1, custom: 1, skip: 1, },
{ opcode: 0xEA, block_boundary: 1, no_next_instruction: 1, os: 1, imm1632: 1, extra_imm16: 1, skip: 1, }, // jmpf
{ opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0xEB, block_boundary: 1, jump_offset_imm: 1, no_next_instruction: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0xEC, block_boundary: 1, skip: 1, }, // in
{ opcode: 0xED, block_boundary: 1, os: 1, skip: 1, },
@ -704,8 +704,8 @@ for(let i = 0; i < 8; i++)
{ opcode: 0x04 | i << 3, nonfaulting: 1, eax: 1, imm8: 1, },
{ opcode: 0x05 | i << 3, nonfaulting: 1, os: 1, eax: 1, imm1632: 1, },
{ opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x70 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x78 | i, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, os: 1, imm8s: 1, custom: 1, skip: 1, },
{ opcode: 0x80, nonfaulting: 1, e: 1, fixed_g: i, imm8: 1, },
{ opcode: 0x81, nonfaulting: 1, os: 1, e: 1, fixed_g: i, imm1632: 1, },

View file

@ -371,39 +371,73 @@ void instr_6E() { outsb(); }
void instr16_6F() { outsw(); }
void instr32_6F() { outsd(); }
void instr_70(int32_t imm8) { jmpcc8( test_o(), imm8); }
void instr_71(int32_t imm8) { jmpcc8(!test_o(), imm8); }
void instr_72(int32_t imm8) { jmpcc8( test_b(), imm8); }
void instr_73(int32_t imm8) { jmpcc8(!test_b(), imm8); }
void instr_74(int32_t imm8) { jmpcc8( test_z(), imm8); }
void instr_75(int32_t imm8) { jmpcc8(!test_z(), imm8); }
void instr_76(int32_t imm8) { jmpcc8( test_be(), imm8); }
void instr_77(int32_t imm8) { jmpcc8(!test_be(), imm8); }
void instr_78(int32_t imm8) { jmpcc8( test_s(), imm8); }
void instr_79(int32_t imm8) { jmpcc8(!test_s(), imm8); }
void instr_7A(int32_t imm8) { jmpcc8( test_p(), imm8); }
void instr_7B(int32_t imm8) { jmpcc8(!test_p(), imm8); }
void instr_7C(int32_t imm8) { jmpcc8( test_l(), imm8); }
void instr_7D(int32_t imm8) { jmpcc8(!test_l(), imm8); }
void instr_7E(int32_t imm8) { jmpcc8( test_le(), imm8); }
void instr_7F(int32_t imm8) { jmpcc8(!test_le(), imm8); }
void instr16_70(int32_t imm8) { jmpcc16( test_o(), imm8); }
void instr16_71(int32_t imm8) { jmpcc16(!test_o(), imm8); }
void instr16_72(int32_t imm8) { jmpcc16( test_b(), imm8); }
void instr16_73(int32_t imm8) { jmpcc16(!test_b(), imm8); }
void instr16_74(int32_t imm8) { jmpcc16( test_z(), imm8); }
void instr16_75(int32_t imm8) { jmpcc16(!test_z(), imm8); }
void instr16_76(int32_t imm8) { jmpcc16( test_be(), imm8); }
void instr16_77(int32_t imm8) { jmpcc16(!test_be(), imm8); }
void instr16_78(int32_t imm8) { jmpcc16( test_s(), imm8); }
void instr16_79(int32_t imm8) { jmpcc16(!test_s(), imm8); }
void instr16_7A(int32_t imm8) { jmpcc16( test_p(), imm8); }
void instr16_7B(int32_t imm8) { jmpcc16(!test_p(), imm8); }
void instr16_7C(int32_t imm8) { jmpcc16( test_l(), imm8); }
void instr16_7D(int32_t imm8) { jmpcc16(!test_l(), imm8); }
void instr16_7E(int32_t imm8) { jmpcc16( test_le(), imm8); }
void instr16_7F(int32_t imm8) { jmpcc16(!test_le(), imm8); }
void instr_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); }
void instr_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); }
void instr_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); }
void instr_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); }
void instr_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); }
void instr_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); }
void instr_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); }
void instr_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); }
void instr_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); }
void instr_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); }
void instr_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); }
void instr_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); }
void instr_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); }
void instr_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); }
void instr_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); }
void instr_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); }
void instr32_70(int32_t imm8) { jmpcc32( test_o(), imm8); }
void instr32_71(int32_t imm8) { jmpcc32(!test_o(), imm8); }
void instr32_72(int32_t imm8) { jmpcc32( test_b(), imm8); }
void instr32_73(int32_t imm8) { jmpcc32(!test_b(), imm8); }
void instr32_74(int32_t imm8) { jmpcc32( test_z(), imm8); }
void instr32_75(int32_t imm8) { jmpcc32(!test_z(), imm8); }
void instr32_76(int32_t imm8) { jmpcc32( test_be(), imm8); }
void instr32_77(int32_t imm8) { jmpcc32(!test_be(), imm8); }
void instr32_78(int32_t imm8) { jmpcc32( test_s(), imm8); }
void instr32_79(int32_t imm8) { jmpcc32(!test_s(), imm8); }
void instr32_7A(int32_t imm8) { jmpcc32( test_p(), imm8); }
void instr32_7B(int32_t imm8) { jmpcc32(!test_p(), imm8); }
void instr32_7C(int32_t imm8) { jmpcc32( test_l(), imm8); }
void instr32_7D(int32_t imm8) { jmpcc32(!test_l(), imm8); }
void instr32_7E(int32_t imm8) { jmpcc32( test_le(), imm8); }
void instr32_7F(int32_t imm8) { jmpcc32(!test_le(), imm8); }
void instr16_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); }
void instr16_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); }
void instr16_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); }
void instr16_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); }
void instr16_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); }
void instr16_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); }
void instr16_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); }
void instr16_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); }
void instr16_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); }
void instr16_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); }
void instr16_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); }
void instr16_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); }
void instr16_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); }
void instr16_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); }
void instr16_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); }
void instr16_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); }
void instr32_70_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_o"); }
void instr32_71_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_no"); }
void instr32_72_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_b"); }
void instr32_73_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nb"); }
void instr32_74_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_z"); }
void instr32_75_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nz"); }
void instr32_76_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_be"); }
void instr32_77_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nbe"); }
void instr32_78_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_s"); }
void instr32_79_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_ns"); }
void instr32_7A_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_p"); }
void instr32_7B_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_np"); }
void instr32_7C_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_l"); }
void instr32_7D_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nl"); }
void instr32_7E_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_le"); }
void instr32_7F_jit(int32_t imm8) { jit_link_block_conditional(imm8, "test_nle"); }
DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_0, add8(___, imm))
DEFINE_MODRM_INSTR2_READ_WRITE_8(instr_80_1, or8(___, imm))
@ -1413,10 +1447,15 @@ void instr_DF_5_reg(int32_t r) { task_switch_test(); fpu_fucomip(r); }
void instr_DF_6_reg(int32_t r) { task_switch_test(); fpu_fcomip(r); }
void instr_DF_7_reg(int32_t r) { trigger_ud(); }
void instr_E0(int32_t off) { loopne(off); }
void instr_E1(int32_t off) { loope(off); }
void instr_E2(int32_t off) { loop(off); }
void instr_E3(int32_t off) { jcxz(off); }
void instr16_E0(int32_t imm8s) { loopne16(imm8s); }
void instr16_E1(int32_t imm8s) { loope16(imm8s); }
void instr16_E2(int32_t imm8s) { loop16(imm8s); }
void instr16_E3(int32_t imm8s) { jcxz16(imm8s); }
void instr32_E0(int32_t imm8s) { loopne32(imm8s); }
void instr32_E1(int32_t imm8s) { loope32(imm8s); }
void instr32_E2(int32_t imm8s) { loop32(imm8s); }
void instr32_E3(int32_t imm8s) { jcxz32(imm8s); }
void instr_E4(int32_t port) {
test_privileges_for_io(port, 1);
@ -1491,14 +1530,22 @@ void instr32_EA(int32_t new_ip, int32_t cs) {
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
}
void instr_EB(int32_t imm8) {
void instr16_EB(int32_t imm8) {
// jmp near
jmp_rel16(imm8);
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
}
void instr32_EB(int32_t imm8) {
// jmp near
instruction_pointer[0] = instruction_pointer[0] + imm8;
dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
}
void instr_EB_jit(int32_t imm8s) {
gen_fn1_const("instr_EB", 8, imm8s);
void instr16_EB_jit(int32_t imm8s) {
gen_fn1_const("instr16_EB", 10, imm8s);
}
void instr32_EB_jit(int32_t imm8s) {
gen_fn1_const("instr32_EB", 10, imm8s);
}
void instr_EC() {

View file

@ -112,14 +112,6 @@ void jmp_rel16(int32_t rel16)
*instruction_pointer = cs_offset + ((*instruction_pointer - cs_offset + rel16) & 0xFFFF);
}
void jmpcc8(bool condition, int32_t imm8)
{
if(condition)
{
*instruction_pointer += imm8;
}
}
void jmpcc16(bool condition, int32_t imm16)
{
if(condition)
@ -136,38 +128,15 @@ void jmpcc32(bool condition, int32_t imm32)
}
}
void loopne(int32_t imm8s)
{
if(decr_ecx_asize() && !getzf())
{
instruction_pointer[0] = instruction_pointer[0] + imm8s;
}
}
void loope(int32_t imm8s)
{
if(decr_ecx_asize() && getzf())
{
instruction_pointer[0] = instruction_pointer[0] + imm8s;
}
}
void loop(int32_t imm8s)
{
if(decr_ecx_asize())
{
instruction_pointer[0] = instruction_pointer[0] + imm8s;
}
}
void jcxz(int32_t imm8s)
{
if(get_reg_asize(ECX) == 0)
{
instruction_pointer[0] = instruction_pointer[0] + imm8s;
}
}
void loopne16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && !getzf(), imm8s); }
void loope16(int32_t imm8s) { jmpcc16(decr_ecx_asize() && getzf(), imm8s); }
void loop16(int32_t imm8s) { jmpcc16(decr_ecx_asize(), imm8s); }
void jcxz16(int32_t imm8s) { jmpcc16(get_reg_asize(ECX) == 0, imm8s); }
void loopne32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && !getzf(), imm8s); }
void loope32(int32_t imm8s) { jmpcc32(decr_ecx_asize() && getzf(), imm8s); }
void loop32(int32_t imm8s) { jmpcc32(decr_ecx_asize(), imm8s); }
void jcxz32(int32_t imm8s) { jmpcc32(get_reg_asize(ECX) == 0, imm8s); }
void cmovcc16(bool condition, int32_t value, int32_t r)
{

View file

@ -29,13 +29,17 @@ bool test_nl(void);
bool test_nle(void);
void jmp_rel16(int32_t rel16);
void jmpcc8(bool condition, int32_t imm8);
void jmpcc16(bool condition, int32_t imm16);
void jmpcc32(bool condition, int32_t imm32);
void loope(int32_t imm8s);
void loopne(int32_t imm8s);
void loop(int32_t imm8s);
void jcxz(int32_t imm8s);
void loope16(int32_t imm8s);
void loopne16(int32_t imm8s);
void loop16(int32_t imm8s);
void jcxz16(int32_t imm8s);
void loope32(int32_t imm8s);
void loopne32(int32_t imm8s);
void loop32(int32_t imm8s);
void jcxz32(int32_t imm8s);
void cmovcc16(bool condition, int32_t value, int32_t r);
void cmovcc32(bool condition, int32_t value, int32_t r);