v86/src/rust/cpu/instruction_helpers.rs
2020-12-31 19:14:32 -06:00

90 lines
3.6 KiB
Rust

macro_rules! SAFE_READ_WRITE8 {
($value:ident, $addr:expr, $instruction:expr) => {{
use cpu::cpu::translate_address_write_and_can_skip_dirty;
use cpu::memory;
use page::Page;
let (phys_addr, can_skip_dirty_page) =
return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
let $value = memory::read8(phys_addr);
let value = $instruction;
if memory::in_mapped_range(phys_addr) {
memory::mmap_write8(phys_addr, value);
}
else {
if !can_skip_dirty_page {
::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
}
else {
dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
}
memory::write8_no_mmap_or_dirty_check(phys_addr, value);
}
}};
}
macro_rules! SAFE_READ_WRITE16 {
($value:ident, $addr:expr, $instruction:expr) => {{
use cpu::cpu::{
translate_address_write_and_can_skip_dirty, virt_boundary_read16, virt_boundary_write16,
};
use cpu::memory;
use page::Page;
let (phys_addr, can_skip_dirty_page) =
return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
if phys_addr & 0xFFF == 0xFFF {
let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 1));
let $value = virt_boundary_read16(phys_addr, phys_addr_high);
virt_boundary_write16(phys_addr, phys_addr_high, $instruction);
}
else {
let $value = memory::read16(phys_addr);
let value = $instruction;
if memory::in_mapped_range(phys_addr) {
memory::mmap_write16(phys_addr, value);
}
else {
if !can_skip_dirty_page {
::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
}
else {
dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
}
memory::write16_no_mmap_or_dirty_check(phys_addr, value);
};
}
}};
}
macro_rules! SAFE_READ_WRITE32 {
($value:ident, $addr:expr, $instruction:expr) => {{
use cpu::cpu::{
translate_address_write_and_can_skip_dirty, virt_boundary_read32s,
virt_boundary_write32,
};
use cpu::memory;
use page::Page;
let (phys_addr, can_skip_dirty_page) =
return_on_pagefault!(translate_address_write_and_can_skip_dirty($addr));
if phys_addr & 0xFFF >= 0xFFD {
let phys_addr_high = return_on_pagefault!(translate_address_write($addr + 3 & !3));
let phys_addr_high = phys_addr_high | ($addr as u32) + 3 & 3;
let $value = virt_boundary_read32s(phys_addr, phys_addr_high);
virt_boundary_write32(phys_addr, phys_addr_high, $instruction);
}
else {
let $value = memory::read32s(phys_addr);
let value = $instruction;
if memory::in_mapped_range(phys_addr) {
memory::mmap_write32(phys_addr, value);
}
else {
if !can_skip_dirty_page {
::jit::jit_dirty_page(::jit::get_jit_state(), Page::page_of(phys_addr));
}
else {
dbg_assert!(!::jit::jit_page_has_code(Page::page_of(phys_addr as u32)));
}
memory::write32_no_mmap_or_dirty_check(phys_addr, value);
};
}
}};
}