fix push sreg only touches 16 bits of the stack dword

This commit is contained in:
Fabian 2022-11-22 18:01:11 -06:00
parent da0845189b
commit 651d0d83f9
5 changed files with 80 additions and 55 deletions

View file

@ -1529,6 +1529,57 @@ pub fn gen_push32(ctx: &mut JitContext, value_local: &WasmLocal) {
ctx.builder.free_local(new_sp_local);
}
pub fn gen_push32_sreg(ctx: &mut JitContext, reg: u32) {
gen_get_sreg(ctx, reg);
let value_local = ctx.builder.set_new_local();
if ctx.cpu.ssize_32() {
gen_get_reg32(ctx, regs::ESP);
}
else {
gen_get_reg16(ctx, regs::SP);
};
ctx.builder.const_i32(4);
ctx.builder.sub_i32();
let new_sp_local = if !ctx.cpu.ssize_32() || !ctx.cpu.has_flat_segmentation() {
let new_sp_local = ctx.builder.tee_new_local();
if !ctx.cpu.ssize_32() {
ctx.builder.const_i32(0xFFFF);
ctx.builder.and_i32();
}
if !ctx.cpu.has_flat_segmentation() {
gen_get_ss_offset(ctx);
ctx.builder.add_i32();
}
let sp_local = ctx.builder.set_new_local();
gen_safe_write16(ctx, &sp_local, &value_local);
ctx.builder.free_local(sp_local);
ctx.builder.get_local(&new_sp_local);
new_sp_local
}
else {
// short path: The address written to is equal to ESP/SP minus four
let new_sp_local = ctx.builder.tee_new_local();
gen_safe_write16(ctx, &new_sp_local, &value_local);
new_sp_local
};
if ctx.cpu.ssize_32() {
gen_set_reg32(ctx, regs::ESP);
}
else {
gen_set_reg16(ctx, regs::SP);
};
ctx.builder.free_local(new_sp_local);
ctx.builder.free_local(value_local);
}
pub fn gen_get_real_eip(ctx: &mut JitContext) {
gen_get_eip(ctx.builder);
ctx.builder.const_i32(!0xFFF);

View file

@ -58,9 +58,7 @@ pub unsafe fn instr32_05(imm32: i32) { write_reg32(EAX, add32(read_reg32(EAX), i
pub unsafe fn instr16_06() {
return_on_pagefault!(push16(*sreg.offset(ES as isize) as i32));
}
pub unsafe fn instr32_06() {
return_on_pagefault!(push32(*sreg.offset(ES as isize) as i32));
}
pub unsafe fn instr32_06() { return_on_pagefault!(push32_sreg(ES)) }
#[no_mangle]
pub unsafe fn instr16_07() {
@ -123,9 +121,7 @@ pub unsafe fn instr32_0D(imm32: i32) { write_reg32(EAX, or32(read_reg32(EAX), im
pub unsafe fn instr16_0E() {
return_on_pagefault!(push16(*sreg.offset(CS as isize) as i32));
}
pub unsafe fn instr32_0E() {
return_on_pagefault!(push32(*sreg.offset(CS as isize) as i32));
}
pub unsafe fn instr32_0E() { return_on_pagefault!(push32_sreg(CS)) }
pub unsafe fn instr16_0F() { run_instruction0f_16(return_on_pagefault!(read_imm8())); }
pub unsafe fn instr32_0F() { run_instruction0f_32(return_on_pagefault!(read_imm8())); }
@ -176,9 +172,7 @@ pub unsafe fn instr32_15(imm32: i32) { write_reg32(EAX, adc32(read_reg32(EAX), i
pub unsafe fn instr16_16() {
return_on_pagefault!(push16(*sreg.offset(SS as isize) as i32));
}
pub unsafe fn instr32_16() {
return_on_pagefault!(push32(*sreg.offset(SS as isize) as i32));
}
pub unsafe fn instr32_16() { return_on_pagefault!(push32_sreg(SS)) }
#[no_mangle]
pub unsafe fn instr16_17() {
@ -244,9 +238,7 @@ pub unsafe fn instr32_1D(imm32: i32) { write_reg32(EAX, sbb32(read_reg32(EAX), i
pub unsafe fn instr16_1E() {
return_on_pagefault!(push16(*sreg.offset(DS as isize) as i32));
}
pub unsafe fn instr32_1E() {
return_on_pagefault!(push32(*sreg.offset(DS as isize) as i32));
}
pub unsafe fn instr32_1E() { return_on_pagefault!(push32_sreg(DS)) }
#[no_mangle]
pub unsafe fn instr16_1F() {

View file

@ -27,7 +27,7 @@ use cpu::fpu::fpu_set_tag_word;
use cpu::global_pointers::*;
use cpu::misc_instr::{
adjust_stack_reg, bswap, cmovcc16, cmovcc32, fxrstor, fxsave, get_stack_pointer, jmpcc16,
jmpcc32, push16, push32, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, test_o,
jmpcc32, push16, push32_sreg, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, test_o,
test_p, test_s, test_z,
};
use cpu::misc_instr::{lar, lsl, verr, verw};
@ -3075,9 +3075,7 @@ pub unsafe fn instr_0F9F_mem(addr: i32, _: i32) { setcc_mem(!test_le(), addr); }
pub unsafe fn instr16_0FA0() {
return_on_pagefault!(push16(*sreg.offset(FS as isize) as i32));
}
pub unsafe fn instr32_0FA0() {
return_on_pagefault!(push32(*sreg.offset(FS as isize) as i32));
}
pub unsafe fn instr32_0FA0() { return_on_pagefault!(push32_sreg(FS)) }
#[no_mangle]
pub unsafe fn instr16_0FA1() {
if !switch_seg(FS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) {
@ -3296,9 +3294,7 @@ pub unsafe fn instr_0FA7() { undefined_instruction(); }
pub unsafe fn instr16_0FA8() {
return_on_pagefault!(push16(*sreg.offset(GS as isize) as i32));
}
pub unsafe fn instr32_0FA8() {
return_on_pagefault!(push32(*sreg.offset(GS as isize) as i32));
}
pub unsafe fn instr32_0FA8() { return_on_pagefault!(push32_sreg(GS)) }
#[no_mangle]
pub unsafe fn instr16_0FA9() {
if !switch_seg(GS, return_on_pagefault!(safe_read16(get_stack_pointer(0)))) {

View file

@ -186,6 +186,22 @@ pub unsafe fn push32_ss32_mem(addr: i32) -> OrPageFault<()> { push32_ss32(safe_r
pub unsafe fn push32(imm32: i32) -> OrPageFault<()> {
if *stack_size_32 { push32_ss32(imm32) } else { push32_ss16(imm32) }
}
pub unsafe fn push32_sreg(i: i32) -> OrPageFault<()> {
// you can't make this up ...
if *stack_size_32 {
let new_esp = read_reg32(ESP) - 4;
safe_write16(get_seg_ss() + new_esp, *sreg.offset(i as isize) as i32)?;
write_reg32(ESP, new_esp);
}
else {
let new_sp = read_reg16(SP) - 4 & 0xFFFF;
safe_write16(get_seg_ss() + new_sp, *sreg.offset(i as isize) as i32)?;
write_reg16(SP, new_sp);
}
Ok(())
}
pub unsafe fn pop16() -> OrPageFault<i32> {
if *stack_size_32 { pop16_ss32() } else { pop16_ss16() }
}

View file

@ -2507,12 +2507,7 @@ pub fn instr16_06_jit(ctx: &mut JitContext) {
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_06_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::ES);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_06_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::ES) }
pub fn instr16_0E_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::CS);
@ -2520,12 +2515,7 @@ pub fn instr16_0E_jit(ctx: &mut JitContext) {
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0E_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::CS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0E_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::CS) }
pub fn instr16_16_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::SS);
@ -2533,12 +2523,7 @@ pub fn instr16_16_jit(ctx: &mut JitContext) {
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_16_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::SS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_16_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::SS) }
pub fn instr16_1E_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::DS);
@ -2546,12 +2531,7 @@ pub fn instr16_1E_jit(ctx: &mut JitContext) {
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_1E_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::DS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_1E_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::DS) }
pub fn instr16_40_jit(ctx: &mut JitContext) { gen_inc16_r(ctx, AX); }
pub fn instr32_40_jit(ctx: &mut JitContext) { gen_inc32_r(ctx, EAX); }
@ -6858,24 +6838,14 @@ pub fn instr16_0FA0_jit(ctx: &mut JitContext) {
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0FA0_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::FS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0FA0_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::FS) }
pub fn instr16_0FA8_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::GS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push16(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0FA8_jit(ctx: &mut JitContext) {
codegen::gen_get_sreg(ctx, regs::GS);
let sreg = ctx.builder.set_new_local();
codegen::gen_push32(ctx, &sreg);
ctx.builder.free_local(sreg);
}
pub fn instr32_0FA8_jit(ctx: &mut JitContext) { codegen::gen_push32_sreg(ctx, regs::GS) }
pub fn instr16_0FA3_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_bt(